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>();@Overridepublic 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>();@Overridepublic 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消息将不会进入队列!