GRPC:用Java/Scala制作高吞吐量客户端

2023-12-21

我有一项以相当高的速率传输消息的服务。

目前它由 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(使用前将#替换为@)

GRPC:用Java/Scala制作高吞吐量客户端 的相关文章

随机推荐

  • 如何在 R 的 For 循环中正确使用 group_by() 和 summarise()

    我正在尝试计算一些摘要信息 以帮助我检查数据集中不同组中的异常值 我可以使用我想要的输出类型dplyr group by and dplyr summarise 包含给定变量的每个组的摘要信息的数据框 像这样的事情 Sepal Length
  • For 循环 gitlab-ci.yml

    我有这个代码片段 它给了我语法错误 意外的文件结尾 如果我将其复制到 sh 文件中并在终端中运行 它就可以工作 before script sbt sbtVersion for file in pending sql do file bas
  • 在快速枚举期间将对象设置为零[重复]

    这个问题在这里已经有答案了 我想在枚举数组时将对象设置为 nil 如下所示 for Object object in array object nil 然后 Xcode 告诉我 默认情况下 无法在 ARC 中修改快速枚举变量 声明变量 st
  • 多对多关系桥表困境

    salesman uId salesGroupLinked uId groupId add performacesScore field here group groupId 我上面有 3 个表 形成了多对多关系 我会添加一个字段 perf
  • 如果@EnvironmentObject如何创建通用?

    我最近遇到需要编写一个 MockClass 因为它会导致 SwiftUIpreview从工作中 不幸的是 我收到错误 Property type T does not match that of the wrappedValue prope
  • React 中基于当前状态的 setState

    在 React 中更新有状态组件时 组件使用当前状态来更新新状态被认为是一种不好的做法 例如 如果我有一个类存储过滤器在其状态中是否打开 那么在性能方面 用于更新状态的这些选项之一是否比另一个更可取 选项1 class Container
  • 遍历页面上的所有

    我想使用 Javascript 浏览页面上的所有元素 看看它们是否设置了属性 有没有一种简单的方法可以做到这一点 或者我是否必须使用递归解决方案 您可以使用 var divs document getElementsByTagName di
  • 在 Gmaps Api 中使用一个航点作为目的地

    我正在使用 gmaps Api 为必须访问市场列表 我的路径点 以记录其股票的人制定一条路线 我使用用户的房屋位置作为路线的起点 使用市场的位置作为我的路径点 问题是我不知道哪个航路点是路线的目的地 因为我设置了属性optimization
  • Sharepoint、计算列、IF 函数和日期

    我正在尝试添加一个计算列 我有一个日期列 其中包含安排会议的日期 在本专栏中 我需要一个代码 如果会议安排在第一季度 第二季度 第三季度或第四季度 则可以返回该代码 我有一个静态代码 如下所示 IF Date lt 40269 Q1 Q2
  • _spark_metadata 导致问题

    我将 Spark 与 Scala 一起使用 并且我有一个目录 其中有多个文件 在这个目录中 我有 Spark 生成的 Parquet 文件和 Spark Streaming 生成的其他文件 并且Spark Streaming生成一个目录 s
  • 如何让 Wintersmith 中的文章不在其自己的子目录中?

    在 Wintersmith 中 默认博客模板从 content articles index md 生成帖子 这很好 因为它允许将图像等关联文件包含在文章中 但实际上 大多数 博客文章 只是与模板关联的文本内容 必须创建子目录是一个小烦恼
  • iPhone,“尝试注册的过滤专辑列表超过最多 5 个。这将失败。”错误

    当我尝试从照片库中读取图像时 出现错误 尝试注册的过滤相册列表超过最多 5 个 这将失败 图像未读取 知道如何解决这个问题吗 我认为您没有检查源类型 你可能正在做 self sourceType UIImagePickerControlle
  • Unix Shell编程:打印时添加空行

    我试图列出目录中的所有文件 但是如何用空行分隔每个文件 基本上每个文件都用空行分隔显示 我正在尝试使用 for 循环 我确实尝试了几个例子 但没有一个真正通过在之间间隔空行来起作用 for i in ls do echo n ls l do
  • 在所有视图中创建 Telerik Sidedrawer

    我已经成功地让 Telerik Side drawer 在一个视图中工作 但我坚持将其制作成一个可以全局使用的组件 我想避免将其复制并粘贴到每个视图中 所以我的问题是如何将其变成可重用的组件 所以当你使用page router outlet
  • MySQL - 如果尚不存在则插入

    我想执行这个 MySQL 查询 INSERT INTO cron stats user VALUES int d by user 每当此类用户尚不存在时 如下所示 SELECT 1 FROM cron stats WHERE user in
  • git log 中带有 tformat 的额外换行符

    当我使用git log pretty oneline shortstat 我得到了我的日志的紧凑表示 git log pretty oneline shortstat 73c6eecd930c2f66d5c1e87fcca7ca9b0e35
  • 需要一些有关使用 PERL 的 IRC BOTS 的信息

    有谁知道有一款用 Perl 编写的好 irc 机器人吗 我只需要一个简单的登录到该频道 然后根据用户所说的内容进行回复 e g 用户
  • 只让实例访问标签本身?

    看着这个帖子 https serverfault com questions 686526 how do you tag and name the ec2 instance that was launched by an ec2 spot
  • AppStore iOS 应用新版本提交问题

    您好 提前致谢 在尝试使用应用程序加载器向 AppStore 提交新版本的 iOS 应用程序时 我收到了以下消息 ITC apps validation prerelease build missing 并停止提交 我在使用以前版本的 iT
  • GRPC:用Java/Scala制作高吞吐量客户端

    我有一项以相当高的速率传输消息的服务 目前它由 akka tcp 提供服务 每分钟生成 350 万条消息 我决定尝试一下 grpc 不幸的是 它导致吞吐量小得多 每分钟约 500k 条消息 甚至更少 您能推荐一下如何优化吗 My setup