메시지를 매우 빠른 속도로 전송하는 서비스가 있습니다.
현재 akka-tcp에서 제공하며 분당 3.5M 메시지를 생성합니다. 나는 grpc를 시도하기로 결정했다. 불행히도 처리량은 훨씬 작습니다. 분당 ~ 55,000 개의 메시지가 훨씬 적습니다.
최적화 방법을 추천 해 주시겠습니까?
내 설정
하드웨어 : 32 코어, 24Gb 힙.
grpc 버전 : 1.25.0
메시지 형식 및 엔드 포인트
메시지는 기본적으로 이진 얼룩입니다. 클라이언트는 100K-1M 이상의 메시지를 동일한 요청 (비동기 적으로)으로 스트리밍하고 서버가 아무 것도 응답하지 않으며 클라이언트가 no-op 관찰자를 사용합니다.
service MyService {
rpc send (stream MyMessage) returns (stream DummyResponse);
}
message MyMessage {
int64 someField = 1;
bytes payload = 2; //not huge
}
message DummyResponse {
}
문제점 : Akka 구현에 비해 메시지 전송률이 낮습니다. CPU 사용률이 낮으므로 grpc 호출이 실제로는 그렇지 않더라도 실제로 내부적으로 차단되고 있다고 생각합니다. onNext()
실제로 전화하면 즉시 반환되지 않지만 테이블에 GC도 있습니다.
이 문제를 완화하기 위해 더 많은 발신자를 만들려고했지만 크게 개선되지 않았습니다.
내 연구 결과 Grpc는 직렬화 할 때 실제로 각 메시지에 8KB 바이트 버퍼를 할당합니다. 스택 추적을 참조하십시오.
java.lang.Thread.State : com.google.common.io.ByteStreams.createBuffer (ByteStreams.java:58) com.google.common.io.ByteStreams.copy (ByteStreams.java : 차단됨 (객체 모니터) 105) io.grpc.internal.MessageFramer.writeToOutputStream (MessageFramer.java:274) io.grpc.internal.MessageFramer.writeKnownLengthUncompressed (MessageFramer.java:230) io.grpc.internal.MessageFramer.writeUncompressed (MessageFramer.java) : 168) io.grpc.internal.MessageFramer.writePayload (MessageFramer.java:141) io.grpc.internal.AbstractStream.writeMessage (AbstractStream.java:53) io.grpc.internal.ForwardingClientStream.writeMessage (ForwardingClientStream. io.grpc.internal의 io.grpc.internal.DelayedStream.writeMessage (DelayedStream.java:252)의 java : 37)io.grpc.internal.ClientCallImpl.sendMessage (ClientCallImpl.java:457)의 io.grpc.ForwardingClientCall.sendMessage (ForwardingClientCall.java:37)의 io.grpc.ForwardingClientCall.java:37의 ClientCallImpl.sendMessageInternal (ClientCallImpl.java:473) (io.grpc.stub.ClientCalls $ CallToStreamObserverAdapter.onNext (ClientCalls.java:346)의 (ForwardingClientCall.java:37)
처리량이 많은 grpc 클라이언트를 구축하는 모범 사례에 대한 도움을 주시면 감사하겠습니다.
scalapb
. 아마도이 스택 트레이스는 스칼라 프에서 생성 된 코드 일 것입니다. scalapb와 관련된 모든 것을 제거했지만 많은 wrt 성능에 도움이되지 않았습니다.