Mam usługę, która przesyła wiadomości z dość wysoką prędkością.
Obecnie jest obsługiwany przez akka-tcp i wytwarza 3,5 miliona wiadomości na minutę. Postanowiłem dać grpc szansę. Niestety spowodowało to znacznie mniejszą przepustowość: ~ 500 000 wiadomości na minutę, a nawet mniej.
Czy mógłbyś polecić jak to zoptymalizować?
Moja konfiguracja
Sprzęt komputerowy : 32 rdzenie, stos 24 Gb.
wersja grpc grpc: 1.25.0
Format wiadomości i punkt końcowy
Wiadomość to w zasadzie binarny obiekt blob. Klient przesyła strumieniowo 100K - 1M i więcej wiadomości do tego samego żądania (asynchronicznie), serwer nic nie odpowiada, klient używa obserwatora bez operacji
service MyService {
rpc send (stream MyMessage) returns (stream DummyResponse);
}
message MyMessage {
int64 someField = 1;
bytes payload = 2; //not huge
}
message DummyResponse {
}
Problemy: Szybkość wiadomości jest niska w porównaniu do implementacji akka. Obserwuję niskie zużycie procesora, więc podejrzewam, że połączenie grpc faktycznie blokuje wewnętrznie, mimo że mówi inaczej. Calling onNext()
rzeczywiście nie wraca natychmiast, ale na stole jest także GC.
Próbowałem odrodzić więcej nadawców, aby złagodzić ten problem, ale nie uzyskałem dużej poprawy.
Moje ustalenia Grpc faktycznie przydziela bufor bajtów 8 KB na każdą wiadomość, gdy jest ona serializowana. Zobacz stacktrace:
java.lang.Thread.State: BLOCKED (na monitorze obiektów) w com.google.common.io.ByteStreams.createBuffer (ByteStreams.java:58) w com.google.common.io.ByteStreams.copy (ByteStreams.java: 105) w io.grpc.internal.MessageFramer.writeToOutputStream (MessageFramer.java:274) w io.grpc.internal.MessageFramer.writeKnownLengthUncompressed (MessageFramer.java:230) w io.grpc.internal.MessageFramer.write : 168) w io.grpc.internal.MessageFramer.writePayload (MessageFramer.java:141) w io.grpc.internal.AbstractStream.writeMessage (AbstractStream.java:53) w io.grpc.internal.ForwardingClientStream.reamiteream (ForwardingClientStream. java: 37) w io.grpc.internal.DelayedStream.writeMessage (DelayedStream.java:252) w io.grpc.internal.ClientCallImpl.sendMessageInternal (ClientCallImpl.java:473) pod adresem io.grpc.internal.ClientCallImpl.sendMessage (ClientCallImpl.java:457) pod adresem io.grpc.ForwardingClientCall.sendMessage (ForwardingClientCall.orva.grva37) (ForwardingClientCall.java:37) w io.grpc.stub.ClientCalls $ CallToStreamObserverAdapter.onNext (ClientCalls.java:346)
Doceniono wszelką pomoc dotyczącą najlepszych praktyk w budowaniu wysokoprzepustowych klientów grpc.
scalapb
. Prawdopodobnie ten stacktrace rzeczywiście był od kodu generowanego przez scalapb. Usunąłem wszystko związane ze skalapb, ale nie pomogło to w dużej wydajności wrt.