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

Netty 不受控制的客户端(websocketx)内存使用过多,netty,Netty,当向一个简单的Netty WebSocket echo服务器实现(示例包中发现的实现的稍加修改的版本)发送数量不受控制的TextWebSocketFrames时,无需等待将来的客户端sync(),服务器上的堆内存使用量呈指数级增长,直到最终耗尽内存 Testcase:客户端不会等到实际字节被写入,也不会等到服务器在写入下一个文本帧之前将文本“回显”到客户端 for (int i = 0; i < 10000000; i++) { ch.write(new TextWebSocket

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

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

for (int i = 0; i < 10000000; i++) {
    ch.write(new TextWebSocketFrame("Message #" + i));
}
在服务器端,主要可以从BigEndianHeapChannelBuffers和CompositeChannelBuffers对象中观察到大量堆积,这些对象从未清理过,也没有垃圾收集过(这可能是因为保存了引用)。我猜这与(单个)工作线程无法将下游“echo”响应写入客户端通道有关,因为它正忙于处理来自客户端的快速传入请求


是否有办法在服务器端防止/限制这种(意外拒绝服务)

在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
    }
  }
}
private final AtomicInteger pendingWrites=new AtomicInteger();
...
while(pendingWrites.get()

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

在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
    }
  }
}
private final AtomicInteger pendingWrites=new AtomicInteger();
...
while(pendingWrites.get()

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

谢谢您的回答。这是否意味着我应该限制服务器端的写操作(下游),而不是限制读操作(上游)从客户端?是的。每当您传输大数据时,我建议进行节流。因此,基本上,为了防止来自恶意客户端的任何类型的拒绝服务(不按照协议输送大量小数据包),您总是需要节流写操作(下游)。难道不应该总是这样吗(就像Netty的默认行为一样)?谢谢你的回答。这是否意味着我应该限制服务器端的写操作(下游),而不是限制客户端的读操作(上游)?是的。每当你传输大数据时,我建议限制。因此,基本上,为了防止来自恶意客户端的任何类型的拒绝服务(不按照协议泵送大量的小软件包),您总是需要限制写操作(下游)。难道不应该总是这样吗(就像Netty的默认行为一样)?