J'ai un service qui transfère des messages à un taux assez élevé.
Actuellement, il est desservi par akka-tcp et génère 3,5 millions de messages par minute. J'ai décidé d'essayer grpc. Malheureusement, cela a entraîné un débit beaucoup plus faible: ~ 500 000 messages par minute, encore moins.
Pourriez-vous s'il vous plaît recommander comment l'optimiser?
Ma configuration
Matériel : 32 cœurs, tas de 24 Go.
version grpc: 1.25.0
Format de message et point de terminaison
Le message est essentiellement un blob binaire. Le client diffuse de 100 000 à 1 million de messages et plus dans la même demande (de manière asynchrone), le serveur ne répond avec rien, le client utilise un observateur sans opération
service MyService {
rpc send (stream MyMessage) returns (stream DummyResponse);
}
message MyMessage {
int64 someField = 1;
bytes payload = 2; //not huge
}
message DummyResponse {
}
Problèmes: le taux de messages est faible par rapport à la mise en œuvre d'Akka. J'observe une faible utilisation du processeur, donc je soupçonne que l'appel grpc se bloque réellement en interne malgré le contraire. L'appel en onNext()
effet ne revient pas immédiatement mais il y a aussi du GC sur la table.
J'ai essayé de générer plus d'expéditeurs pour atténuer ce problème, mais je n'ai pas obtenu beaucoup d'amélioration.
Mes résultats Grpc alloue en fait un tampon de 8 Ko sur chaque message lors de sa sérialisation. Voir le stacktrace:
java.lang.Thread.State: BLOCKED (on object monitor) sur com.google.common.io.ByteStreams.createBuffer (ByteStreams.java:58) sur com.google.common.io.ByteStreams.copy (ByteStreams.java: 105) sur io.grpc.internal.MessageFramer.writeToOutputStream (MessageFramer.java:274) sur io.grpc.internal.MessageFramer.writeKnownLengthUncompressed (MessageFramer.java:230) sur io.grpc.internal.MessageFramer.compresseur : 168) sur io.grpc.internal.MessageFramer.writePayload (MessageFramer.java:141) sur io.grpc.internal.AbstractStream.writeMessage (AbstractStream.java:53) sur io.grpc.internal.ForwardingClientStream.writeMessage (Forwarding). java: 37) sur io.grpc.internal.DelayedStream.writeMessage (DelayedStream.java:252) sur io.grpc.internal.ClientCallImpl.sendMessageInternal (ClientCallImpl.java:473) à io.grpc.internal.ClientCallImpl.sendMessage (ClientCallImpl.java:457) à io.grpc.ForwardingClientCall.sendMessage (ForwardingClientCall.java:Client.For.Cost.For.Client.Force.For.ClientCompendio.ForientiFormage.Forward.ClientCompendors.Forward.ClientCall.js (ForwardingClientCall.java:37) sur io.grpc.stub.ClientCalls $ CallToStreamObserverAdapter.onNext (ClientCalls.java:346)
Toute aide avec les meilleures pratiques sur la construction de clients grpc à haut débit appréciée.
scalapb
. Cette trace de pile provenait probablement du code généré par scalapb. J'ai supprimé tout ce qui concerne le scalapb, mais cela n'a pas beaucoup amélioré les performances.