Sobre serialização, desserialização, rede e microservice

Olá,

Desenvolvi uma aplicação que roda em dois serviços que estão em máquinas diferentes. A comunicação é feita via socket utilizado ObjectInputStream e ObjectOutputStream. Nos testes que fiz, o tempo de comunicação e transporte dos dados entre as máquinas consomem um tempo significativo do tempo total de execução e pior, testei em rede de 100 MB e rede Giga, o tempo de comunicação é o mesmo.
Já li que a latência, a serialização e desserialização são desvantagens na arquitetura. Pergunto: Existe alguma forma de melhorar o desempenho de comunicação entre as máquinas e reduzir o tempo de transferência dos dados? Por que não tem diferença entre desempenho na rede MB e Giga? Por acaso o ObjectInputStream já envia via rede conforme serializa?

Desde já Agradeço,

Ronny

O que se passa nessa comunicação? Dependendo, você poderia usar MQTT.

Só com essas informações não dá pra ter certeza a causa da lentidão, mas se a mensagem transportada for relativamente simples dá pra usar o DataInputStream e DataOutputStream, em que você transporta os valores dos objetos em vez do objeto java inteiro. Pode melhorar em até 6 vezes a performance comparado com usar apenas ObjectInputStream/ObjectOutputStream.

Estou transferindo resultado de uma consulta em banco de dados para tratar em outra máquina por outro service. Mais de 40.000 registros com tamanho de ~130 MiB, em geral será um grande volume de dados. Em um serviço executo a consulta no banco, armazeno o resultado em um ArrayList e envio essa Lista para outra máquina, na qual outro serviço anonimiza os dados:

socketPrivacy = new Socket("privacy",9002);		
outputPrivacy = new ObjectOutputStream(socketPrivacy.getOutputStream());
inputPrivacy = new ObjectInputStream(socketPrivacy.getInputStream());
System.out.println("Sending Result to Apply Privacy....");
outputPrivacy.writeObject(result);
outputPrivacy.writeObject(params.get(2));
outputPrivacy.writeUTF(user);
outputPrivacy.writeUTF(sql);
outputPrivacy.flush();				            			

System.out.println("Receiving Result of Privacy Service....");				            			

result = concatList((ArrayList<String[]>) inputPrivacy.readObject(), (ArrayList<String[]>) resultSQL.get(1));
message = (String) inputPrivacy.readUTF();

Com esse cenário, posso usar o DataInputStream e DataOutputStream? O MQTT se aplicaria (apesar de não conhecer esse protocolo)?

Desde já agradeço a ajuda.

Ah, então seria mais complicado usar só DataInputStream.

Usar BefferedOutputStream com ObjectOutputStream melhora a performance significativamente também, só não sei vai ser o suficiente pro seu caso.

// =================== ENVIANDO OS DADOS ===================
ObjectOutputStream outputPrivacy = new ObjectOutputStream(new BufferedOutputStream(socketPrivacy.getOutputStream()));
outputPrivacy.writeObject(result);
outputPrivacy.flush();

...

// =================== RECEBENDO OS DADOS ===================
ObjectInputStream inputPrivacy = new ObjectInputStream(new BufferedInputStream(socketPrivacy.getInputStream()));
ArrayList<String[]> result = (ArrayList<String[]>) inputPrivacy.readObject();

Mas a forma ideal de transportar dados entre serviços diferentes da mesma aplicação geralmente é por protocolos que segue o padrão publisher/subscriber como AMQP, SQS da Amazon, Kafka, acho que o MQTT também faz algo parecido.

Agradeço a ajuda. Vou incluir o BufferedOutputStream e ver se melhora o desempenho. Sobre os protocolos, como funciona o Kafka? Ele é uma plataforma que tenho que instalar e configurar em outra máquina ou um biblioteca que adiciona às minhas aplicações Java?

Testei, e simplesmente travou a execução. Alguma ideia do porquê aconteceu isso?

Como assim travou? Não acontece nada sem dar nenhum erro, nenhuma exception?

O Kafka é uma plataforma que você sobe e configura em alguma máquina (ou em várias) da mesma forma que você instala e configura um banco de dados separadamente da aplicação. Aí a sua aplicação vai enviar e ouvir mensagens do Kafka. Existem bibliotecas em várias linguagens que facilita acessar, mandar mensagens, configurar um cluster Kafka.

Você pode ouvir vários termos como publisher/subscriber, filas, message broker, mensageria, etc. Cada um talvez tenha um significado levemente diferente, mas no geral todos significa você centralizar o envio/recebimento de mensagens num lugar pra permitir troca de mensagens/dados entre vários serviços da aplicação.

Obrigado novamente pela informação sobre Kafka, vou estudar melhor. Achei muito interessante. Sobre a aplicação, não dá erro, é como se entrasse em um loop infinito.

Pode ser um deadlock. As threads devem estar bloqueadas esperando o fim da conexão, mas como nenhum dos lados encerra, a conexão fica “pendurada” e as respectivas threads ficam bloqueadas, esperando a troca de mais dados. Nesses casos, é interessante que você defina algum tipo de “terminandor” da transmissão, para que quando o outro lado receber esse “terminador” a outra ponta encerre a conexão.