Tengo un servicio que transfiere mensajes a una velocidad bastante alta.
Actualmente es atendido por akka-tcp y genera 3,5 millones de mensajes por minuto. Decidí probar grpc. Desafortunadamente, resultó en un rendimiento mucho menor: ~ 500k mensajes por minuto e incluso menos.
¿Podría recomendarme cómo optimizarlo?
Mi configuración
Hardware : 32 núcleos, montón de 24 Gb.
versión de grpc: 1.25.0
Formato del mensaje y punto final
El mensaje es básicamente un blob binario. El cliente transmite 100K - 1M y más mensajes en la misma solicitud (asíncronamente), el servidor no responde con nada, el cliente usa un observador no operativo
service MyService {
rpc send (stream MyMessage) returns (stream DummyResponse);
}
message MyMessage {
int64 someField = 1;
bytes payload = 2; //not huge
}
message DummyResponse {
}
Problemas: la tasa de mensajes es baja en comparación con la implementación de akka. Observo un bajo uso de la CPU, por lo que sospecho que la llamada grpc en realidad está bloqueando internamente a pesar de que dice lo contrario. Las llamadas onNext()
no vuelven de inmediato, pero también hay GC sobre la mesa.
Traté de generar más remitentes para mitigar este problema, pero no obtuve muchas mejoras.
Mis hallazgos Grpc en realidad asigna un búfer de bytes de 8 KB en cada mensaje cuando lo serializa. Ver el stacktrace:
java.lang.Thread.State: BLOCKED (en el monitor de objetos) en com.google.common.io.ByteStreams.createBuffer (ByteStreams.java:58) en com.google.common.io.ByteStreams.copy (ByteStreams.java: 105) en io.grpc.internal.MessageFramer.writeToOutputStream (MessageFramer.java:274) en io.grpc.internal.MessageFramer.writeKnownLengthUncompressed (MessageFramer.java:230) en io.grpc.internal.MessageFramer.wpressed.MessageFramer.vader. : 168) en io.grpc.internal.MessageFramer.writePayload (MessageFramer.java:141) en io.grpc.internal.AbstractStream.writeMessage (AbstractStream.java:53) en io.grpc.internal.ForwardingClientStream.writeMessageS (ForwardingClientStream.writeMessageS. java: 37) en io.grpc.internal.DelayedStream.writeMessage (DelayedStream.java:252) en io.grpc.internal.ClientCallImpl.sendMessageInternal (ClientCallImpl.java:473) en io.grpc.internal.ClientCallImpl.sendMessage (ClientCallImpl.java:457) en io.grpc.ForwardingClientCall.sendMessage (ForwardingClientCall.javagr37) en io.gr. (ForwardingClientCall.java:37) en io.grpc.stub.ClientCalls $ CallToStreamObserverAdapter.onNext (ClientCalls.java:346)
Se agradece cualquier ayuda con las mejores prácticas en la construcción de clientes grpc de alto rendimiento.
scalapb
. Probablemente este stacktrace fue de hecho al código generado por scalapb. Eliminé todo lo relacionado con scalapb pero no ayudó mucho el rendimiento de wrt.