我有一项以相当高的速率传输消息的服务。
目前它由 akka-tcp 提供服务,每分钟生成 350 万条消息。我决定尝试一下 grpc。
不幸的是,它导致吞吐量小得多:每分钟约 500k 条消息,甚至更少。
您能推荐一下如何优化吗?
My setup
Hardware: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:BLOCKED(在对象监视器上)
在 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.java:37)
在 io.grpc.internal.DelayedStream.writeMessage(DelayedStream.java:252)
在io.grpc.internal.ClientCallImpl.sendMessageInternal(ClientCallImpl.java:473)
在io.grpc.internal.ClientCallImpl.sendMessage(ClientCallImpl.java:457)
在 io.grpc.ForwardingClientCall.sendMessage(ForwardingClientCall.java:37)
在 io.grpc.ForwardingClientCall.sendMessage(ForwardingClientCall.java:37)
在 io.grpc.stub.ClientCalls$CallToStreamObserverAdapter.onNext(ClientCalls.java:346)
任何关于构建高吞吐量 grpc 客户端最佳实践的帮助都值得赞赏。
我通过创建几个解决了这个问题ManagedChannel
每个目的地的实例。尽管有文章说ManagedChannel
本身可以产生足够的连接,因此一个实例就足够了,但在我的情况下并非如此。
性能与 akka-tcp 实现相当。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)