Netty-发送队列积压导致内存泄漏

导致Netty内存泄漏的原因很多,如使用内存池方式创建的对象忘记释放,或者系统处理压力过大导致发送队列积压,尽管Netty采用NIO非阻塞通信,I/O处理往往不会成为业务瓶颈,但如果客户端并发压力过大,超过了服务端处理能力,又没有流控保护,则容易发生内存泄漏


   高并发故障场景
   如何防止发送队列积压
   其他可能导致发送队列积压的因素


高并发故障场景

     模拟一下业务代码,在一个客户端内部创建一个线程,向服务端循环发送请求信息,模拟客户端高并发场景,示例代码如下:

public void channelActive(final ChannelHandlerContext ctx){
	loadRunner = new Runnable(){
		@Override
		public void run(){
			try{
				TimeUnit.SECONDS.sleep(30);
			} catch(InterruptedException e){
				e.printStackTrace();
			}
			ByteBuf msg = null;
			final int len = "Netty OOM Example".getBytes().length;
			while(true){
				msg = Unpooled.wrappedBuffer("Netty OOM Example".getBytes());
				ctx.writeAndFlush(msg);
			}
		}
	};
	new Thread(loadRunner).start();
}

     创建链路后,客户端启动一个线程向服务端循环发送信息,系统运行,发现内存占用率飙升。内存数据监控图:
在这里插入图片描述
     来看看GC监控图:
在这里插入图片描述
     CPU使用情况:
在这里插入图片描述
     GC线程占用大量CPU资源。


如何防止发送队列积压

     为防止在高并发场景下,由于服务器处理慢导致客户端消息积压,除了服务端做流控,客户端也需要做并发保护,防止自身发生消息积压。
     Netty提供高低水位机制,可以实现客户端更精准的流控,当发送队列待发送的字节数组达到高水位时,对应的Channel就变为不可写状态。由于高水位并不影响业务线程调用write方法并把消息加入待发送队列,因此,必须在消息发送时对Channel的状态进行判断:当到达高水位时,Channel的状态被设置为不可写,通过对Channel的可写状态进行判断来决定是否发送消息:

public void channelActive(final ChannelHandlerContext ctx){
	ctx.channel().config.setWriteBufferHighWaterMark(1024 * 1024);	//设置高水位
	loadRunner = new Runnable(){
		@Override
		public void run(){
			try{
				TimeUnit.SECONDS.sleep(30);
			} catch(InterruptedException e){
				e.printStackTrace();
			}
			ByteBuf msg = null;
			final int len = "Netty OOM Example".getBytes().length;
			while(true){
				if(ctx.channel().isWritable()){
					msg = Unpooled.wrappedBuffer("Netty OOM Example".getBytes());
					ctx.writeAndFlush(msg);
				}else{
					LOG.warning("The write queue is busy");
				}
			}
		}
	};
	new Thread(loadRunner).start();
}

其他可能导致发送队列积压的因素

     然而,在实际情况中,并非只有高并发场景才会导致消息积压,在一些异常场景下,尽管流量不大,但仍然可能导致消息积压,场景如下:

  • 网络瓶颈,当发送速度超过网络链接处理能力,会导致发送队列积压
  • 当对端读取速度小于己方发送速度,导致自身TCP发送缓冲区满,频繁发生write 0字节时,待发送消息会在Netty发送队列中排队。当出现大量排队时,很容易导致Netty的直接内存泄漏。
发布了12 篇原创文章 · 获赞 12 · 访问量 677

猜你喜欢

转载自blog.csdn.net/MarchRS/article/details/103952718