我有一项可以以很高的速率传输邮件的服务。
目前,它由akka-tcp提供服务,每分钟发送350万条消息。我决定尝试一下grpc。不幸的是,它导致吞吐量大大降低:每分钟约50万条消息甚至更低。
您能推荐如何优化它吗?
我的设定
硬件:32核,24Gb堆。
grpc版本:1.25.0
消息格式和端点
消息基本上是一个二进制blob。客户端将100K-1M和更多消息流传输到同一请求中(异步),服务器不响应任何内容,客户端使用无操作观察者
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.copy(ByteStreams.java:com.google.common.io.ByteStreams.createBuffer(ByteStreams.java:58)处处于阻塞状态(在对象监视器上): 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。 java:37)位于io.grpc.internal.DelayedStream.writeMessage(DelayedStream.java:252)位于io.grpc.internal。io.grpc.internal.ClientCallImpl.sendMessage(ClientCallImpl.java:457)的io.grpc.ForwardingClientCall.sendMessage(ForwardingClientCall.java:37)的io.grpc.internal.ClientCallImpl.sendMessageInternal(ClientCallImpl.java:473)io.grpc.ForwardingClientCall.sendMessage的(ForwardingClientCall.java:37)位于io.grpc.stub.ClientCalls $ CallToStreamObserverAdapter.onNext(ClientCalls.java:346)
对于构建高吞吐量grpc客户的最佳做法的任何帮助,均表示赞赏。
scalapb
。可能此堆栈跟踪确实是从scalapb生成的代码。我删除了与scalapb相关的所有内容,但对性能没有太大帮助。