首页 > 解决方案 > 在什么情况下 ChannelPipeline 会删除其所有元素?

问题描述

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

遵循Norman Mauer 的建议,该应用程序大量使用将任务提交给EventExecutor 可访问的 fromChannelHandlerContext#executor()。(我以这种方式提交的任务保留了对提交时有效的引用。)ChannelHandlerContext

在观察应用程序中的奇怪行为后,我记录了ChannelHandlerContext.pipeline().toMap()这些任务之一的输出,因为它由EventExecutoron(定义)事件循环执行。

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

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

我的应用程序中没有任何逻辑可以从ChannelPipeline.

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

我很确定我一定做错了什么——也许我不清楚 a 何时ChannelPipeline超出范围或以其他方式“清除”。Netty 什么时候ChannelPipeline清除?

标签: netty

解决方案


Netty 本身不会从 Pipeline 中移除处理程序。ChannelPipeline当不再使用时(通道保持ChannelPipeline关闭),GC 将其收集为常规 Java 对象。

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

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

在负载下,这个 ChannelHandlerContext “被移除”,因此提交的写入任务在被事件循环运行时不能发生。

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

更新:

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

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

您可以检查ChannelFuture写操作的结果:

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

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

Netty 非常灵活并且提供了许多可能的流程。


推荐阅读