在什么情况下,ChannelPipeline 的所有元素都会被移除?

Under what circumstances will a ChannelPipeline have all of its elements removed?

我正在对 Netty 应用程序进行负载测试。

该应用程序大量使用 submitting tasks to the EventExecutor reachable from ChannelHandlerContext#executor(), following Norman Mauer's recommendations。 (我以这种方式提交的任务保留了对提交时有效的 ChannelHandlerContext 的引用。)

在观察到应用程序中的奇怪行为后,我从其中一个任务中记录了 ChannelHandlerContext.pipeline().toMap() 的输出,因为它是由 EventExecutor 在(定义上)事件循环中执行的。

如此记录的管道是空的,令我惊讶的是(对我而言)。

(我从更传统的 channelRead 方法中记录了管道,不用说它不是空的。)

我的应用程序中没有任何从 ChannelPipeline.

中删除项目的逻辑

我没有关闭任何通道(客户端请求保持连接)。

我很确定我一定是做错了什么——也许我不清楚 ChannelPipeline 何时超出范围或 "cleared"。 ChannelPipeline 什么时候被 Netty 清除?

Netty 本身不会从管道中删除处理程序。 ChannelPipeline 在不再使用时被 GC 收集为常规 Java 对象(通道持有 ChannelPipeline 已关闭)。

所以要么你在你的代码中这样做(但你没有),要么管道被通道破坏。 当您进行负载测试时,我的建议是:

  • 您在服务器上创建负载;
  • 测试客户端无法处理足够的负载并关闭一些连接(在高负载测试期间很常见的情况);
  • Netty 看到连接已关闭并删除通道(和管道)并使用 GC 收集;
  • 因此,您仍然拥有引用已删除频道的上下文;

Under load, this ChannelHandlerContext "becomes removed", and hence the submitted write task cannot, when run by the event loop, take place.

这是意料之中的。频道随时可能变得不可用。因此,如果您将任务委托给某个线程池,您应该检查通道是否仍然是 active/writable,或者您可以使用 write() 操作中的 ChannelFuture

更新:

根据您的需要,您有多种选择。您可以在实际写入之前检查通道是否可写:

if (ctx.channel().isWritable()) {
    //write
}

写操作结果可以查看ChannelFuture

ChannelFuture cf = ctx.writeAndFlush();
//cf has a bunch of method + listeners that you can use

您也可以使用 ChannelPromise 并覆盖所需的方法。

Netty 非常灵活,提供了很多可能的流程。