为什么 Netty HTTP 处理程序不可共享?

Aci*_*ier 3 java garbage-collection instantiation netty java-11

每当打开新连接时,Netty 都会实例化一组请求处理程序类。这对于像 websocket 这样的连接将在 websocket 的生命周期内保持打开状态似乎很好。

当使用 Netty 作为每秒可以接收数千个请求的 HTTP 服务器时,这似乎是垃圾收集的负担。每个请求都会实例化几个类(在我的例子中是 10 个处理程序类),然后在几毫秒后垃圾收集它们。

在具有中等负荷〜1000请求/秒的HTTP服务器,这将是10000类实例化和垃圾收集每一秒

似乎我们可以简单地 看到下面的答案创建可共享的处理程序,使用ChannelHandler.Sharable. 他们只需要是线程安全的。

但是,我看到打包在库中的所有非常基本的 HTTP 处理程序都不可共享,例如HttpServerCodecHttpObjectAggregator。此外,没有一个HTTP 处理程序示例是可共享的。99% 的示例代码和教程似乎都不会打扰它。Norman Maurer 的(Netty 的作者)中只有一句话说明了使用共享处理程序的原因:

为什么要共享一个通道处理程序?

在多个 ChannelPipelines 中安装单个 ChannelHandler 的一个常见原因是收集多个 Channel 的统计信息。

没有提到任何地方的 GC 负载问题。


Netty 已在常规生产环境中使用了近十年。对于高度并发的非阻塞 IO,它可以说是现存最常用的 Java 库。

换句话说,它的设计目的远不止我每秒 1000 个中等的请求。

是否有什么我错过了使 GC 负载不成问题的东西?

或者,我应该尝试实现自己的Sharable处理程序,其具有类似的功能来解码、编码和写入 HTTP 请求和响应吗?

Nor*_*rer 5

虽然我们始终致力于在 netty 中产生尽可能少的 GC,但在某些情况下这是不可能的。例如,http 编解码器等保持每个连接的状态,因此它们不能共享(即使它们是线程安全的)。

解决这个问题的唯一方法是将它们池化,但我认为还有其他更可能导致 GC 问题的对象,对于这些对象,我们会尽可能地尝试池化。