在 Netty 4 (3.x) 之前的版本中,有一种方法可以通过执行器内存感知 channel 处理,并使用 OrderedMemoryAwareThreadPoolExecutor
执行器来执行 channel 操作给定 Channel
。 3.x 中的这个 OrderedMemoryAwareThreadPoolExecutor
将负责为 channel 排序事件处理,即使它们可以由不同的线程执行,也可以限制 使用的总内存 channel
。如果 channel 内存(由于排队的事件)超过某个阈值,事件的执行将被阻止,直到内存被释放。
然而,在 4.x 中,没有这样的机制。新的线程模型确实提供了执行事件的排序(因为特定 channel 的事件由单个线程执行),但似乎没有办法限制单个 Channel
消耗的内存在任何 EventExecutorGroup
中。这意味着,如果这不可能,发送到一个特定 Channel
的大量事件可能会耗尽服务器上的内存。虽然我还没有对此进行测试,但我认为可能值得在这里问一下 Netty 4.x 是否确实如此。
所以我的问题本质上是:
在 Netty 4.x 中使用 EventExecutorGroup
和 ChannelHandler
时,是否有办法限制单个 Channel
消耗的内存?
最佳答案
你是对的。这种情况是有可能的。
但是,Netty 为您的 channel 提供了 ChannelOption.WRITE_BUFFER_WATER_MARK
选项。因此,当您向某个 channel 写入太快并且待处理消息队列超过 ChannelOption.WRITE_BUFFER_WATER_MARK
限制时,您正在写入的 channel 将变得不可写。所以你可以保护你的代码:
if (channel.isWritable()) {
}
或
if (ctx.channel().isWritable()) {
}
从而防止在 channel 繁忙或事件消耗缓慢时耗尽内存。
您还可以更改 ChannelOption.AUTO_READ
以生成事件并手动处理此事件:
ctx.channel().config().setAutoRead(false);
因此您的服务器将停止从生成过多事件的 channel 中读取事件。 Here is pull request这证明了这种方式。
关于java - 使用 Netty 4.1 的内存感知 channel 处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44562265/