当前位置: 首页 > 知识库问答 >
问题:

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

田志尚
2023-03-14

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

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

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 和复合通道缓冲器对象中可以观察到一大堆堆积,这些对象永远不会被清理,也不会被垃圾回收(当引用被保存时,这可能是不可能的)。我猜这与(单个)工作线程无法将下游“echo”响应写入客户端通道有关,因为它正忙于处理来自客户端的快速传入请求

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

共有1个答案

黄景胜
2023-03-14

在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
    }
  }
}

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

 类似资料:
  • 下面是背景故事。。。 我需要创建一个简单的java控制台项目来访问MongoDB数据库,并对其中的记录进行一些更改,以便另一个(更大的)程序在尝试读取记录时不会出错。 现在我正试图让我的java控制台项目连接到MongoDB,但程序一直声明我试图使用的包不存在。 com/logFileModifer/Main Class.java: 3:错误:包com.mongodb.client不存在导入com

  • 我在Linux上使用C。我需要构建使用共享内存和信号量进行通信的两个程序。 其中一个程序必须充当服务器(一次只能充当一个),另一个程序必须充当客户机(一次任意数量)。通信应遵循以下模式: 我知道如何在两个进程之间使用共享内存和信号量,但我不知道如何在数量不明的进程之间进行通信时使用它们。我考虑为每个客户机使用共享内存块,但我必须交换密钥并通知服务器新的客户机。所以这并不能解决问题。

  • 问题内容: 我的磁盘上只有168MB的文件。这只是一个逗号分隔的单词,id的列表。该单词的长度可以为1-5个字符。有650万行。 我在python中创建了一个字典,将其加载到内存中,因此我可以针对该单词列表搜索传入的文本。当python将其加载到内存中时,它显示已使用的1.3 GB RAM空间。知道为什么吗? 假设我的word文件如下所示… 然后再加上650万。然后,我遍历该文件并创建一个字典(p

  • 我正在使用POSIX共享内存和未命名信号量实现客户机服务器。服务器可以同时处理多个客户端。该代码适用于单个客户端,但不适用于多个客户端。POSIX操作是用,

  • 1. 创建 Maven 工程 服务端部署完毕后,我们可以新建一个 Maven 工程使用 SOFARegistry 提供的服务。首先新建一个 Maven 工程,然后引入如下依赖: <dependency> <groupId>com.alipay.sofa</groupId> <artifactId>registry-client-all</artifactId> <versi