热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

GRPC:在Java/Scala中成为高吞吐量客户端

我有一项服务,可以以很高的速率传输邮件。当前,它由akka-tcp服务,每分钟发

我有一项服务,可以以很高的速率传输邮件。

当前,它由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.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实现相当。

,

有趣的问题。计算机网络软件包使用stack of protocols进行编码,并且这些协议是在前一个协议的规范之上构建的。因此,由于要在基础协议之上添加额外的编码/解码步骤,因此协议的性能(吞吐量)受用于构建协议的性能的限制。

例如,gRPC构建在HTTP 1.1/2之上,而L7 Application层​​em>或HTTP上的协议,因此其性能为受HTTP的性能约束。现在TCP本身是建立在L4之上的,而gRPC位于传输层TCP,因此我们可以推断出TCP的吞吐量不能大于gRPC层中提供的等效代码。

换句话说:如果您的服务器能够处理原始DbContext包,那么增加新的复杂性层(DbContext)会如何提高性能?

,

我对Akka TCP在这里的出色表现印象深刻:D

我们的经验略有不同。我们正在使用Akka Cluster处理更小的实例。对于Akka远程处理,我们使用Artery从Akka TCP更改为UDP,并实现了更高的速率+更低的响应时间和更稳定的响应时间。 Artery中甚至有一个配置,有助于在CPU消耗和冷启动响应时间之间取得平衡。

我的建议是使用一些基于UDP的框架,该框架也为您提供传输可靠性(例如,Artery UDP),并且仅使用Protobuf进行序列化,而不是使用完整的gRPC。 HTTP / 2传输通道并不是真正用于高吞吐量,低响应时间的目的。


推荐阅读
  • 本文讨论了在VMWARE5.1的虚拟服务器Windows Server 2008R2上安装oracle 10g客户端时出现的问题,并提供了解决方法。错误日志显示了异常访问违例,通过分析日志中的问题帧,找到了解决问题的线索。文章详细介绍了解决方法,帮助读者顺利安装oracle 10g客户端。 ... [详细]
  • 本文介绍了解决Netty拆包粘包问题的一种方法——使用特殊结束符。在通讯过程中,客户端和服务器协商定义一个特殊的分隔符号,只要没有发送分隔符号,就代表一条数据没有结束。文章还提供了服务端的示例代码。 ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • Hadoop 源码学习笔记(4)Hdfs 数据读写流程分析
    Hdfs的数据模型在对读写流程进行分析之前,我们需要先对Hdfs的数据模型有一个简单的认知。数据模型如上图所示,在NameNode中有一个唯一的FSDirectory类负责维护文件 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 怎么在PHP项目中实现一个HTTP断点续传功能发布时间:2021-01-1916:26:06来源:亿速云阅读:96作者:Le ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • 纠正网上的错误:自定义一个类叫java.lang.System/String的方法
    本文纠正了网上关于自定义一个类叫java.lang.System/String的错误答案,并详细解释了为什么这种方法是错误的。作者指出,虽然双亲委托机制确实可以阻止自定义的System类被加载,但通过自定义一个特殊的类加载器,可以绕过双亲委托机制,达到自定义System类的目的。作者呼吁读者对网上的内容持怀疑态度,并带着问题来阅读文章。 ... [详细]
  • ***byte(字节)根据长度转成kb(千字节)和mb(兆字节)**parambytes*return*publicstaticStringbytes2kb(longbytes){ ... [详细]
  • Servlet多用户登录时HttpSession会话信息覆盖问题的解决方案
    本文讨论了在Servlet多用户登录时可能出现的HttpSession会话信息覆盖问题,并提供了解决方案。通过分析JSESSIONID的作用机制和编码方式,我们可以得出每个HttpSession对象都是通过客户端发送的唯一JSESSIONID来识别的,因此无需担心会话信息被覆盖的问题。需要注意的是,本文讨论的是多个客户端级别上的多用户登录,而非同一个浏览器级别上的多用户登录。 ... [详细]
  • ejava,刘聪dejava
    本文目录一览:1、什么是Java?2、java ... [详细]
  • 流数据流和IO流的使用及应用
    本文介绍了流数据流和IO流的基本概念和用法,包括输入流、输出流、字节流、字符流、缓冲区等。同时还介绍了异常处理和常用的流类,如FileReader、FileWriter、FileInputStream、FileOutputStream、OutputStreamWriter、InputStreamReader、BufferedReader、BufferedWriter等。此外,还介绍了系统流和标准流的使用。 ... [详细]
  • 本文介绍了如何使用go语言实现一个一对一的聊天服务器和客户端,包括服务器开启、等待客户端连接、关闭连接等操作。同时提供了一个相关的多人聊天的链接供参考。 ... [详细]
author-avatar
nikechen
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有