关于Netty的一些理解、实践与陷阱
核心概念的理解
Netty對于網絡層進行了自己的抽象,用Channel表示連接,讀寫就是Channel上發生的事件,ChannelHandler用來處理這些事件,ChannelPipeline基于unix哲學提供了一種優雅的組織ChannelHandler的方式,用管道解耦不同層面的處理。現在回過頭來看看,真的是非常天才和優雅的設計,是我心中API設計的典范之一了。
TCP半包、粘包
使用Netty內置的LineBasedFrameDecoder或者LengthFieldBasedFrameDecoder,我們只要在pipeline中添加,就解決了這個問題。
Writtable問題
有時候,由于TCP的send buffer滿了,向channel的寫入會失敗。我們需要檢查channel().isWritable()標記來確定是否執行寫入。
處理耗時任務
Netty In Action以及網上的一些資料中,都沒有很直接的展示如何在Netty中去處理耗時任務。其實也很簡單,只要給handler指定一個事件循環就可以,例如
public class MyChannelInitializer extends ChannelInitializer<Channel> {private static EventExecutorGroup longTaskGroup = new DefaultEventExecutorGroup(5);protected void initChannel(Channel channel) throws Exception {ChannelPipeline pipeline = channel.pipeline();...pipeline.addLast(longTaskGroup, new PrintHandler());} }復制代碼Pitfall
Netty的ChannelPipeline只有一條雙向鏈,消息入站,經過一串InBoundHandler之后,以相反的順序再經過OutBoundHandler出站.因此,我們自定義的handler一般會處于pipeline的末尾!
舉個例子,當以如下順序添加handler時,如果調用ChannelHandlerContext上的writeAndFlush方法,出站消息是無法經過StringEncoder的
public class MyChannelInitializer extends ChannelInitializer<Channel> {private static EventExecutorGroup longTaskGroup = new DefaultEventExecutorGroup(5);protected void initChannel(Channel channel) throws Exception {ChannelPipeline pipeline = channel.pipeline();pipeline.addLast(new LineBasedFrameDecoder(64 * 1024));pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));pipeline.addLast(longTaskGroup, new PrintHandler());pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));} }復制代碼這個問題有兩個解決方式
調整handler的順序
public class MyChannelInitializer extends ChannelInitializer<Channel> {private static EventExecutorGroup longTaskGroup = new DefaultEventExecutorGroup(5);protected void initChannel(Channel channel) throws Exception {ChannelPipeline pipeline = channel.pipeline();pipeline.addLast(new LineBasedFrameDecoder(64 * 1024));pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));pipeline.addLast(longTaskGroup, new PrintHandler());} }復制代碼調用Channel上的writeAndFlush方法
public class PrintHandler extends SimpleChannelInboundHandler<String> {protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { // ctx.writeAndFlush(msg);ctx.channel().writeAndFlush(msg);System.out.println(msg);} }復制代碼參考
www.voidcn.com/article/p-y…
stackoverflow.com/questions/3…
《Netty In Action》
總結
以上是生活随笔為你收集整理的关于Netty的一些理解、实践与陷阱的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 园友们注意:淘宝网上QQ会员 4钻 3元
- 下一篇: linux架构师高级系统调优策略