Saya memiliki layanan yang mentransfer pesan pada tingkat yang cukup tinggi.
Saat ini dilayani oleh akka-tcp dan menghasilkan 3,5 juta pesan per menit. Saya memutuskan untuk mencoba grpc. Sayangnya itu menghasilkan throughput yang jauh lebih kecil: ~ 500rb pesan per menit bahkan lebih sedikit.
Bisakah Anda merekomendasikan cara mengoptimalkannya?
Pengaturan saya
Perangkat keras : 32 core, tumpukan 24Gb.
versi grpc : 1.25.0
Format pesan dan titik akhir
Pesan pada dasarnya adalah gumpalan biner. Klien melakukan stream 100K - 1M dan lebih banyak pesan ke permintaan yang sama (asinkron), server tidak menanggapi apa pun, klien menggunakan pengamat no-op
service MyService {
rpc send (stream MyMessage) returns (stream DummyResponse);
}
message MyMessage {
int64 someField = 1;
bytes payload = 2; //not huge
}
message DummyResponse {
}
Masalah: Tingkat pesan rendah dibandingkan dengan implementasi akka. Saya mengamati penggunaan CPU yang rendah jadi saya curiga bahwa panggilan grpc sebenarnya memblokir secara internal meskipun dikatakan sebaliknya. Memanggil onNext()
memang tidak segera kembali tetapi ada juga GC di atas meja.
Saya mencoba menelurkan lebih banyak pengirim untuk mengurangi masalah ini tetapi tidak mendapatkan banyak perbaikan.
Temuan saya, Grpc, sebenarnya mengalokasikan buffer byte 8KB pada setiap pesan ketika membuat serialisasi. Lihat stacktrace:
java.lang.Thread.State: BLOCKED (pada objek monitor) di com.google.common.io.ByteStreams.createBuffer (ByteStreams.java:58) di com.google.common.io.ByteStreams.copy (ByteStreams.java: 105) di io.grpc.internal.MessageFramer.writeToOutputStream (MessageFramer.java:74) di io.grpc.internal.MessageFramer.writeKnownLengthUncompressed (MessageFramer.java.w30) di io.grpc.internal.MessageFramer.writeUnter : 168) di io.grpc.internal.MessageFramer.writePayload (MessageFramer.java:141) di io.grpc.internal.AbstrakStream.writeMessage (AbstractStream.java:53) di io.grpc.internal.ForwardingClientStream.writeMessage (ForwardingClientStream. java: 37) di io.grpc.internal.DelayedStream.writeMessage (DelayedStream.java:252) di io.grpc.internal.ClientCallImpl.sendMessageInternal (ClientCallImpl.java:473) di io.grpc.internal.ClientCallImpl.sendMessage (ClientCallImpl.java:457) di io.grpc.ForwardingClientCall.sendMessage (forwardingClient.call. (ForwardingClientCall.java:37) di io.grpc.stub.ClientCalls $ CallToStreamObserverAdapter.onNext (ClientCalls.java:346)
Setiap bantuan dengan praktik terbaik untuk membangun klien grpc throughput tinggi dihargai.
scalapb
. Mungkin stacktrace ini memang dari ke kode yang dihasilkan scalapb. Saya menghapus semua yang berhubungan dengan scalapb tetapi itu tidak membantu banyak kinerja.