netty版本
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.50.Final</version>
</dependency>
此版本ChunkedWriteHandler 的write方法如下
public class ChunkedWriteHandler extends ChannelDuplexHandler {
private final Queue<PendingWrite> queue = new ArrayDeque<PendingWrite>();
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
queue.add(new PendingWrite(msg, promise));
}
}
源码可知所有的消息都会被放置queue队列中,同时也不会触发channel高低水位设置,在大量消息堆积时导致内存无法回收OOM。堆内存分析如下:
解决:升级netty版本!
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.108.Final</version>
</dependency>
高版本对write方法进行了优化:
public class ChunkedWriteHandler extends ChannelDuplexHandler {
private final Queue<PendingWrite> queue = new ArrayDeque<PendingWrite>();
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
if (this.queueIsEmpty() && !(msg instanceof ChunkedInput)) {
ctx.write(msg, promise);
} else {
this.allocateQueue();
this.queue.add(new ChunkedWriteHandler.PendingWrite(msg, promise));
}
}
}
在加入queue前对消息类型进行了判断,因此TextWebSocketFrame消息将不会进入队列!