﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-paulwong-随笔分类-NETTY</title><link>http://www.blogjava.net/paulwong/category/54729.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 02 Dec 2020 14:17:25 GMT</lastBuildDate><pubDate>Wed, 02 Dec 2020 14:17:25 GMT</pubDate><ttl>60</ttl><item><title>史上最通俗Netty入门长文：基本介绍、环境搭建、动手实战</title><link>http://www.blogjava.net/paulwong/archive/2020/12/02/435738.html</link><dc:creator>paulwong</dc:creator><author>paulwong</author><pubDate>Wed, 02 Dec 2020 01:15:00 GMT</pubDate><guid>http://www.blogjava.net/paulwong/archive/2020/12/02/435738.html</guid><wfw:comment>http://www.blogjava.net/paulwong/comments/435738.html</wfw:comment><comments>http://www.blogjava.net/paulwong/archive/2020/12/02/435738.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/paulwong/comments/commentRss/435738.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/paulwong/services/trackbacks/435738.html</trackback:ping><description><![CDATA[<a href="http://www.blogjava.net/jb2011/archive/2020/11/18/435727.html" target="_blank">http://www.blogjava.net/jb2011/archive/2020/11/18/435727.html</a><img src ="http://www.blogjava.net/paulwong/aggbug/435738.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/paulwong/" target="_blank">paulwong</a> 2020-12-02 09:15 <a href="http://www.blogjava.net/paulwong/archive/2020/12/02/435738.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SPRING MVC整合NETTY</title><link>http://www.blogjava.net/paulwong/archive/2016/04/19/430146.html</link><dc:creator>paulwong</dc:creator><author>paulwong</author><pubDate>Tue, 19 Apr 2016 05:27:00 GMT</pubDate><guid>http://www.blogjava.net/paulwong/archive/2016/04/19/430146.html</guid><wfw:comment>http://www.blogjava.net/paulwong/comments/430146.html</wfw:comment><comments>http://www.blogjava.net/paulwong/archive/2016/04/19/430146.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/paulwong/comments/commentRss/430146.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/paulwong/services/trackbacks/430146.html</trackback:ping><description><![CDATA[<a href="http://wenku.baidu.com/view/4573aba4ce2f0066f53322e8.html" target="_blank">http://wenku.baidu.com/view/4573aba4ce2f0066f53322e8.html</a><img src ="http://www.blogjava.net/paulwong/aggbug/430146.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/paulwong/" target="_blank">paulwong</a> 2016-04-19 13:27 <a href="http://www.blogjava.net/paulwong/archive/2016/04/19/430146.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Netty是什么？</title><link>http://www.blogjava.net/paulwong/archive/2016/04/12/430057.html</link><dc:creator>paulwong</dc:creator><author>paulwong</author><pubDate>Tue, 12 Apr 2016 07:19:00 GMT</pubDate><guid>http://www.blogjava.net/paulwong/archive/2016/04/12/430057.html</guid><wfw:comment>http://www.blogjava.net/paulwong/comments/430057.html</wfw:comment><comments>http://www.blogjava.net/paulwong/archive/2016/04/12/430057.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/paulwong/comments/commentRss/430057.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/paulwong/services/trackbacks/430057.html</trackback:ping><description><![CDATA[<p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">本质：JBoss做的一个Jar包</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">目的：快速开发高性能、高可靠性的网络服务器和客户端程序</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">优点：提供异步的、事件驱动的网络应用程序框架和工具</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">通俗的说：一个好使的处理Socket的东东</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">如果没有Netty？</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">远古：java.net + java.io</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">近代：java.nio</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">其他：Mina，Grizzly</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">为什么不是Mina？</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">1、都是Trustin Lee的作品，Netty更晚；</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">2、Mina将内核和一些特性的联系过于紧密，使得用户在不需要这些特性的时候无法脱离，相比下性能会有所下降，Netty解决了这个设计问题；</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">3、Netty的文档更清晰，很多Mina的特性在Netty里都有；</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">4、Netty更新周期更短，新版本的发布比较快；</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">5、它们的架构差别不大，Mina靠apache生存，而Netty靠jboss，和jboss的结合度非常高，Netty有对google protocal buf的支持，有更完整的ioc容器支持(spring,guice,jbossmc和osgi)；</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">6、Netty比Mina使用起来更简单，Netty里你可以自定义的处理upstream events 或/和 downstream events，可以使用decoder和encoder来解码和编码发送内容；</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">7、Netty和Mina在处理UDP时有一些不同，Netty将UDP无连接的特性暴露出来；而Mina对UDP进行了高级层次的抽象，可以把UDP当成"面向连接"的协议，而要Netty做到这一点比较困难。</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">Netty的特性</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">设计</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">统一的API，适用于不同的协议（阻塞和非阻塞）</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">基于灵活、可扩展的事件驱动模型</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">高度可定制的线程模型</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">可靠的无连接数据Socket支持（UDP）</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">性能</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">更好的吞吐量，低延迟</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">更省资源</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">尽量减少不必要的内存拷贝</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">安全</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">完整的SSL/TLS和STARTTLS的支持</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">能在Applet与Android的限制环境运行良好</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">健壮性</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">不再因过快、过慢或超负载连接导致OutOfMemoryError</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">不再有在高速网络环境下NIO读写频率不一致的问题</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">易用</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">完善的JavaDoc，用户指南和样例</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">简洁简单</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">仅信赖于JDK1.5</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">看例子吧！</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">Server端：</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><div style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;"><div>Java代码&nbsp;&nbsp;<a href="http://www.360doc.com/content/16/0412/15/12309855_550010175.shtml" title="收藏这段代码" style="color: #3d6ba7; text-decoration: none;"><img src="http://image89.360doc.com/DownloadImg/2015/10/1815/60361547_1.png" alt="收藏代码" style="border: 0px;" /></a></div><ol start="1"><li style="padding: 0px; margin: 0px;">package&nbsp;me.hello.netty;&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">import&nbsp;org.jboss.netty.bootstrap.ServerBootstrap;&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">import&nbsp;org.jboss.netty.channel.*;&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">import&nbsp;org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">import&nbsp;org.jboss.netty.handler.codec.string.StringDecoder;&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">import&nbsp;org.jboss.netty.handler.codec.string.StringEncoder;&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">import&nbsp;java.net.InetSocketAddress;&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">import&nbsp;java.util.concurrent.Executors;&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">/**&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;*&nbsp;God&nbsp;Bless&nbsp;You!&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;*&nbsp;Author:&nbsp;Fangniude&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;*&nbsp;Date:&nbsp;2013-07-15&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;*/&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">public&nbsp;class&nbsp;NettyServer&nbsp;{&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ServerBootstrap&nbsp;bootstrap&nbsp;=&nbsp;new&nbsp;ServerBootstrap(new&nbsp;NioServerSocketChannelFactory(Executors.newCachedThreadPool(),&nbsp;Executors.newCachedThreadPool()));&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Set&nbsp;up&nbsp;the&nbsp;default&nbsp;event&nbsp;pipeline.&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bootstrap.setPipelineFactory(new&nbsp;ChannelPipelineFactory()&nbsp;{&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;ChannelPipeline&nbsp;getPipeline()&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;Channels.pipeline(new&nbsp;StringDecoder(),&nbsp;new&nbsp;StringEncoder(),&nbsp;new&nbsp;ServerHandler());&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Bind&nbsp;and&nbsp;start&nbsp;to&nbsp;accept&nbsp;incoming&nbsp;connections.&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Channel&nbsp;bind&nbsp;=&nbsp;bootstrap.bind(new&nbsp;InetSocketAddress(8000));&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Server已经启动，监听端口:&nbsp;"&nbsp;+&nbsp;bind.getLocalAddress()&nbsp;+&nbsp;"，&nbsp;等待客户端注册。。。");&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;class&nbsp;ServerHandler&nbsp;extends&nbsp;SimpleChannelHandler&nbsp;{&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;messageReceived(ChannelHandlerContext&nbsp;ctx,&nbsp;MessageEvent&nbsp;e)&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(e.getMessage()&nbsp;instanceof&nbsp;String)&nbsp;{&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;message&nbsp;=&nbsp;(String)&nbsp;e.getMessage();&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Client发来:"&nbsp;+&nbsp;message);&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.getChannel().write("Server已收到刚发送的:"&nbsp;+&nbsp;message);&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("\n等待客户端输入。。。");&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super.messageReceived(ctx,&nbsp;e);&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;exceptionCaught(ChannelHandlerContext&nbsp;ctx,&nbsp;ExceptionEvent&nbsp;e)&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super.exceptionCaught(ctx,&nbsp;e);&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;channelConnected(ChannelHandlerContext&nbsp;ctx,&nbsp;ChannelStateEvent&nbsp;e)&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("有一个客户端注册上来了。。。");&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Client:"&nbsp;+&nbsp;e.getChannel().getRemoteAddress());&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Server:"&nbsp;+&nbsp;e.getChannel().getLocalAddress());&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("\n等待客户端输入。。。");&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super.channelConnected(ctx,&nbsp;e);&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">}&nbsp;&nbsp;</li></ol></div><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">客户端：</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><div style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;"><div>Java代码&nbsp;&nbsp;<a href="http://www.360doc.com/content/16/0412/15/12309855_550010175.shtml" title="收藏这段代码" style="color: #3d6ba7; text-decoration: none;"><img src="http://image89.360doc.com/DownloadImg/2015/10/1815/60361547_1.png" alt="收藏代码" style="border: 0px;" /></a></div><ol start="1"><li style="padding: 0px; margin: 0px;">package&nbsp;me.hello.netty;&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">import&nbsp;org.jboss.netty.bootstrap.ClientBootstrap;&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">import&nbsp;org.jboss.netty.channel.*;&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">import&nbsp;org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">import&nbsp;org.jboss.netty.handler.codec.string.StringDecoder;&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">import&nbsp;org.jboss.netty.handler.codec.string.StringEncoder;&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">import&nbsp;java.io.BufferedReader;&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">import&nbsp;java.io.InputStreamReader;&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">import&nbsp;java.net.InetSocketAddress;&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">import&nbsp;java.util.concurrent.Executors;&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">/**&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;*&nbsp;God&nbsp;Bless&nbsp;You!&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;*&nbsp;Author:&nbsp;Fangniude&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;*&nbsp;Date:&nbsp;2013-07-15&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;*/&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">public&nbsp;class&nbsp;NettyClient&nbsp;{&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Configure&nbsp;the&nbsp;client.&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ClientBootstrap&nbsp;bootstrap&nbsp;=&nbsp;new&nbsp;ClientBootstrap(new&nbsp;NioClientSocketChannelFactory(Executors.newCachedThreadPool(),&nbsp;Executors.newCachedThreadPool()));&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Set&nbsp;up&nbsp;the&nbsp;default&nbsp;event&nbsp;pipeline.&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bootstrap.setPipelineFactory(new&nbsp;ChannelPipelineFactory()&nbsp;{&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;ChannelPipeline&nbsp;getPipeline()&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;Channels.pipeline(new&nbsp;StringDecoder(),&nbsp;new&nbsp;StringEncoder(),&nbsp;new&nbsp;ClientHandler());&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Start&nbsp;the&nbsp;connection&nbsp;attempt.&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ChannelFuture&nbsp;future&nbsp;=&nbsp;bootstrap.connect(new&nbsp;InetSocketAddress("localhost",&nbsp;8000));&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Wait&nbsp;until&nbsp;the&nbsp;connection&nbsp;is&nbsp;closed&nbsp;or&nbsp;the&nbsp;connection&nbsp;attempt&nbsp;fails.&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;future.getChannel().getCloseFuture().awaitUninterruptibly();&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Shut&nbsp;down&nbsp;thread&nbsp;pools&nbsp;to&nbsp;exit.&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bootstrap.releaseExternalResources();&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;class&nbsp;ClientHandler&nbsp;extends&nbsp;SimpleChannelHandler&nbsp;{&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;BufferedReader&nbsp;sin&nbsp;=&nbsp;new&nbsp;BufferedReader(new&nbsp;InputStreamReader(System.in));&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;messageReceived(ChannelHandlerContext&nbsp;ctx,&nbsp;MessageEvent&nbsp;e)&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(e.getMessage()&nbsp;instanceof&nbsp;String)&nbsp;{&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;message&nbsp;=&nbsp;(String)&nbsp;e.getMessage();&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(message);&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.getChannel().write(sin.readLine());&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("\n等待客户端输入。。。");&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super.messageReceived(ctx,&nbsp;e);&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;channelConnected(ChannelHandlerContext&nbsp;ctx,&nbsp;ChannelStateEvent&nbsp;e)&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("已经与Server建立连接。。。。");&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("\n请输入要发送的信息：");&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super.channelConnected(ctx,&nbsp;e);&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.getChannel().write(sin.readLine());&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li style="padding: 0px; margin: 0px;">}&nbsp;&nbsp;</li></ol></div><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">Netty整体架构</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;"><br /><img alt="" src="http://image89.360doc.com/DownloadImg/2015/10/1815/60361547_2.jpg" style="border: 0px;" /><br />&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">Netty组件</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">ChannelFactory</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">Boss</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">Worker</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">Channel</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">ChannelEvent</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">Pipeline</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">ChannelContext</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">Handler</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">Sink</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">Server端核心类</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">NioServerSocketChannelFactory</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">NioServerBossPool&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">NioWorkerPool</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">NioServerBoss</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">NioWorker</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">NioServerSocketChannel</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">NioAcceptedSocketChannel</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">DefaultChannelPipeline</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">NioServerSocketPipelineSink</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">Channels</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">ChannelFactory</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">Channel工厂，很重要的类</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">保存启动的相关参数</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">NioServerSocketChannelFactory</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">NioClientSocketChannelFactory</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">NioDatagramChannelFactory</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">这是Nio的，还有Oio和Local的</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">SelectorPool</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">Selector的线程池</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">NioServerBossPool 默认线程数：1</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">NioClientBossPool &nbsp; &nbsp; &nbsp;1</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">NioWorkerPool &nbsp; &nbsp; &nbsp;2 * Processor</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">NioDatagramWorkerPool</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">Selector</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">选择器，很核心的组件</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">NioServerBoss</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">NioClientBoss</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">NioWorker</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">NioDatagramWorker</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">Channel</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">通道</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">NioServerSocketChannel</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">NioClientSocketChannel</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">NioAcceptedSocketChannel</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">NioDatagramChannel</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">Sink</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">负责和底层的交互</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">如bind，Write，Close等</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">NioServerSocketPipelineSink</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">NioClientSocketPipelineSink</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">NioDatagramPipelineSink</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">Pipeline</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">负责维护所有的Handler</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">ChannelContext</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">一个Channel一个，是Handler和Pipeline的中间件</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">Handler</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">对Channel事件的处理器</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">ChannelPipeline</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;"><br /><img alt="" src="http://image89.360doc.com/DownloadImg/2015/10/1815/60361547_3.png" style="border: 0px;" /><br />&nbsp;<br /><img alt="" src="http://image89.360doc.com/DownloadImg/2015/10/1815/60361547_4.jpg" style="border: 0px;" /><br />&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">优秀的设计----事件驱动</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;"><br /><img alt="" src="http://image89.360doc.com/DownloadImg/2015/10/1815/60361547_5.gif" style="border: 0px;" /><br />&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">优秀的设计----线程模型</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;"><br /><img alt="" src="http://image89.360doc.com/DownloadImg/2015/10/1815/60361547_6.jpg" style="border: 0px;" /><br />&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">注意事项</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">解码时的Position</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">Channel的关闭</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">更多Handler</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">Channel的关闭</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">用完的Channel，可以直接关闭；</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">1、ChannelFuture加Listener</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">2、writeComplete</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">一段时间没用，也可以关闭</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; background-color: #ffffff;">TimeoutHandler</p><img src ="http://www.blogjava.net/paulwong/aggbug/430057.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/paulwong/" target="_blank">paulwong</a> 2016-04-12 15:19 <a href="http://www.blogjava.net/paulwong/archive/2016/04/12/430057.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>轻量级分布式 RPC 框架</title><link>http://www.blogjava.net/paulwong/archive/2016/04/12/430053.html</link><dc:creator>paulwong</dc:creator><author>paulwong</author><pubDate>Tue, 12 Apr 2016 05:44:00 GMT</pubDate><guid>http://www.blogjava.net/paulwong/archive/2016/04/12/430053.html</guid><wfw:comment>http://www.blogjava.net/paulwong/comments/430053.html</wfw:comment><comments>http://www.blogjava.net/paulwong/archive/2016/04/12/430053.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/paulwong/comments/commentRss/430053.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/paulwong/services/trackbacks/430053.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->1、每套服务需搭配一个RPCSERVER2、RPCSERVER作为SPRING&nbsp;容器的一个BEAN3、在SPRING启动的时候，RPCSERVER会启动一个NETTY服务器端，然后将SPRING...&nbsp;&nbsp;<a href='http://www.blogjava.net/paulwong/archive/2016/04/12/430053.html'>阅读全文</a><img src ="http://www.blogjava.net/paulwong/aggbug/430053.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/paulwong/" target="_blank">paulwong</a> 2016-04-12 13:44 <a href="http://www.blogjava.net/paulwong/archive/2016/04/12/430053.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Reactor模式详解</title><link>http://www.blogjava.net/paulwong/archive/2015/09/08/427190.html</link><dc:creator>paulwong</dc:creator><author>paulwong</author><pubDate>Tue, 08 Sep 2015 04:28:00 GMT</pubDate><guid>http://www.blogjava.net/paulwong/archive/2015/09/08/427190.html</guid><wfw:comment>http://www.blogjava.net/paulwong/comments/427190.html</wfw:comment><comments>http://www.blogjava.net/paulwong/archive/2015/09/08/427190.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/paulwong/comments/commentRss/427190.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/paulwong/services/trackbacks/427190.html</trackback:ping><description><![CDATA[<div style="color: #2e415c; font-family: Arial, Helvetica, sans-serif; line-height: normal; clear: both;"></div><div style="color: #2e415c; font-family: Arial, Helvetica, sans-serif; line-height: normal; clear: both;"></div><div id="article_contents_inner_6006557521" dir="ltr" style="font-family: Arial, Helvetica, sans-serif; line-height: 1.5; max-width: 650px; padding-top: 10px; padding-bottom: 10px; padding-left: 12px; word-break: break-word; color: #2e415c;"><h2>前记</h2>第一次听到Reactor模式是三年前的某个晚上，一个室友突然跑过来问我什么是Reactor模式？我上网查了一下，很多人都是给出NIO中的 Selector的例子，而且就是NIO里Selector多路复用模型，只是给它起了一个比较fancy的名字而已，虽然它引入了EventLoop概 念，这对我来说是新的概念，但是代码实现却是一样的，因而我并没有很在意这个模式。然而最近开始读Netty源码，而Reactor模式是很多介绍Netty的文章中被大肆宣传的模式，因而我再次问自己，什么是Reactor模式？本文就是对这个问题关于我的一些理解和尝试着来解答。<br /><br /><h2>什么是Reactor模式</h2>要回答这个问题，首先当然是求助Google或Wikipedia，其中Wikipedia上说：&#8220;The reactor design pattern is an event handling pattern for handling service requests delivered concurrently by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to associated request handlers.&#8221;。从这个描述中，我们知道Reactor模式首先是<strong>事件驱动的，有一个或多个并发输入源，有一个Service Handler，有多个Request Handlers</strong>；这个Service Handler会同步的将输入的请求（Event）多路复用的分发给相应的Request Handler。如果用图来表达：<br /><div style="position: relative; display: inline-block; z-index: 21; float: none;"><div id="pc_231662"  pc_first"="" title="将图片保存到 Pinterest。 点按右键可以关闭此功能。" style="position: absolute; top: 10px; left: 10px; padding-top: 5px; padding-right: 5px; padding-left: 5px; opacity: 0; border-radius: 25px; cursor: pointer; z-index: 22; transition: opacity 0.2s ease-in-out, -webkit-transform 0.2s ease-in-out; background-color: #222222;"></div><img alt="" src="http://www.blogjava.net/images/blogjava_net/dlevin/Reactor_Simple.png" height="247" width="429" style="border: 0px none; outline: none; max-width: 887px; height: auto; object-fit: contain;" /></div><br />从结构上，这有点类似生产者消费者模式，即有一个或多个生产者将事件放入一个Queue中，而一个或多个消费者主动的从这个Queue中Poll事件来处理；而Reactor模式则并没有Queue来做缓冲，每当一个Event输入到Service Handler之后，该Service Handler会主动的根据不同的Event类型将其分发给对应的Request Handler来处理。<br /><br />更学术的，这篇文章（<a href="http://www.dre.vanderbilt.edu/~schmidt/PDF/reactor-siemens.pdf" target="_blank"  bluelink"="" tabindex="-1" style="border: 0px none; outline: none; color: #296bcc;">Reactor An Object Behavioral Pattern for Demultiplexing and Dispatching Handles for Synchronous Events</a>）上说：&#8220;The Reactor design pattern handles service requests that are delivered concurrently to an application by one or more clients. Each service in an application may consistent of several methods and is represented by a separate event handler that is responsible for dispatching service-specific requests. Dispatching of event handlers is performed by an initiation dispatcher, which manages the registered event handlers. Demultiplexing of service requests is performed by a synchronous event demultiplexer. Also known as&nbsp;<strong>Dispatcher, Notifier</strong>&#8221;。这段描述和Wikipedia上的描述类似，有多个输入源，有多个不同的EventHandler（RequestHandler）来处理不同的请求，Initiation Dispatcher用于管理EventHander，EventHandler首先要注册到Initiation Dispatcher中，然后Initiation Dispatcher根据输入的Event分发给注册的EventHandler；然而Initiation Dispatcher并不监听Event的到来，这个工作交给Synchronous Event Demultiplexer来处理。<br /><h2>Reactor模式结构</h2>在解决了什么是Reactor模式后，我们来看看Reactor模式是由什么模块构成。图是一种比较简洁形象的表现方式，因而先上一张图来表达各个模块的名称和他们之间的关系：<br /><div style="position: relative; display: inline-block; z-index: 21; float: none;"><div id="pc_149929"  pc_first"="" title="将图片保存到 Pinterest。 点按右键可以关闭此功能。" style="position: absolute; top: 10px; left: 10px; padding-top: 5px; padding-right: 5px; padding-left: 5px; opacity: 0; border-radius: 25px; cursor: pointer; z-index: 22; transition: opacity 0.2s ease-in-out, -webkit-transform 0.2s ease-in-out; background-color: #222222;"></div><img alt="" src="http://www.blogjava.net/images/blogjava_net/dlevin/Reactor_Structures.png" height="266" width="401" style="border: 0px none; outline: none; max-width: 887px; height: auto; object-fit: contain;" /></div><br /><strong>Handle：</strong>即操作系统中的句柄，是对资源在操作系统层面上的一种抽象，它可以是打开的文件、一个连接(Socket)、Timer等。由于Reactor模式一般使用在网络编程中，因而这里一般指Socket Handle，即一个网络连接（Connection，在Java NIO中的Channel）。这个Channel注册到Synchronous Event Demultiplexer中，以监听Handle中发生的事件，对ServerSocketChannnel可以是CONNECT事件，对SocketChannel可以是READ、WRITE、CLOSE事件等。<br /><strong>Synchronous Event Demultiplexer：</strong>阻塞等待一系列的Handle中的事件到来，如果阻塞等待返回，即表示在返回的Handle中可以不阻塞的执行返回的事件类型。这个模块一般使用操作系统的select来实现。在Java NIO中用Selector来封装，当Selector.select()返回时，可以调用Selector的selectedKeys()方法获取Set&lt;SelectionKey&gt;，一个SelectionKey表达一个有事件发生的Channel以及该Channel上的事件类型。上图的&#8220;Synchronous Event Demultiplexer ---notifies--&gt; Handle&#8221;的流程如果是对的，那内部实现应该是select()方法在事件到来后会先设置Handle的状态，然后返回。不了解内部实现机制，因而保留原图。<br /><strong>Initiation Dispatcher：</strong>用于管理Event Handler，即EventHandler的容器，用以注册、移除EventHandler等；另外，它还作为Reactor模式的入口调用Synchronous Event Demultiplexer的select方法以阻塞等待事件返回，当阻塞等待返回时，根据事件发生的Handle将其分发给对应的Event Handler处理，即回调EventHandler中的handle_event()方法。<br /><strong>Event Handler：</strong>定义事件处理方法：handle_event()，以供InitiationDispatcher回调使用。<br /><strong>Concrete Event Handler：</strong>事件EventHandler接口，实现特定事件处理逻辑。<br /><h2>Reactor模式模块之间的交互</h2>简单描述一下Reactor各个模块之间的交互流程，先从序列图开始：<br /><div style="position: relative; display: inline-block; z-index: 21; float: none;"><div id="pc_427171"  pc_first"="" title="将图片保存到 Pinterest。 点按右键可以关闭此功能。" style="position: absolute; top: 10px; left: 10px; padding-top: 5px; padding-right: 5px; padding-left: 5px; opacity: 0; border-radius: 25px; cursor: pointer; z-index: 22; transition: opacity 0.2s ease-in-out, -webkit-transform 0.2s ease-in-out; background-color: #222222;"></div><img alt="" src="http://www.blogjava.net/images/blogjava_net/dlevin/Reactor_Sequence.png" height="222" width="385" style="border: 0px none; outline: none; max-width: 887px; height: auto; object-fit: contain;" /></div><br />1. 初始化InitiationDispatcher，并初始化一个Handle到EventHandler的Map。<br />2. 注册EventHandler到InitiationDispatcher中，每个EventHandler包含对相应Handle的引用，从而建立Handle到EventHandler的映射（Map）。<br />3. 调用InitiationDispatcher的handle_events()方法以启动Event Loop。在Event Loop中，调用select()方法（Synchronous Event Demultiplexer）阻塞等待Event发生。<br />4. 当某个或某些Handle的Event发生后，select()方法返回，InitiationDispatcher根据返回的Handle找到注册的EventHandler，并回调该EventHandler的handle_events()方法。<br />5. 在EventHandler的handle_events()方法中还可以向InitiationDispatcher中注册新的Eventhandler，比如对AcceptorEventHandler来，当有新的client连接时，它会产生新的EventHandler以处理新的连接，并注册到InitiationDispatcher中。<br /><h2>Reactor模式实现</h2>在<a href="http://www.dre.vanderbilt.edu/~schmidt/PDF/reactor-siemens.pdf" target="_blank"  bluelink"="" tabindex="-1" style="border: 0px none; outline: none; color: #296bcc;">Reactor An Object Behavioral Pattern for Demultiplexing and Dispatching Handles for Synchronous Events</a>中，一直以Logging Server来分析Reactor模式，这个Logging Server的实现完全遵循这里对Reactor描述，因而放在这里以做参考。Logging Server中的Reactor模式实现分两个部分：Client连接到Logging Server和Client向Logging Server写Log。因而对它的描述分成这两个步骤。<br /><strong>Client连接到Logging Server</strong><br /><div style="position: relative; display: inline-block; z-index: 21; float: none;"><div id="pc_993198"  pc_first"="" title="将图片保存到 Pinterest。 点按右键可以关闭此功能。" style="position: absolute; top: 10px; left: 10px; padding-top: 5px; padding-right: 5px; padding-left: 5px; opacity: 0; border-radius: 25px; cursor: pointer; z-index: 22; transition: opacity 0.2s ease-in-out, -webkit-transform 0.2s ease-in-out; background-color: #222222;"></div><img alt="" src="http://www.blogjava.net/images/blogjava_net/dlevin/Reactor_LoggingServer_connect.png" height="220" width="411" style="border: 0px none; outline: none; max-width: 887px; height: auto; object-fit: contain;" /></div><br />1. Logging Server注册LoggingAcceptor到InitiationDispatcher。<br />2. Logging Server调用InitiationDispatcher的handle_events()方法启动。<br />3. InitiationDispatcher内部调用select()方法（Synchronous Event Demultiplexer），阻塞等待Client连接。<br />4. Client连接到Logging Server。<br />5. InitiationDisptcher中的select()方法返回，并通知LoggingAcceptor有新的连接到来。&nbsp;<br />6. LoggingAcceptor调用accept方法accept这个新连接。<br />7. LoggingAcceptor创建新的LoggingHandler。<br />8. 新的LoggingHandler注册到InitiationDispatcher中(同时也注册到Synchonous Event Demultiplexer中)，等待Client发起写log请求。<br /><strong>Client向Logging Server写Log</strong><br /><div style="position: relative; display: inline-block; z-index: 21; float: none;"><div id="pc_219666"  pc_first"="" title="将图片保存到 Pinterest。 点按右键可以关闭此功能。" style="position: absolute; top: 10px; left: 10px; padding-top: 5px; padding-right: 5px; padding-left: 5px; opacity: 0; border-radius: 25px; cursor: pointer; z-index: 22; transition: opacity 0.2s ease-in-out, -webkit-transform 0.2s ease-in-out; background-color: #222222;"></div><img alt="" src="http://www.blogjava.net/images/blogjava_net/dlevin/Reactor_LoggingServer_log.png" height="265" width="413" style="border: 0px none; outline: none; max-width: 887px; height: auto; object-fit: contain;" /></div><br />1. Client发送log到Logging server。<br />2. InitiationDispatcher监测到相应的Handle中有事件发生，返回阻塞等待，根据返回的Handle找到LoggingHandler，并回调LoggingHandler中的handle_event()方法。<br />3. LoggingHandler中的handle_event()方法中读取Handle中的log信息。<br />4. 将接收到的log写入到日志文件、数据库等设备中。<br />3.4步骤循环直到当前日志处理完成。<br />5. 返回到InitiationDispatcher等待下一次日志写请求。<br /><br />在<a href="http://www.dre.vanderbilt.edu/~schmidt/PDF/reactor-siemens.pdf" target="_blank"  bluelink"="" tabindex="-1" style="border: 0px none; outline: none; color: #296bcc;">Reactor An Object Behavioral Pattern for Demultiplexing and Dispatching Handles for Synchronous Events</a>有对Reactor模式的C++的实现版本，多年不用C++，因而略过。&nbsp;<h2>Java NIO对Reactor的实现</h2>在Java的NIO中，对Reactor模式有无缝的支持，即使用Selector类封装了操作系统提供的Synchronous Event Demultiplexer功能。这个Doug Lea已经在<a href="http://gee.cs.oswego.edu/dl/cpjslides/nio.pdf" target="_blank"  bluelink"="" tabindex="-1" style="border: 0px none; outline: none; color: #296bcc;">Scalable IO In Java</a>中有非常深入的解释了，因而不再赘述，另外<a href="http://www.cnblogs.com/luxiaoxun/archive/2015/03/11/4331110.html" target="_blank"  bluelink"="" tabindex="-1" style="border: 0px none; outline: none; color: #296bcc;">这篇文章</a>对Doug Lea的<a href="http://gee.cs.oswego.edu/dl/cpjslides/nio.pdf" target="_blank"  bluelink"="" tabindex="-1" style="border: 0px none; outline: none; color: #296bcc;">Scalable IO In Java</a>有一些简单解释，至少它的代码格式比Doug Lea的PPT要整洁一些。<br /><br />需要指出的是，不同这里使用InitiationDispatcher来管理EventHandler，在Doug Lea的版本中使用SelectionKey中的Attachment来存储对应的EventHandler，因而不需要注册EventHandler这个步骤，或者设置Attachment就是这里的注册。而且在这篇文章中，Doug Lea从单线程的Reactor、Acceptor、Handler实现这个模式出发；演化为将Handler中的处理逻辑多线程化，实现类似Proactor模式，此时所有的IO操作还是单线程的，因而再演化出一个Main Reactor来处理CONNECT事件(Acceptor)，而多个Sub Reactor来处理READ、WRITE等事件(Handler)，这些Sub Reactor可以分别再自己的线程中执行，从而IO操作也多线程化。这个最后一个模型正是Netty中使用的模型。并且在<a href="http://www.dre.vanderbilt.edu/~schmidt/PDF/reactor-siemens.pdf" target="_blank"  bluelink"="" tabindex="-1" style="border: 0px none; outline: none; color: #296bcc;">Reactor An Object Behavioral Pattern for Demultiplexing and Dispatching Handles for Synchronous Events</a>的9.5 Determine the Number of Initiation Dispatchers in an Application中也有相应的描述。<br /><h2>EventHandler接口定义</h2>对EventHandler的定义有两种设计思路：single-method设计和multi-method设计：<br /><strong>A single-method interface：</strong>它将Event封装成一个Event Object，EventHandler只定义一个handle_event(Event event)方法。这种设计的好处是有利于扩展，可以后来方便的添加新的Event类型，然而在子类的实现中，需要判断不同的Event类型而再次扩展成 不同的处理方法，从这个角度上来说，它又不利于扩展。另外在Netty3的使用过程中，由于它不停的创建ChannelEvent类，因而会引起GC的不稳定。<br /><strong>A multi-method interface：</strong>这种设计是将不同的Event类型在 EventHandler中定义相应的方法。这种设计就是Netty4中使用的策略，其中一个目的是避免ChannelEvent创建引起的GC不稳定， 另外一个好处是它可以避免在EventHandler实现时判断不同的Event类型而有不同的实现，然而这种设计会给扩展新的Event类型时带来非常 大的麻烦，因为它需要该接口。<br /><br />关于Netty4对Netty3的改进可以参考<a href="http://netty.io/wiki/new-and-noteworthy-in-4.0.html" target="_blank"  bluelink"="" tabindex="-1" style="border: 0px none; outline: none; color: #296bcc;">这里</a>：<br /><strong>ChannelHandler with no event object</strong>In 3.x, every I/O operation created a&nbsp;<code style="padding: 2px 5px; font-size: 0.9em; position: relative; top: -1px; border-radius: 3px; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; background-color: #f1f5fa;">ChannelEvent</code>&nbsp;object. For each read / write, it additionally created a new&nbsp;<code style="padding: 2px 5px; font-size: 0.9em; position: relative; top: -1px; border-radius: 3px; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; background-color: #f1f5fa;">ChannelBuffer</code>. It simplified the internals of Netty quite a lot because it delegates resource management and buffer pooling to the JVM. However, it often was the root cause of GC pressure and uncertainty which are sometimes observed in a Netty-based application under high load.<p>4.0 removes event object creation almost completely by replacing the event objects with strongly typed method invocations. 3.x had catch-all event handler methods such as&nbsp;<code style="padding: 2px 5px; font-size: 0.9em; position: relative; top: -1px; border-radius: 3px; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; background-color: #f1f5fa;">handleUpstream()</code>&nbsp;and<code style="padding: 2px 5px; font-size: 0.9em; position: relative; top: -1px; border-radius: 3px; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; background-color: #f1f5fa;">handleDownstream()</code>, but this is not the case anymore. Every event type has its own handler method now:</p><h2>为什么使用Reactor模式</h2>归功与Netty和Java NIO对Reactor的宣传，本文慕名而学习的Reactor模式，因而已经默认Reactor具有非常优秀的性能，然而慕名归慕名，到这里，我还是要不得不问自己Reactor模式的好处在哪里？即为什么要使用这个Reactor模式？在<a href="http://www.dre.vanderbilt.edu/~schmidt/PDF/reactor-siemens.pdf" target="_blank"  bluelink"="" tabindex="-1" style="border: 0px none; outline: none; color: #296bcc;">Reactor An Object Behavioral Pattern for Demultiplexing and Dispatching Handles for Synchronous Events</a>中是这么说的：<br /><strong>Reactor Pattern优点</strong><div title="Page 9"><p><span style="font-size: 10pt; font-family: Times; font-weight: 700;">Separation of concerns:&nbsp;</span><span style="font-size: 10pt; font-family: Times;">The Reactor pattern decouples application-independent demultiplexing and dispatching mechanisms from application-specific hook method functionality. The application-independent mechanisms become reusable components that know how to demultiplex events and dispatch the appropriate hook methods defined by</span><span style="font-size: 10pt; font-family: Courier;">Event Handlers</span><span style="font-size: 10pt; font-family: Times;">. In contrast, the application-specific functionality in a hook method knows how to perform a particular type of service.</span></p><p><span style="font-size: 10pt; font-family: Times; font-weight: 700;">Improve modularity, reusability, and configurability of event-driven applications:&nbsp;</span><span style="font-size: 10pt; font-family: Times;">The pattern decouples application functionality into separate classes. For instance, there are two separate classes in the logging server: one for establishing connections and another for receiving and processing logging records. This decoupling enables the reuse of the connection establishment class for different types of connection-oriented services (such as file transfer, remote login, and video-on-demand). Therefore, modifying or extending the functionality of the logging server only affects the implementation of the logging handler class.</span></p></div><div title="Page 9"><p><span style="font-size: 10pt; font-family: Times; font-weight: 700;">Improves application portability:&nbsp;</span><span style="font-size: 10pt; font-family: Times;">The&nbsp;</span><span style="font-size: 10pt; font-family: Courier;">Initiation Dispatcher</span><span style="font-size: 10pt; font-family: Times;">&#8217;s interface can be reused independently of the OS system calls that perform event demultiplexing. These system calls detect and report the occurrence of one or more events that may occur simultaneously on multiple sources of events. Common sources of events may in- clude I/O handles, timers, and synchronization objects. On UNIX platforms, the event demultiplexing system calls are called</span><span style="font-size: 10pt; font-family: Courier;">select&nbsp;</span><span style="font-size: 10pt; font-family: Times;">and&nbsp;</span><span style="font-size: 10pt; font-family: Courier;">poll&nbsp;</span><span style="font-size: 10pt; font-family: Times;">[1]. In the Win32 API [16], the&nbsp;</span><span style="font-size: 10pt; font-family: Courier;">WaitForMultipleObjects&nbsp;</span><span style="font-size: 10pt; font-family: Times;">system call performs event demultiplexing.</span></p><p><span style="font-size: 10pt; font-family: Times; font-weight: 700;">Provides coarse-grained concurrency control:&nbsp;</span><span style="font-size: 10pt; font-family: Times;">The Reactor pattern serializes the invocation of event handlers at the level of event demultiplexing and dispatching within a process or thread. Serialization at the&nbsp;</span><span style="font-size: 10pt; font-family: Courier;">Initiation Dispatcher&nbsp;</span><span style="font-size: 10pt; font-family: Times;">level often eliminates the need for more complicated synchronization or locking within an application process.</span></p></div>这些貌似是很多模式的共性：解耦、提升复用性、模块化、可移植性、事件驱动、细力度的并发控制等，因而并不能很好的说明什么，特别是它鼓吹的对性能的提升，这里并没有体现出来。当然在这篇文章的开头有描述过另一种直观的实现：Thread-Per-Connection，即传统的实现，提到了这个传统实现的以下问题：<br /><strong>Thread Per Connection缺点</strong><div title="Page 1"><p><span style="font-size: 10pt; font-family: Times; font-weight: 700;">Efficiency:&nbsp;</span><span style="font-size: 10pt; font-family: Times;">Threading may lead to poor performance due to context switching, synchronization, and data movement [2];</span></p></div><div title="Page 2"><p><span style="font-size: 10pt; font-family: Times; font-weight: 700;">Programming simplicity:&nbsp;</span><span style="font-size: 10pt; font-family: Times;">Threading may require complex concurrency control schemes;</span></p></div><span style="font-size: 10pt; font-family: Times; font-weight: 700;">Portability:&nbsp;</span><span style="font-size: 10pt; font-family: Times;">Threading is not available on all OS platforms.&nbsp;</span>对于性能，它其实就是第一点关于Efficiency的描述，即线程的切换、同步、数据的移动会引起性能问题。也就是说从性能的角度上，它最大的提升就是减少了性能的使用，即不需要每个Client对应一个线程。我的理解，其他业务逻辑处理很多时候也会用到相同的线程，IO读写操作相对CPU的操作还是要慢很多，即使Reactor机制中每次读写已经能保证非阻塞读写，这里可以减少一些线程的使用，但是这减少的线程使用对性能有那么大的影响吗？答案貌似是肯定的，这篇论文(<a href="http://www.eecs.harvard.edu/~mdw/papers/seda-sosp01.pdf" target="_blank"  bluelink"="" tabindex="-1" style="border: 0px none; outline: none; color: #296bcc;">SEDA: Staged Event-Driven Architecture - An Architecture for Well-Conditioned, Scalable Internet Service</a>)对随着线程的增长带来性能降低做了一个统计：<br /><div style="position: relative; display: inline-block; z-index: 21; float: none;"><div id="pc_308492"  pc_first"="" title="将图片保存到 Pinterest。 点按右键可以关闭此功能。" style="position: absolute; top: 10px; left: 10px; padding-top: 5px; padding-right: 5px; padding-left: 5px; opacity: 0; border-radius: 25px; cursor: pointer; z-index: 22; transition: opacity 0.2s ease-in-out, -webkit-transform 0.2s ease-in-out; background-color: #222222;"></div><img alt="" src="http://www.blogjava.net/images/blogjava_net/dlevin/Reactor_thread_per_connection.png" height="482" width="407" style="border: 0px none; outline: none; max-width: 887px; height: auto; object-fit: contain;" /></div><br />在这个统计中，每个线程从磁盘中读8KB数据，每个线程读同一个文件，因而数据本身是缓存在操作系统内部的，即减少IO的影响；所有线程是事先分配的，不会有线程启动的影响；所有任务在测试内部产生，因而不会有网络的影响。该统计数据运行环境：Linux 2.2.14，2GB内存，4-way 500MHz Pentium III。从图中可以看出，随着线程的增长，吞吐量在线程数为8个左右的时候开始线性下降，并且到64个以后而迅速下降，其相应事件也在线程达到256个后指数上升。即1+1&lt;2，因为线程切换、同步、数据移动会有性能损失，线程数增加到一定数量时，这种性能影响效果会更加明显。<br /><br />对于这点，还可以参考<a href="https://en.wikipedia.org/wiki/C10k_problem" target="_blank"  bluelink"="" tabindex="-1" style="border: 0px none; outline: none; color: #296bcc;">C10K Problem</a>，用以描述同时有10K个Client发起连接的问题，到2010年的时候已经出现10M Problem了。<br /><br />当然也有人说：<a href="http://cometdaily.com/2008/11/21/are-raining-comets-and-threads/" target="_blank"  bluelink"="" tabindex="-1" style="border: 0px none; outline: none; color: #296bcc;">Threads are expensive are no longer valid</a>.在不久的将来可能又会发生不同的变化，或者这个变化正在、已经发生着？没有做过比较仔细的测试，因而不敢随便断言什么，然而本人观点，即使线程变的影响并没有以前那么大，使用Reactor模式，甚至时SEDA模式来减少线程的使用，再加上其他解耦、模块化、提升复用性等优点，还是值得使用的。<br /><h2>Reactor模式的缺点</h2>Reactor模式的缺点貌似也是显而易见的：<br />1. 相比传统的简单模型，Reactor增加了一定的复杂性，因而有一定的门槛，并且不易于调试。<br />2. Reactor模式需要底层的Synchronous Event Demultiplexer支持，比如Java中的Selector支持，操作系统的select系统调用支持，如果要自己实现Synchronous Event Demultiplexer可能不会有那么高效。<br />3. Reactor模式在IO读写数据时还是在同一个线程中实现的，即使使用多个Reactor机制的情况下，那些共享一个Reactor的Channel如果出现一个长时间的数据读写，会影响这个Reactor中其他Channel的相应时间，比如在大文件传输时，IO操作就会影响其他Client的相应时间，因而对这种操作，使用传统的Thread-Per-Connection或许是一个更好的选择，或则此时使用Proactor模式。<br /><h2>参考</h2><a href="https://en.wikipedia.org/wiki/Reactor_pattern#cite_ref-1" target="_blank"  bluelink"="" tabindex="-1" style="border: 0px none; outline: none; color: #296bcc;">Reactor Pattern WikiPedia</a><br /><a href="http://www.dre.vanderbilt.edu/~schmidt/PDF/reactor-siemens.pdf" target="_blank"  bluelink"="" tabindex="-1" style="border: 0px none; outline: none; color: #296bcc;">Reactor An Object Behavioral Pattern for Demultiplexing and Dispatching Handles for Synchronous Events</a><br /><a href="http://gee.cs.oswego.edu/dl/cpjslides/nio.pdf" target="_blank"  bluelink"="" tabindex="-1" style="border: 0px none; outline: none; color: #296bcc;">Scalable IO In Java</a><br /><a href="https://en.wikipedia.org/wiki/C10k_problem" target="_blank"  bluelink"="" tabindex="-1" style="border: 0px none; outline: none; color: #296bcc;">C10K Problem WikiPedia</a></div><img src ="http://www.blogjava.net/paulwong/aggbug/427190.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/paulwong/" target="_blank">paulwong</a> 2015-09-08 12:28 <a href="http://www.blogjava.net/paulwong/archive/2015/09/08/427190.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Netty3架构解析</title><link>http://www.blogjava.net/paulwong/archive/2015/09/08/427186.html</link><dc:creator>paulwong</dc:creator><author>paulwong</author><pubDate>Tue, 08 Sep 2015 03:11:00 GMT</pubDate><guid>http://www.blogjava.net/paulwong/archive/2015/09/08/427186.html</guid><wfw:comment>http://www.blogjava.net/paulwong/comments/427186.html</wfw:comment><comments>http://www.blogjava.net/paulwong/archive/2015/09/08/427186.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/paulwong/comments/commentRss/427186.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/paulwong/services/trackbacks/427186.html</trackback:ping><description><![CDATA[<div style="font-size: 14.7px; font-weight: bold; margin-bottom: 10px; color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; line-height: 20.7999992370605px;"></div><h2>前记</h2><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;">很早以前就有读Netty源码的打算了，然而第一次尝试的时候从Netty4开始，一直抓不到核心的框架流程，后来因为其他事情忙着就放下了。这次趁着休假重新捡起这个硬骨头，因为Netty3现在还在被很多项目使用，因而这次决定先从Netty3入手，瞬间发现Netty3的代码比Netty4中规中矩的多，很多概念在代码本身中都有清晰的表达，所以半天就把整个框架的骨架搞清楚了。再读</span><a href="http://netty.io/wiki/new-and-noteworthy-in-4.0.html" style="color: #4371a6; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;">Netty4对Netty3的改进总结</a><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;">，回去读Netty4的源码，反而觉得轻松了，一种豁然开朗的感觉。</span><br style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;" /><br style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;" /><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;">记得去年读Jetty源码的时候，因为代码太庞大，并且自己的HTTP Server的了解太少，因而只能自底向上的一个一个模块的叠加，直到最后把所以的模块连接在一起而看清它的真正核心骨架。现在读源码，开始习惯先把骨架理清，然后延伸到不同的器官、血肉而看清整个人体。</span><br style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;" /><br style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;" /><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;">本文从Reactor模式在Netty3中的应用，引出Netty3的整体架构以及控制流程；然而除了Reactor模式，Netty3还在ChannelPipeline中使用了</span><a href="http://www.blogjava.net/DLevin/archive/2015/09/03/427086.html" style="color: #4371a6; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;">Intercepting Filter</a><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;">模式，这个模式也在Servlet的Filter中成功使用，因而本文还会从Intercepting Filter模式出发详细介绍ChannelPipeline的设计理念。本文假设读者已经对Netty有一定的了解，因而不会包含过多入门介绍，以及帮Netty做宣传的文字。</span><br style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;" /><h2>Netty3中的Reactor模式</h2><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;">Reactor模式在Netty中应用非常成功，因而它也是在Netty中受大肆宣传的模式，关于Reactor模式可以详细参考本人的另一篇文章</span><a href="http://www.blogjava.net/DLevin/archive/2015/09/02/427045.html" style="color: #4371a6; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;">《Reactor模式详解》</a><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;">，对Reactor模式的实现是Netty3的基本骨架，因而本小节会详细介绍Reactor模式如何应用Netty3中。</span><br style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;" /><br style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;" /><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;">如果读《Reactor模式详解》，我们知道Reactor模式由Handle、Synchronous Event Demultiplexer、Initiation Dispatcher、Event Handler、Concrete Event Handler构成，在Java的实现版本中，Channel对应Handle，Selector对应Synchronous Event Demultiplexer，并且Netty3还使用了两层Reactor：Main Reactor用于处理Client的连接请求，Sub Reactor用于处理和Client连接后的读写请求（关于这个概念还可以参考Doug Lea的这篇PPT：</span><a href="http://gee.cs.oswego.edu/dl/cpjslides/nio.pdf" style="color: #4371a6; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;">Scalable IO In Java</a><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;">）。所以我们先要解决Netty3中使用什么类实现所有的上述模块并把他们联系在一起的，以NIO实现方式为例：</span><br style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;" /><img alt="" src="http://www.blogjava.net/images/blogjava_net/dlevin/Netty3_Architecture.png" style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;" /><br style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;" /><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;">模式是一种抽象，但是在实现中，经常会因为语言特性、框架和性能需要而做一些改变，因而Netty3对Reactor模式的实现有一套自己的设计：<br /></span><br style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;" /><strong style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;">1. ChannelEvent：</strong><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;">Reactor是基于事件编程的，因而在Netty3中使用ChannelEvent抽象的表达Netty3内部可以产生的各种事件，所有这些事件对象在Channels帮助类中产生，并且由它将事件推入到ChannelPipeline中，ChannelPipeline构建ChannelHandler管道，ChannelEvent流经这个管道实现所有的业务逻辑处理。ChannelEvent对应的事件有：ChannelStateEvent表示Channel状态的变化事件，而如果当前Channel存在Parent Channel，则该事件还会传递到Parent Channel的ChannelPipeline中，如OPEN、BOUND、CONNECTED、INTEREST_OPS等，该事件可以在各种不同实现的Channel、ChannelSink中产生；MessageEvent表示从Socket中读取数据完成、需要向Socket写数据或ChannelHandler对当前Message解析(如Decoder、Encoder)后触发的事件，它由NioWorker、需要对Message做进一步处理的ChannelHandler产生；WriteCompletionEvent表示写完成而触发的事件，它由NioWorker产生；ExceptionEvent表示在处理过程中出现的Exception，它可以发生在各个构件中，如Channel、ChannelSink、NioWorker、ChannelHandler中；IdleStateEvent由IdleStateHandler触发，这也是一个ChannelEvent可以无缝扩展的例子。注：在Netty4后，已经没有ChannelEvent类，所有不同事件都用对应方法表达，这也意味这ChannelEvent不可扩展，Netty4采用在ChannelInboundHandler中加入userEventTriggered()方法来实现这种扩展，具体可以参考</span><a href="http://netty.io/wiki/new-and-noteworthy-in-4.0.html" style="color: #4371a6; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;">这里</a><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;">。<br /></span><br style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;" /><strong style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;">2. ChannelHandler：</strong><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;">在Netty3中，ChannelHandler用于表示Reactor模式中的EventHandler。ChannelHandler只是一个标记接口，它有两个子接口：ChannelDownstreamHandler和ChannelUpstreamHandler，其中ChannelDownstreamHandler表示从用户应用程序流向Netty3内部直到向Socket写数据的管道，在Netty4中改名为ChannelOutboundHandler；ChannelUpstreamHandler表示数据从Socket进入Netty3内部向用户应用程序做数据处理的管道，在Netty4中改名为ChannelInboundHandler。<br /></span><br style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;" /><strong style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;">3. ChannelPipeline：</strong><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;">用于管理ChannelHandler的管道，每个Channel一个ChannelPipeline实例，可以运行过程中动态的向这个管道中添加、删除ChannelHandler（由于实现的限制，在最末端的ChannelHandler向后添加或删除ChannelHandler不一定在当前执行流程中起效，参考</span><a href="http://netty.io/3.10/api/org/jboss/netty/channel/ChannelPipeline.html" style="color: #4371a6; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;">这里</a><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;">）。ChannelPipeline内部维护一个ChannelHandler的双向链表，它以Upstream(Inbound)方向为正向，Downstream(Outbound)方向为方向。ChannelPipeline采用Intercepting Filter模式实现，具体可以参考</span><a href="http://www.blogjava.net/DLevin/archive/2015/09/03/427086.html" style="color: #4371a6; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;">这里</a><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;">，这个模式的实现在后一节中还是详细介绍。<br /></span><br style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;" /><strong style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;">4. NioSelector：</strong><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;">Netty3使用NioSelector来存放Selector（Synchronous Event Demultiplexer），每个新产生的NIO Channel都向这个Selector注册自己以让这个Selector监听这个NIO Channel中发生的事件，当事件发生时，调用帮助类Channels中的方法生成ChannelEvent实例，将该事件发送到这个Netty Channel对应的ChannelPipeline中，而交给各级ChannelHandler处理。其中在向Selector注册NIO Channel时，Netty Channel实例以Attachment的形式传入，该Netty Channel在其内部的NIO Channel事件发生时，会以Attachment的形式存在于SelectionKey中，因而每个事件可以直接从这个Attachment中获取相关链的Netty Channel，并从Netty Channel中获取与之相关联的ChannelPipeline，这个实现和Doug Lea的</span><a href="http://gee.cs.oswego.edu/dl/cpjslides/nio.pdf" style="color: #4371a6; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;">Scalable IO In Java</a><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;">一模一样。另外Netty3还采用了</span><a href="http://gee.cs.oswego.edu/dl/cpjslides/nio.pdf" style="color: #4371a6; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;">Scalable IO In Java</a><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;">中相同的Main Reactor和Sub Reactor设计，其中NioSelector的两个实现：Boss即为Main Reactor，NioWorker为Sub Reactor。Boss用来处理新连接加入的事件，NioWorker用来处理各个连接对Socket的读写事件，其中Boss通过NioWorkerPool获取NioWorker实例，Netty3模式使用RoundRobin方式放回NioWorker实例。更形象一点的，可以通过</span><a href="http://gee.cs.oswego.edu/dl/cpjslides/nio.pdf" style="color: #4371a6; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;">Scalable IO In Java</a><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;">的这张图表达：<br /></span><br style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;" /><img alt="" src="http://www.blogjava.net/images/blogjava_net/dlevin/Netty_Multi_Reactors.jpg" height="436" width="632" style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;" /><br style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;" /><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;">若与Ractor模式对应，NioSelector中包含了Synchronous Event Demultiplexer，而ChannelPipeline中管理着所有EventHandler，因而NioSelector和ChannelPipeline共同构成了Initiation Dispatcher。<br /></span><br style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;" /><strong style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;">5. ChannelSink：</strong><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;">在ChannelHandler处理完成所有逻辑需要向客户端写响应数据时，一般会调用Netty Channel中的write方法，然而在这个write方法实现中，它不是直接向其内部的Socket写数据，而是交给Channels帮助类，内部创建DownstreamMessageEvent，反向从ChannelPipeline的管道中流过去，直到第一个ChannelHandler处理完毕，最后交给ChannelSink处理，以避免阻塞写而影响程序的吞吐量。ChannelSink将这个MessageEvent提交给Netty Channel中的writeBufferQueue，最后NioWorker会等到这个NIO Channel已经可以处理写事件时无阻塞的向这个NIO Channel写数据。这就是上图的send是从SubReactor直接出发的原因。<br /></span><br style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;" /><strong style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;">6. Channel：</strong><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;">Netty有自己的Channel抽象，它是一个资源的容器，包含了所有一个连接涉及到的所有资源的饮用，如封装NIO Channel、ChannelPipeline、Boss、NioWorkerPool等。另外它还提供了向内部NIO Channel写响应数据的接口write、连接/绑定到某个地址的connect/bind接口等，个人感觉虽然对Channel本身来说，因为它封装了NIO Channel，因而这些接口定义在这里是合理的，但是如果考虑到Netty的架构，它的Channel只是一个资源容器，有这个Channel实例就可以得到和它相关的基本所有资源，因而这种write、connect、bind动作不应该再由它负责，而是应该由其他类来负责，比如在Netty4中就在ChannelHandlerContext添加了write方法，虽然netty4并没有删除Channel中的write接口。</span><br style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;" /><h2>Netty3中的Intercepting Filter模式</h2><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;">如果说Reactor模式是Netty3的骨架，那么Intercepting Filter模式则是Netty的中枢。Reactor模式主要应用在Netty3的内部实现，它是Netty3具有良好性能的基础，而Intercepting Filter模式则是ChannelHandler组合实现一个应用程序逻辑的基础，只有很好的理解了这个模式才能使用好Netty，甚至能得心应手。</span><br style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;" /><br style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;" /><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;">关于Intercepting Filter模式的详细介绍可以参考</span><a href="http://www.blogjava.net/DLevin/archive/2015/09/03/427086.html" style="color: #4371a6; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;">这里</a><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;">，本节主要介绍Netty3中对Intercepting Filter模式的实现，其实就是DefaultChannelPipeline对Intercepting Filter模式的实现。在上文有提到Netty3的ChannelPipeline是ChannelHandler的容器，用于存储与管理ChannelHandler，同时它在Netty3中也起到桥梁的作用，即它是连接Netty3内部到所有ChannelHandler的桥梁。作为ChannelPipeline的实现者DefaultChannelPipeline，它使用一个ChannelHandler的双向链表来存储，以DefaultChannelPipelineContext作为节点：<br /><br /></span><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">interface</span>&nbsp;ChannelHandlerContext&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;Channel&nbsp;getChannel();<br />&nbsp;&nbsp;&nbsp;&nbsp;ChannelPipeline&nbsp;getPipeline();<br />&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;getName();<br />&nbsp;&nbsp;&nbsp;&nbsp;ChannelHandler&nbsp;getHandler();<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">boolean</span>&nbsp;canHandleUpstream();<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">boolean</span>&nbsp;canHandleDownstream();<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;sendUpstream(ChannelEvent&nbsp;e);<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;sendDownstream(ChannelEvent&nbsp;e);<br />&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;getAttachment();<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;setAttachment(Object&nbsp;attachment);<br />}<br /><br /><span style="color: #0000FF; ">private</span>&nbsp;<span style="color: #0000FF; ">final</span>&nbsp;<span style="color: #0000FF; ">class</span>&nbsp;DefaultChannelHandlerContext&nbsp;<span style="color: #0000FF; ">implements</span>&nbsp;ChannelHandlerContext&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">volatile</span>&nbsp;DefaultChannelHandlerContext&nbsp;next;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">volatile</span>&nbsp;DefaultChannelHandlerContext&nbsp;prev;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;<span style="color: #0000FF; ">final</span>&nbsp;String&nbsp;name;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;<span style="color: #0000FF; ">final</span>&nbsp;ChannelHandler&nbsp;handler;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;<span style="color: #0000FF; ">final</span>&nbsp;<span style="color: #0000FF; ">boolean</span>&nbsp;canHandleUpstream;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;<span style="color: #0000FF; ">final</span>&nbsp;<span style="color: #0000FF; ">boolean</span>&nbsp;canHandleDownstream;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;<span style="color: #0000FF; ">volatile</span>&nbsp;Object&nbsp;attachment;<br /><img src="http://www.blogjava.net/Images/dot.gif"  alt="" />..<br />}</div><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;"><br />在DefaultChannelPipeline中，它存储了和当前ChannelPipeline相关联的Channel、ChannelSink以及ChannelHandler链表的head、tail，所有ChannelEvent通过sendUpstream、sendDownstream为入口流经整个链表：<br /><br /></span><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">class</span>&nbsp;DefaultChannelPipeline&nbsp;<span style="color: #0000FF; ">implements</span>&nbsp;ChannelPipeline&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;<span style="color: #0000FF; ">volatile</span>&nbsp;Channel&nbsp;channel;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;<span style="color: #0000FF; ">volatile</span>&nbsp;ChannelSink&nbsp;sink;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;<span style="color: #0000FF; ">volatile</span>&nbsp;DefaultChannelHandlerContext&nbsp;head;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;<span style="color: #0000FF; ">volatile</span>&nbsp;DefaultChannelHandlerContext&nbsp;tail;<br /><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;sendUpstream(ChannelEvent&nbsp;e)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DefaultChannelHandlerContext&nbsp;head&nbsp;=&nbsp;getActualUpstreamContext(<span style="color: #0000FF; ">this</span>.head);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(head&nbsp;==&nbsp;<span style="color: #0000FF; ">null</span>)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sendUpstream(head,&nbsp;e);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;sendUpstream(DefaultChannelHandlerContext&nbsp;ctx,&nbsp;ChannelEvent&nbsp;e)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">try</span>&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((ChannelUpstreamHandler)&nbsp;ctx.getHandler()).handleUpstream(ctx,&nbsp;e);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">catch</span>&nbsp;(Throwable&nbsp;t)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;notifyHandlerException(e,&nbsp;t);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;sendDownstream(ChannelEvent&nbsp;e)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DefaultChannelHandlerContext&nbsp;tail&nbsp;=&nbsp;getActualDownstreamContext(<span style="color: #0000FF; ">this</span>.tail);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(tail&nbsp;==&nbsp;<span style="color: #0000FF; ">null</span>)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">try</span>&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getSink().eventSunk(<span style="color: #0000FF; ">this</span>,&nbsp;e);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">catch</span>&nbsp;(Throwable&nbsp;t)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;notifyHandlerException(e,&nbsp;t);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sendDownstream(tail,&nbsp;e);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;sendDownstream(DefaultChannelHandlerContext&nbsp;ctx,&nbsp;ChannelEvent&nbsp;e)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(e&nbsp;<span style="color: #0000FF; ">instanceof</span>&nbsp;UpstreamMessageEvent)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">throw</span>&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;IllegalArgumentException("cannot&nbsp;send&nbsp;an&nbsp;upstream&nbsp;event&nbsp;to&nbsp;downstream");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">try</span>&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((ChannelDownstreamHandler)&nbsp;ctx.getHandler()).handleDownstream(ctx,&nbsp;e);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">catch</span>&nbsp;(Throwable&nbsp;t)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.getFuture().setFailure(t);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;notifyHandlerException(e,&nbsp;t);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}</div><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;"><br />对Upstream事件，向后找到所有实现了ChannelUpstreamHandler接口的ChannelHandler组成链（</span><span style="font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;">getActualUpstreamContext()）</span><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;">，而对Downstream事件，向前找到所有实现了ChannelDownstreamHandler接口的ChannelHandler组成链（</span><span style="font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;">getActualDownstreamContext()</span><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;">）：<br /><br /></span><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->&nbsp; &nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;DefaultChannelHandlerContext&nbsp;getActualUpstreamContext(DefaultChannelHandlerContext&nbsp;ctx)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(ctx&nbsp;==&nbsp;<span style="color: #0000FF; ">null</span>)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">null</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DefaultChannelHandlerContext&nbsp;realCtx&nbsp;=&nbsp;ctx;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;(!realCtx.canHandleUpstream())&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;realCtx&nbsp;=&nbsp;realCtx.next;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(realCtx&nbsp;==&nbsp;<span style="color: #0000FF; ">null</span>)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">null</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;realCtx;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;DefaultChannelHandlerContext&nbsp;getActualDownstreamContext(DefaultChannelHandlerContext&nbsp;ctx)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(ctx&nbsp;==&nbsp;<span style="color: #0000FF; ">null</span>)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">null</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DefaultChannelHandlerContext&nbsp;realCtx&nbsp;=&nbsp;ctx;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;(!realCtx.canHandleDownstream())&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;realCtx&nbsp;=&nbsp;realCtx.prev;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(realCtx&nbsp;==&nbsp;<span style="color: #0000FF; ">null</span>)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">null</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;realCtx;<br />&nbsp;&nbsp;&nbsp;&nbsp;}</div><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;"><br />在实际实现ChannelUpstreamHandler或ChannelDownstreamHandler时，调用 ChannelHandlerContext中的sendUpstream或sendDownstream方法将控制流程交给下一个 ChannelUpstreamHandler或下一个ChannelDownstreamHandler，或调用Channel中的write方法发送 响应消息。<br /><br /></span><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">class</span>&nbsp;MyChannelUpstreamHandler&nbsp;<span style="color: #0000FF; ">implements</span>&nbsp;ChannelUpstreamHandler&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;handleUpstream(ChannelHandlerContext&nbsp;ctx,&nbsp;ChannelEvent&nbsp;e)&nbsp;<span style="color: #0000FF; ">throws</span>&nbsp;Exception&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;handle&nbsp;current&nbsp;logic,&nbsp;use&nbsp;Channel&nbsp;to&nbsp;write&nbsp;response&nbsp;if&nbsp;needed.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;ctx.getChannel().write(message);</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ctx.sendUpstream(e);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /><br /><span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">class</span>&nbsp;MyChannelDownstreamHandler&nbsp;<span style="color: #0000FF; ">implements</span>&nbsp;ChannelDownstreamHandler&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;handleDownstream(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ChannelHandlerContext&nbsp;ctx,&nbsp;ChannelEvent&nbsp;e)&nbsp;<span style="color: #0000FF; ">throws</span>&nbsp;Exception&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;handle&nbsp;current&nbsp;logic</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ctx.sendDownstream(e);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}</div><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;"><br />当ChannelHandler向ChannelPipelineContext发送事件时，其内部从当前ChannelPipelineContext节点出发找到下一个ChannelUpstreamHandler或ChannelDownstreamHandler实例，并向其发送ChannelEvent，对于Downstream链，如果到达链尾，则将ChannelEvent发送给ChannelSink：<br /><br /></span><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;sendDownstream(ChannelEvent&nbsp;e)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;DefaultChannelHandlerContext&nbsp;prev&nbsp;=&nbsp;getActualDownstreamContext(<span style="color: #0000FF; ">this</span>.prev);<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(prev&nbsp;==&nbsp;<span style="color: #0000FF; ">null</span>)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">try</span>&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getSink().eventSunk(DefaultChannelPipeline.<span style="color: #0000FF; ">this</span>,&nbsp;e);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">catch</span>&nbsp;(Throwable&nbsp;t)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;notifyHandlerException(e,&nbsp;t);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DefaultChannelPipeline.<span style="color: #0000FF; ">this</span>.sendDownstream(prev,&nbsp;e);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /><br /><span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;sendUpstream(ChannelEvent&nbsp;e)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;DefaultChannelHandlerContext&nbsp;next&nbsp;=&nbsp;getActualUpstreamContext(<span style="color: #0000FF; ">this</span>.next);<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(next&nbsp;!=&nbsp;<span style="color: #0000FF; ">null</span>)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DefaultChannelPipeline.<span style="color: #0000FF; ">this</span>.sendUpstream(next,&nbsp;e);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}</div><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;"><br />正是因为这个实现，如果在一个末尾的ChannelUpstreamHandler中先移除自己，在向末尾添加一个新的ChannelUpstreamHandler，它是无效的，因为它的next已经在调用前就固定设置为null了。</span><br style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;" /><br style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;" /><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;">ChannelPipeline作为ChannelHandler的容器，它还提供了各种增、删、改ChannelHandler链表中的方法，而且如果某个ChannelHandler还实现了LifeCycleAwareChannelHandler，则该ChannelHandler在被添加进ChannelPipeline或从中删除时都会得到同志：<br /><br /></span><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">interface</span>&nbsp;LifeCycleAwareChannelHandler&nbsp;<span style="color: #0000FF; ">extends</span>&nbsp;ChannelHandler&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;beforeAdd(ChannelHandlerContext&nbsp;ctx)&nbsp;<span style="color: #0000FF; ">throws</span>&nbsp;Exception;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;afterAdd(ChannelHandlerContext&nbsp;ctx)&nbsp;<span style="color: #0000FF; ">throws</span>&nbsp;Exception;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;beforeRemove(ChannelHandlerContext&nbsp;ctx)&nbsp;<span style="color: #0000FF; ">throws</span>&nbsp;Exception;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;afterRemove(ChannelHandlerContext&nbsp;ctx)&nbsp;<span style="color: #0000FF; ">throws</span>&nbsp;Exception;<br />}<br /><br /><span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">interface</span>&nbsp;ChannelPipeline&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;addFirst(String&nbsp;name,&nbsp;ChannelHandler&nbsp;handler);<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;addLast(String&nbsp;name,&nbsp;ChannelHandler&nbsp;handler);<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;addBefore(String&nbsp;baseName,&nbsp;String&nbsp;name,&nbsp;ChannelHandler&nbsp;handler);<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;addAfter(String&nbsp;baseName,&nbsp;String&nbsp;name,&nbsp;ChannelHandler&nbsp;handler);<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;remove(ChannelHandler&nbsp;handler);<br />&nbsp;&nbsp;&nbsp;&nbsp;ChannelHandler&nbsp;remove(String&nbsp;name);<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;T&nbsp;<span style="color: #0000FF; ">extends</span>&nbsp;ChannelHandler&gt;&nbsp;T&nbsp;remove(Class&lt;T&gt;&nbsp;handlerType);<br />&nbsp;&nbsp;&nbsp;&nbsp;ChannelHandler&nbsp;removeFirst();<br />&nbsp;&nbsp;&nbsp;&nbsp;ChannelHandler&nbsp;removeLast();<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;replace(ChannelHandler&nbsp;oldHandler,&nbsp;String&nbsp;newName,&nbsp;ChannelHandler&nbsp;newHandler);<br />&nbsp;&nbsp;&nbsp;&nbsp;ChannelHandler&nbsp;replace(String&nbsp;oldName,&nbsp;String&nbsp;newName,&nbsp;ChannelHandler&nbsp;newHandler);<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;T&nbsp;<span style="color: #0000FF; ">extends</span>&nbsp;ChannelHandler&gt;&nbsp;T&nbsp;replace(Class&lt;T&gt;&nbsp;oldHandlerType,&nbsp;String&nbsp;newName,&nbsp;ChannelHandler&nbsp;newHandler);<br />&nbsp;&nbsp;&nbsp;&nbsp;ChannelHandler&nbsp;getFirst();<br />&nbsp;&nbsp;&nbsp;&nbsp;ChannelHandler&nbsp;getLast();<br />&nbsp;&nbsp;&nbsp;&nbsp;ChannelHandler&nbsp;get(String&nbsp;name);<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;T&nbsp;<span style="color: #0000FF; ">extends</span>&nbsp;ChannelHandler&gt;&nbsp;T&nbsp;get(Class&lt;T&gt;&nbsp;handlerType);<br />&nbsp;&nbsp;&nbsp;&nbsp;ChannelHandlerContext&nbsp;getContext(ChannelHandler&nbsp;handler);<br />&nbsp;&nbsp;&nbsp;&nbsp;ChannelHandlerContext&nbsp;getContext(String&nbsp;name);<br />&nbsp;&nbsp;&nbsp;&nbsp;ChannelHandlerContext&nbsp;getContext(Class&lt;?&nbsp;<span style="color: #0000FF; ">extends</span>&nbsp;ChannelHandler&gt;&nbsp;handlerType);<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;sendUpstream(ChannelEvent&nbsp;e);<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;sendDownstream(ChannelEvent&nbsp;e);<br />&nbsp;&nbsp;&nbsp;&nbsp;ChannelFuture&nbsp;execute(Runnable&nbsp;task);<br />&nbsp;&nbsp;&nbsp;&nbsp;Channel&nbsp;getChannel();<br />&nbsp;&nbsp;&nbsp;&nbsp;ChannelSink&nbsp;getSink();<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;attach(Channel&nbsp;channel,&nbsp;ChannelSink&nbsp;sink);<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">boolean</span>&nbsp;isAttached();<br />&nbsp;&nbsp;&nbsp;&nbsp;List&lt;String&gt;&nbsp;getNames();<br />&nbsp;&nbsp;&nbsp;&nbsp;Map&lt;String,&nbsp;ChannelHandler&gt;&nbsp;toMap();<br />}</div><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;"><br /></span><span style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px; background-color: #ffffff;">在DefaultChannelPipeline的ChannelHandler链条的处理流程为：</span><br style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;" /><img alt="" src="http://www.blogjava.net/images/blogjava_net/dlevin/Netty_ChannelPipeline.png" height="409" width="968" style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;" /><br /><br /><a href="http://www.blogjava.net/DLevin/archive/2015/09/04/427031.html" target="_blank">http://www.blogjava.net/DLevin/archive/2015/09/04/427031.html</a><br style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;" /><h2><a target="null"></a><br />参考：</h2><a href="http://netty.io/index.html" style="color: #4371a6; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;">《Netty主页》</a><br style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;" /><a href="http://ifeve.com/netty-reactor-4/" style="color: #4371a6; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;">《Netty源码解读（四）Netty与Reactor模式》</a><br style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;" /><a href="http://jm-blog.aliapp.com/?p=423" style="color: #4371a6; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;">《Netty代码分析》</a><br style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;" /><a href="http://gee.cs.oswego.edu/dl/cpjslides/nio.pdf" style="color: #4371a6; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;">Scalable IO In Java</a><br style="color: #4b4b4b; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;" /><a href="http://www.oracle.com/technetwork/java/interceptingfilter-142169.html" style="color: #4371a6; font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20.7999992370605px;">Intercepting Filter Pattern</a><img src ="http://www.blogjava.net/paulwong/aggbug/427186.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/paulwong/" target="_blank">paulwong</a> 2015-09-08 11:11 <a href="http://www.blogjava.net/paulwong/archive/2015/09/08/427186.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>100万并发连接服务器笔记之Java Netty处理1M连接会怎么样</title><link>http://www.blogjava.net/paulwong/archive/2015/07/13/426202.html</link><dc:creator>paulwong</dc:creator><author>paulwong</author><pubDate>Mon, 13 Jul 2015 10:26:00 GMT</pubDate><guid>http://www.blogjava.net/paulwong/archive/2015/07/13/426202.html</guid><wfw:comment>http://www.blogjava.net/paulwong/comments/426202.html</wfw:comment><comments>http://www.blogjava.net/paulwong/archive/2015/07/13/426202.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/paulwong/comments/commentRss/426202.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/paulwong/services/trackbacks/426202.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 前言每一种该语言在某些极限情况下的表现一般都不太一样，那么我常用的Java语言，在达到100万个并发连接情况下，会怎么样呢，有些好奇，更有些期盼。这次使用经常使用的顺手的netty&nbsp;NIO框架（netty-3.6.5.Final），封装的很好，接口很全面，就像它现在的域名&nbsp;netty.io，专注于网络IO。整个过程没有什么技术含量，浅显分析过就更显得有些枯燥无聊，准备好，硬着头...&nbsp;&nbsp;<a href='http://www.blogjava.net/paulwong/archive/2015/07/13/426202.html'>阅读全文</a><img src ="http://www.blogjava.net/paulwong/aggbug/426202.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/paulwong/" target="_blank">paulwong</a> 2015-07-13 18:26 <a href="http://www.blogjava.net/paulwong/archive/2015/07/13/426202.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>轻量级、高性能NIO网络通讯框架（around 60K）-zbus</title><link>http://www.blogjava.net/paulwong/archive/2015/04/22/424600.html</link><dc:creator>paulwong</dc:creator><author>paulwong</author><pubDate>Wed, 22 Apr 2015 07:53:00 GMT</pubDate><guid>http://www.blogjava.net/paulwong/archive/2015/04/22/424600.html</guid><wfw:comment>http://www.blogjava.net/paulwong/comments/424600.html</wfw:comment><comments>http://www.blogjava.net/paulwong/archive/2015/04/22/424600.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/paulwong/comments/commentRss/424600.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/paulwong/services/trackbacks/424600.html</trackback:ping><description><![CDATA[轻量级、高性能NIO网络通讯框架（around&nbsp;60K），zbus通讯基础&nbsp;&#8212;&#8212;&nbsp;查看更多<br /><a href="qq://txfile/#">http://git.oschina.net/rushmore/zbus</a><br /><br />为什么没有选择netty或者mina？<br />个人观点：netty与mina过于庞大，需要学习的成本比较高，debug中的chain过长，自己不方便改写<img src ="http://www.blogjava.net/paulwong/aggbug/424600.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/paulwong/" target="_blank">paulwong</a> 2015-04-22 15:53 <a href="http://www.blogjava.net/paulwong/archive/2015/04/22/424600.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>commonrpc 0.1 发布，高性能分布式 RPC 框架</title><link>http://www.blogjava.net/paulwong/archive/2015/03/12/423414.html</link><dc:creator>paulwong</dc:creator><author>paulwong</author><pubDate>Thu, 12 Mar 2015 11:02:00 GMT</pubDate><guid>http://www.blogjava.net/paulwong/archive/2015/03/12/423414.html</guid><wfw:comment>http://www.blogjava.net/paulwong/comments/423414.html</wfw:comment><comments>http://www.blogjava.net/paulwong/archive/2015/03/12/423414.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/paulwong/comments/commentRss/423414.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/paulwong/services/trackbacks/423414.html</trackback:ping><description><![CDATA[<span style="color: rgba(0, 0, 0, 0.8); font-family: Lato, 'Helvetica Neue', 'Microsoft YaHei', Arial, Helvetica, sans-serif; font-size: 15px; line-height: 19.9500007629395px; background-color: #fafafa;">还在羡慕BAT，京东等公司的大流量的架构吗？让你的java系统引用解耦，互相独立,commonrpc 就可以办到。commonrpc 是一个以netty为基础，spring 自定义shcema为基础标签的rpc框架,不侵入任何业务代码，一个高性能分布式rpc框架，支持tcp协议,http协议,同时HTTP协议支持restful 方式访问.</span><div style="box-sizing: inherit; color: rgba(0, 0, 0, 0.8); font-family: Lato, 'Helvetica Neue', 'Microsoft YaHei', Arial, Helvetica, sans-serif; font-size: 15px; line-height: 19.9500007629395px; background-color: #fafafa;"><a href="http://git.oschina.net/284520459/commonrpc/wikis/home" rel="nofollow" style="box-sizing: inherit; color: #4183c4; text-decoration: none; cursor: pointer !important; background: transparent;" target="_blank">http://git.oschina.net/284520459/commonrpc/wikis/home</a></div><img src ="http://www.blogjava.net/paulwong/aggbug/423414.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/paulwong/" target="_blank">paulwong</a> 2015-03-12 19:02 <a href="http://www.blogjava.net/paulwong/archive/2015/03/12/423414.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>NETTY资源</title><link>http://www.blogjava.net/paulwong/archive/2015/02/26/423039.html</link><dc:creator>paulwong</dc:creator><author>paulwong</author><pubDate>Thu, 26 Feb 2015 01:49:00 GMT</pubDate><guid>http://www.blogjava.net/paulwong/archive/2015/02/26/423039.html</guid><wfw:comment>http://www.blogjava.net/paulwong/comments/423039.html</wfw:comment><comments>http://www.blogjava.net/paulwong/archive/2015/02/26/423039.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/paulwong/comments/commentRss/423039.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/paulwong/services/trackbacks/423039.html</trackback:ping><description><![CDATA[<a href="http://blog.csdn.net/u013252773/article/details/21046697" style="color: #333333; text-decoration: none; font-family: 'Microsoft YaHei'; font-size: 20px; line-height: 30px; background-color: #ffffff;" target="_blank">Netty4.0学习笔记系列之一：Server与Client的通讯</a><br />
<br />
<a href="http://blog.csdn.net/u013252773/article/details/21195593" style="color: #333333; text-decoration: none; font-family: 'Microsoft YaHei'; font-size: 20px; line-height: 30px; background-color: #ffffff;" target="_blank">Netty4.0学习笔记系列之二：Handler的执行顺序</a><br />
<br />
<br />
<a href="http://blog.csdn.net/u013252773/article/details/21254257" style="color: #333333; text-decoration: none; font-family: 'Microsoft YaHei'; font-size: 20px; line-height: 30px; background-color: #ffffff;" target="_blank">Netty4.0学习笔记系列之三：构建简单的http服务</a><br />
<br />
<br />
<a href="http://blog.csdn.net/u013252773/article/details/21564301" style="color: #333333; text-decoration: none; font-family: 'Microsoft YaHei'; font-size: 20px; line-height: 30px; background-color: #ffffff;" target="_blank">Netty4.0学习笔记系列之四：混合使用coder和handler</a><br />
<br />
<br />
<a href="http://blog.csdn.net/u013252773/article/details/21608951" style="color: #333333; text-decoration: none; font-family: 'Microsoft YaHei'; font-size: 20px; line-height: 30px; background-color: #ffffff;" target="_blank">Netty4.0学习笔记系列之五：自定义通讯协议<br />
<br />
</a><a href="http://blog.csdn.net/u013252773/article/details/22108385" style="color: #333333; text-decoration: none;" target="_blank">Netty4.0学习笔记系列之六：多种通讯协议支持</a><br />
<br />
<br />
<span style="color: red;">NETTY HTTP JAX-RS服务器</span><br />
<a href="https://github.com/continuuity/netty-http" target="_blank">https://github.com/continuuity/netty-http<br />
</a>
<br />
netty和tomcat的hello world性能比较<br />
<a href="http://my.oschina.net/u/2302546/blog/368685" target="_blank">http://my.oschina.net/u/2302546/blog/368685</a>
<br /><br /><h1><a href="http://www.oschina.net/question/1765708_158026" hidefocus="true" name="top" style="padding: 0px; margin: 0px; color: #000000; outline: 0px; text-decoration: none;" target="_blank">nginx+tomcat与netty优缺点</a></h1><br />NETTY官方EXAMPLE<br /><a href="https://github.com/netty/netty/tree/4.0/example/src/main/java/io/netty/example" target="_blank">https://github.com/netty/netty/tree/4.0/example/src/main/java/io/netty/example</a><br /><br /><br /><img src ="http://www.blogjava.net/paulwong/aggbug/423039.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/paulwong/" target="_blank">paulwong</a> 2015-02-26 09:49 <a href="http://www.blogjava.net/paulwong/archive/2015/02/26/423039.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>