分析 Netty 性能

2022-09-03 08:09:06

我正在编写一个Netty应用程序。该应用程序在 64 位八核 Linux 机箱上运行

Netty 应用程序是一个简单的路由器,它接受请求(传入管道)从请求中读取一些元数据,并将数据转发到远程服务(传出管道)。

此远程服务将向传出管道返回一个或多个响应。Netty 应用程序会将响应路由回原始客户端(传入管道)

将有成千上万的客户。将有数千个远程服务。

我正在做一些小规模的测试(十个客户端,十个远程服务),我没有看到我期望在99.9百分位的低于10毫秒的性能。我正在从客户端和服务器端测量延迟。

我使用的是完全异步协议,类似于SPDY。我捕获时间(我只使用System.nanoTime())当我们处理FrameDecoder中的第一个字节时。我在调用 channel.write() 之前停止了计时器。我正在测量从传入管道到传出管道的亚毫秒级时间(99.9 百分位),反之亦然。

我还测量了从 FrameDecoder 中的第一个字节到在(上面的)message.write() 上调用 ChannelFutureListener 回调的时间。时间是几十毫秒(99.9百分位),但我很难说服自己这是有用的数据。

我最初的想法是,我们有一些缓慢的客户。我看了 channel.isWriteable() 并在返回 false 时记录。此方法在正常情况下未返回 false

一些事实:

  • 我们正在使用蔚来工厂。我们尚未自定义工人尺寸
  • 我们已经禁用了Nagel(tcpNoDelay=true)
  • 我们已经启用了保持活动状态(keepAlive=true)
  • CPU 在 90% 以上的时间内处于空闲状态
  • 网络空闲
  • GC (CMS) 在很短的时间内每 100 秒左右调用一次

有没有一种调试技术可以遵循来确定为什么我的Netty应用程序没有像我认为的那样快运行?

感觉就像channel.write()将消息添加到队列中,而我们(使用Netty的应用程序开发人员)对此队列没有透明度。我不知道队列是Netty队列,操作系统队列,网卡队列还是什么。无论如何,我正在查看现有应用程序的示例,我没有看到我正在遵循的任何反模式

感谢您的任何帮助/见解


答案 1

Netty 默认创建 Runtime.getRuntime().availableProcessors() * 2 个 worker。16 在你的情况下。这意味着您最多可以同时处理 16 个通道,其他通道将等到您释放 ChannelUpstreamHandler.handleUpstream/SimpleChannelHandler.messageReceived 处理程序,因此不要在这些 (IO) 线程中执行繁重的操作,否则您可能会卡住其他通道。


答案 2

您尚未指定 Netty 版本,但听起来像 Netty 3。Netty 4现在是稳定的,我建议您尽快更新。您已指定需要超低延迟时间,以及数以万计的客户端和服务。这并不能很好地混合。与OIO相反,NIO本质上是合理的潜在因素。然而,这里的陷阱是OIO可能无法达到您所希望的客户数量。无论如何,我会使用OIO事件循环/工厂,看看它是如何进行的。

我自己有一个TCP服务器,在localhost上发送,接收和处理几个TCP数据包大约需要30ms(从客户端打开套接字到服务器关闭它的时间测量)。如果您确实需要如此低的延迟,我建议您由于打开连接所需的SYN / ACK垃圾邮件而远离TCP,这将占用您10ms的大部分时间。


推荐