Ich habe einen Dienst, der Nachrichten mit einer ziemlich hohen Rate überträgt.
Derzeit wird es von akka-tcp bereitgestellt und sendet 3,5 Millionen Nachrichten pro Minute. Ich beschloss, grpc auszuprobieren. Leider führte dies zu einem viel geringeren Durchsatz: ~ 500.000 Nachrichten pro Minute und noch weniger.
Könnten Sie bitte empfehlen, wie Sie es optimieren können?
Mein Setup
Hardware : 32 Kerne, 24 GB Heap.
grpc version : 1.25.0
Nachrichtenformat und Endpunkt
Nachricht ist im Grunde ein binärer Blob. Der Client überträgt 100K - 1M und mehr Nachrichten in dieselbe Anforderung (asynchron), der Server antwortet mit nichts, der Client verwendet einen No-Op-Beobachter
service MyService {
rpc send (stream MyMessage) returns (stream DummyResponse);
}
message MyMessage {
int64 someField = 1;
bytes payload = 2; //not huge
}
message DummyResponse {
}
Probleme: Die Nachrichtenrate ist im Vergleich zur akka-Implementierung niedrig. Ich beobachte eine geringe CPU-Auslastung, daher vermute ich, dass der grpc-Aufruf tatsächlich intern blockiert, obwohl etwas anderes angegeben ist. BerufungonNext()
kehrt zwar nicht sofort zurück, aber es liegt auch GC auf dem Tisch.
Ich habe versucht, mehr Absender zu erzeugen, um dieses Problem zu beheben, aber keine großen Verbesserungen erzielt.
Meine Ergebnisse Grpc weist jeder Nachricht bei der Serialisierung tatsächlich einen 8-KB-Byte-Puffer zu. Siehe die Stapelverfolgung:
java.lang.Thread.State: BLOCKED (auf dem Objektmonitor) unter com.google.common.io.ByteStreams.createBuffer (ByteStreams.java:58) unter com.google.common.io.ByteStreams.copy (ByteStreams.java: 105) unter io.grpc.internal.MessageFramer.writeToOutputStream (MessageFramer.java:274) unter io.grpc.internal.MessageFramer.writeKnownLengthUncompressed (MessageFramer.java:230) unter io.grpc : 168) unter io.grpc.internal.MessageFramer.writePayload (MessageFramer.java:141) unter io.grpc.internal.AbstractStream.writeMessage (AbstractStream.java:53) unter io.grpc.internal.ForwardingClientStream.writeM. java: 37) bei io.grpc.internal.DelayedStream.writeMessage (DelayedStream.java:252) bei io.grpc.internal.ClientCallImpl.sendMessageInternal (ClientCallImpl.java:473) unter io.grpc.internal.ClientCallImpl.sendMessage (ClientCallImpl.java:457) unter io.grpc.ForwardingClientCall.sendMessage (ForwardingClientCall.allCall.sendMallage) (ForwardingClientCall.java:37) unter io.grpc.stub.ClientCalls $ CallToStreamObserverAdapter.onNext (ClientCalls.java:346)
Jede Hilfe mit Best Practices beim Aufbau von Grpc-Clients mit hohem Durchsatz wird geschätzt.
scalapb
. Wahrscheinlich war dieser Stacktrace tatsächlich von Scalapb-generiertem Code. Ich habe alles entfernt, was mit Scalapb zu tun hat, aber es hat nicht viel zur Leistung beigetragen.