netty - 不受控制的客户端使用过多内存 (websocketx)

标签 netty

当发送不受控制的数量的 TextWebSocketFrames 到一个简单的 Netty WebSocket echo 服务器实现(示例包中的实现的稍微修改版本)时,无需等待 ChannelFuture 上的客户端同步(),服务器呈指数增长,直到最终耗尽内存。

测试用例:客户端不会等到实际字节被写入,也不会等待服务器在写入下一个文本帧之前将文本“回显”回客户端

for (int i = 0; i < 10000000; i++) {
    ch.write(new TextWebSocketFrame("Message #" + i));
}

观察 yourkit 内存分析器时(测试 15 秒,写入约 20.000 帧),BigEndianHeapChannelBuffer 对象的数量增长过度。

BigEndianHeapChannelBuffer 284,509 (objects) 9,104,288 (shallow size) (after ~30.000 frames sent within 10 second window)

在服务器端,主要可以从 BigEndianHeapChannelBuffers 和 CompositeChannelBuffers 对象中观察到大量堆积,这些对象从未被清理或垃圾收集(这可能是不可能的,因为引用被保留)。我猜测这与(单个)工作线程无法将下游“回显”响应写入客户端 channel 有关,因为它正忙于处理来自客户端的快速传入请求

有没有办法在服务器端防止/限制这种情况(意外拒绝服务)?

最佳答案

在 Netty 中,大多数 I/O 操作都是异步的。因此,在不等待前面的写入完成的情况下写入数千条消息将会导致 OutOfMemoryError。为了避免这种情况,我更喜欢使用计数器变量来计算待处理写入的数量。例如:

private final AtomicInteger pendingWrites = new AtomicInteger();

...
while (pendingWrites.get() < MAX_PENDING_WRITES) {
  pendingWrites.incrementAndGet();
  ch.write(msg).addListener(new ChannelFutureListener() {
    ...
    pendingWrites.decrementAndGet();
    if (pendingWrites.get() < MAX_PENDING_WRITES) {
      // resume writing here
    }
  }
}

或者,您可以使用 ChunkedWriteHandler ,它基本上可以完成相同的工作。

关于netty - 不受控制的客户端使用过多内存 (websocketx),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11042503/

相关文章:

ssl - 如何在 Netty 客户端启用 session 恢复

java - HttpObjectAggregator 处的 Netty 4 泄漏异常

java - Netty3.2 API 中的超时示例( IdleStateHandler 和 ReadTimeoutHandler )不适用于服务器

sockets - 接收套接字请求,通过各种端点,并使用 camel 中的 netty 响应同一个套接字连接

Java 数据包处理程序线程

java - netty epoll native 在 linux (debian) 中抛出 java.lang.IllegalArgumentException

java - Netty:我应该创建新的 ChannelBuffer 来向每个客户端发送数据吗?

java - 使用Netty时如何处理连接或绑定(bind)异常

amazon-ec2 - 亚马逊 ec2 上的 Websockets 连接失败

java - 即使业务逻辑是纯CPU操作,是否也需要在channelread方法中启动一个新线程来执行业务逻辑?