java - GRPC:用 Java/Scala 制作高吞吐量客户端
问题描述
我有一项以相当高的速率传输消息的服务。
目前它由 akka-tcp 提供服务,每分钟发送 350 万条消息。我决定试一试grpc。不幸的是,它导致吞吐量小得多:每分钟约 500k 条消息甚至更少。
你能推荐一下如何优化它吗?
我的设置
硬件: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.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
我通过为每个目的地创建多个实例解决了这个问题。尽管文章说 aManagedChannel
本身可以产生足够多的连接,所以一个实例就足够了,但在我的情况下并非如此。
性能与 akka-tcp 实现相当。
推荐阅读
- c++ - CppKafka Consumer 初始化需要 5 秒
- java - 具有多个级别的休眠级联删除
- javascript - 如何防止我的可拖动菜单超出 Polymer 2 中的 div?
- excel - 根据今天的日期更改单元格值
- android - 未能部署自定义图像分类模型 (TFLITE)
- git - 复制 Github Webhook -> 对 Postman 的 Jenkins 请求失败:签名与计算的不匹配
- html - CSS padding-top 技巧不会给我正确的比例
- ios - 在 Apple TV 中使用 Apple 登录
- java - 在一系列偏移量之间从 Kafka 主题读取消息
- vba - 无法在输入框中输入范围