Sobre serialização, desserialização, rede e microservice
10 respostas
Ronny_Peterson
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?
O que se passa nessa comunicação? Dependendo, você poderia usar MQTT.
confuso
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.
Ronny_Peterson
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=newSocket("privacy",9002);outputPrivacy=newObjectOutputStream(socketPrivacy.getOutputStream());inputPrivacy=newObjectInputStream(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.
confuso
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 ===================ObjectOutputStreamoutputPrivacy=newObjectOutputStream(newBufferedOutputStream(socketPrivacy.getOutputStream()));outputPrivacy.writeObject(result);outputPrivacy.flush();...// =================== RECEBENDO OS DADOS ===================ObjectInputStreaminputPrivacy=newObjectInputStream(newBufferedInputStream(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.
Ronny_Peterson
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?
Ronny_Peterson
Testei, e simplesmente travou a execução. Alguma ideia do porquê aconteceu isso?
confuso
Como assim travou? Não acontece nada sem dar nenhum erro, nenhuma exception?
confuso
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.
Ronny_Peterson
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.
rmendes08
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.