netty做Pipe一端快一端慢时防止内存溢出进行的操作
前段时间用netty3.x做了一个pipe的功能,读的速度很快,写的速度很慢,结果读总是把内存耗光(来不及写写到pipe的另一端),后面解决了这个问题。
原来的pipe的代码:
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { inboundChannel.write(e.getMessage()); }
inboundChannel是一个很慢的连接,而当前连接很快(messageReceived调用很频繁),inboundChannel的写缓冲区很快满了(inboundChannel.isWritable() =false),继续写很容易就OOM了,
修改后的代码是:
private Object trafficLock = new Object(); public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { synchronized (trafficLock) { inboundChannel.write(e.getMessage()); if (!inboundChannel.isWritable()) { e.getChannel().setReadable(false); } } } @Override public void channelInterestChanged(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { synchronized (trafficLock) { if (e.getChannel().isWritable()) { inboundChannel.setReadable(true); } } }
必须给双方的channel都添加包含上述代码的handler,才能生效;
上面的代码可以理解成:
1,如果对方channel不可写时,把当前channel的读操作禁用;
2,如果当前的channel可写了,把对方channel的读操作启用;
两个handler是对等的,恰好可以解决这个问题。
注意:两个handler必须共享锁trafficLock,具体原因,参见讨论:
http://markmail.org/message/x7jc6mqx6ripynqf
以及另外一个实例:
http://searchco.de/codesearch/view/16958454