??xml version="1.0" encoding="utf-8" standalone="yes"?>青青伊人久久,濑亚美莉一二区在线视频 ,在线的色视频http://www.aygfsteel.com/paulwong/category/54729.htmlzh-cnWed, 02 Dec 2020 14:17:25 GMTWed, 02 Dec 2020 14:17:25 GMT60史上最通俗Netty入门长文Q基本介l、环境搭建、动手实?/title><link>http://www.aygfsteel.com/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.aygfsteel.com/paulwong/archive/2020/12/02/435738.html</guid><wfw:comment>http://www.aygfsteel.com/paulwong/comments/435738.html</wfw:comment><comments>http://www.aygfsteel.com/paulwong/archive/2020/12/02/435738.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/paulwong/comments/commentRss/435738.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/paulwong/services/trackbacks/435738.html</trackback:ping><description><![CDATA[<a href="http://www.aygfsteel.com/jb2011/archive/2020/11/18/435727.html" target="_blank">http://www.aygfsteel.com/jb2011/archive/2020/11/18/435727.html</a><img src ="http://www.aygfsteel.com/paulwong/aggbug/435738.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/paulwong/" target="_blank">paulwong</a> 2020-12-02 09:15 <a href="http://www.aygfsteel.com/paulwong/archive/2020/12/02/435738.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SPRING MVC整合NETTYhttp://www.aygfsteel.com/paulwong/archive/2016/04/19/430146.htmlpaulwongpaulwongTue, 19 Apr 2016 05:27:00 GMThttp://www.aygfsteel.com/paulwong/archive/2016/04/19/430146.htmlhttp://www.aygfsteel.com/paulwong/comments/430146.htmlhttp://www.aygfsteel.com/paulwong/archive/2016/04/19/430146.html#Feedback0http://www.aygfsteel.com/paulwong/comments/commentRss/430146.htmlhttp://www.aygfsteel.com/paulwong/services/trackbacks/430146.htmlhttp://wenku.baidu.com/view/4573aba4ce2f0066f53322e8.html

paulwong 2016-04-19 13:27 发表评论
]]>
Netty是什么?http://www.aygfsteel.com/paulwong/archive/2016/04/12/430057.htmlpaulwongpaulwongTue, 12 Apr 2016 07:19:00 GMThttp://www.aygfsteel.com/paulwong/archive/2016/04/12/430057.htmlhttp://www.aygfsteel.com/paulwong/comments/430057.htmlhttp://www.aygfsteel.com/paulwong/archive/2016/04/12/430057.html#Feedback0http://www.aygfsteel.com/paulwong/comments/commentRss/430057.htmlhttp://www.aygfsteel.com/paulwong/services/trackbacks/430057.html本质QJBoss做的一个Jar?/p>

 

目的Q快速开发高性能、高可靠性的|络服务器和客户端程?/p>

 

优点Q提供异步的、事仉动的|络应用E序框架和工?/p>

 

通俗的说Q一个好使的处理Socket的东?/p>

 

 

如果没有NettyQ?/p>

 

q古Qjava.net + java.io

 

q代Qjava.nio

 

其他QMinaQGrizzly

 

Z么不是MinaQ?/p>

 

1、都是Trustin Lee的作品,Netty更晚Q?/p>

2、Mina内核和一些特性的联系q于紧密Q得用户在不需要这些特性的时候无法脱,相比下性能会有所下降QNetty解决了这个设计问题;

3、Netty的文档更清晰Q很多Mina的特性在Netty里都有;

4、Netty更新周期更短Q新版本的发布比较快Q?/p>

5、它们的架构差别不大QMina靠apache生存Q而Netty靠jbossQ和jboss的结合度非常高,Netty有对google protocal buf的支持,有更完整的ioc容器支持(spring,guice,jbossmc和osgi)Q?/p>

6、Netty比Mina使用h更简单,Netty里你可以自定义的处理upstream events ??downstream eventsQ可以用decoder和encoder来解码和~码发送内容;

7、Netty和Mina在处理UDP时有一些不同,NettyUDP无连接的Ҏ暴露出来;而Mina对UDPq行了高U层ơ的抽象Q可以把UDP当成"面向q接"的协议,而要Netty做到q一Ҏ较困难?/p>

 

 

Netty的特?/p>

 

设计

l一的APIQ适用于不同的协议Q阻塞和非阻塞)

Z灉|、可扩展的事仉动模?/p>

高度可定制的U程模型

可靠的无q接数据Socket支持QUDPQ?/p>

 

性能

更好的吞吐量Q低延迟

更省资源

量减少不必要的内存拯

 

安全

完整的SSL/TLS和STARTTLS的支?/p>

能在Applet与Android的限制环境运行良?/p>

 

健壮?/p>

不再因过快、过慢或负载连接导致OutOfMemoryError

不再有在高速网l环境下NIOd频率不一致的问题

 

易用

完善的JavaDocQ用h南和样例

z简?/p>

仅信赖于JDK1.5

 

看例子吧Q?/p>

 

Server端:

 

Java代码  收藏代码
  1. package me.hello.netty;  
  2.   
  3. import org.jboss.netty.bootstrap.ServerBootstrap;  
  4. import org.jboss.netty.channel.*;  
  5. import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;  
  6. import org.jboss.netty.handler.codec.string.StringDecoder;  
  7. import org.jboss.netty.handler.codec.string.StringEncoder;  
  8.   
  9. import java.net.InetSocketAddress;  
  10. import java.util.concurrent.Executors;  
  11.   
  12. /** 
  13.  * God Bless You! 
  14.  * Author: Fangniude 
  15.  * Date: 2013-07-15 
  16.  */  
  17. public class NettyServer {  
  18.     public static void main(String[] args) {  
  19.         ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));  
  20.   
  21.         // Set up the default event pipeline.  
  22.         bootstrap.setPipelineFactory(new ChannelPipelineFactory() {  
  23.             @Override  
  24.             public ChannelPipeline getPipeline() throws Exception {  
  25.                 return Channels.pipeline(new StringDecoder(), new StringEncoder(), new ServerHandler());  
  26.             }  
  27.         });  
  28.   
  29.         // Bind and start to accept incoming connections.  
  30.         Channel bind = bootstrap.bind(new InetSocketAddress(8000));  
  31.         System.out.println("Server已经启动Q监听端? " + bind.getLocalAddress() + "Q?nbsp;{待客户端注册。。?);  
  32.     }  
  33.   
  34.     private static class ServerHandler extends SimpleChannelHandler {  
  35.         @Override  
  36.         public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {  
  37.             if (e.getMessage() instanceof String) {  
  38.                 String message = (String) e.getMessage();  
  39.                 System.out.println("Client发来:" + message);  
  40.   
  41.                 e.getChannel().write("Server已收到刚发送的:" + message);  
  42.   
  43.                 System.out.println("\n{待客户端输入。。?);  
  44.             }  
  45.   
  46.             super.messageReceived(ctx, e);  
  47.         }  
  48.   
  49.         @Override  
  50.         public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {  
  51.             super.exceptionCaught(ctx, e);  
  52.         }  
  53.   
  54.         @Override  
  55.         public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {  
  56.             System.out.println("有一个客L注册上来了。。?);  
  57.             System.out.println("Client:" + e.getChannel().getRemoteAddress());  
  58.             System.out.println("Server:" + e.getChannel().getLocalAddress());  
  59.             System.out.println("\n{待客户端输入。。?);  
  60.             super.channelConnected(ctx, e);  
  61.         }  
  62.     }  
  63. }  

 

客户端:

 

Java代码  收藏代码
  1. package me.hello.netty;  
  2.   
  3. import org.jboss.netty.bootstrap.ClientBootstrap;  
  4. import org.jboss.netty.channel.*;  
  5. import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;  
  6. import org.jboss.netty.handler.codec.string.StringDecoder;  
  7. import org.jboss.netty.handler.codec.string.StringEncoder;  
  8.   
  9. import java.io.BufferedReader;  
  10. import java.io.InputStreamReader;  
  11. import java.net.InetSocketAddress;  
  12. import java.util.concurrent.Executors;  
  13.   
  14. /** 
  15.  * God Bless You! 
  16.  * Author: Fangniude 
  17.  * Date: 2013-07-15 
  18.  */  
  19. public class NettyClient {  
  20.   
  21.     public static void main(String[] args) {  
  22.         // Configure the client.  
  23.         ClientBootstrap bootstrap = new ClientBootstrap(new NioClientSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));  
  24.   
  25.         // Set up the default event pipeline.  
  26.         bootstrap.setPipelineFactory(new ChannelPipelineFactory() {  
  27.             @Override  
  28.             public ChannelPipeline getPipeline() throws Exception {  
  29.                 return Channels.pipeline(new StringDecoder(), new StringEncoder(), new ClientHandler());  
  30.             }  
  31.         });  
  32.   
  33.         // Start the connection attempt.  
  34.         ChannelFuture future = bootstrap.connect(new InetSocketAddress("localhost", 8000));  
  35.   
  36.         // Wait until the connection is closed or the connection attempt fails.  
  37.         future.getChannel().getCloseFuture().awaitUninterruptibly();  
  38.   
  39.         // Shut down thread pools to exit.  
  40.         bootstrap.releaseExternalResources();  
  41.     }  
  42.   
  43.     private static class ClientHandler extends SimpleChannelHandler {  
  44.         private BufferedReader sin = new BufferedReader(new InputStreamReader(System.in));  
  45.   
  46.         @Override  
  47.         public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {  
  48.             if (e.getMessage() instanceof String) {  
  49.                 String message = (String) e.getMessage();  
  50.                 System.out.println(message);  
  51.   
  52.                 e.getChannel().write(sin.readLine());  
  53.   
  54.                 System.out.println("\n{待客户端输入。。?);  
  55.             }  
  56.   
  57.             super.messageReceived(ctx, e);  
  58.         }  
  59.   
  60.         @Override  
  61.         public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {  
  62.             System.out.println("已经与Server建立q接。。。?);  
  63.             System.out.println("\n误入要发送的信息Q?);  
  64.             super.channelConnected(ctx, e);  
  65.   
  66.             e.getChannel().write(sin.readLine());  
  67.         }  
  68.     }  
  69. }  

 

Netty整体架构



 

Nettylg

 

ChannelFactory

Boss

Worker

Channel

ChannelEvent

Pipeline

ChannelContext

Handler

Sink

 

Server端核心类

NioServerSocketChannelFactory

NioServerBossPool 

NioWorkerPool

NioServerBoss

NioWorker

NioServerSocketChannel

NioAcceptedSocketChannel

DefaultChannelPipeline

NioServerSocketPipelineSink

Channels

 

 

ChannelFactory

Channel工厂Q很重要的类

保存启动的相兛_?/p>

 

NioServerSocketChannelFactory

NioClientSocketChannelFactory

NioDatagramChannelFactory

 

q是Nio的,q有Oio和Local?/p>

 

 

SelectorPool

 

Selector的线E池

 

NioServerBossPool 默认U程敎ͼ1

NioClientBossPool      1

NioWorkerPool      2 * Processor

NioDatagramWorkerPool

 

 

Selector

 

选择器,很核心的lg

 

NioServerBoss

NioClientBoss

NioWorker

NioDatagramWorker

 

 

Channel

 

通道

 

NioServerSocketChannel

NioClientSocketChannel

NioAcceptedSocketChannel

NioDatagramChannel

 

Sink

负责和底层的交互

如bindQWriteQClose{?/p>

 

NioServerSocketPipelineSink

NioClientSocketPipelineSink

NioDatagramPipelineSink

 

Pipeline

负责l护所有的Handler

 

ChannelContext

一个Channel一个,是Handler和Pipeline的中间g

 

Handler

对Channel事g的处理器

 

 

ChannelPipeline

 



 

 

 

优秀的设?---事g驱动



 

 

优秀的设?---U程模型



 

注意事项

 

解码时的Position

 

Channel的关?/p>

 

更多Handler

 

 

Channel的关?/p>

 

用完的ChannelQ可以直接关闭;

1、ChannelFuture加Listener

2、writeComplete

 

一D|间没用,也可以关?/p>

TimeoutHandler



paulwong 2016-04-12 15:19 发表评论
]]>
轻量U分布式 RPC 框架http://www.aygfsteel.com/paulwong/archive/2016/04/12/430053.htmlpaulwongpaulwongTue, 12 Apr 2016 05:44:00 GMThttp://www.aygfsteel.com/paulwong/archive/2016/04/12/430053.htmlhttp://www.aygfsteel.com/paulwong/comments/430053.htmlhttp://www.aygfsteel.com/paulwong/archive/2016/04/12/430053.html#Feedback0http://www.aygfsteel.com/paulwong/comments/commentRss/430053.htmlhttp://www.aygfsteel.com/paulwong/services/trackbacks/430053.html1、每套服务需搭配一个RPCSERVER2、RPCSERVER作ؓSPRING 容器的一个BEAN3、在SPRING启动的时候,RPCSERVER会启动一个NETTY服务器端Q然后将SPRING...  阅读全文

paulwong 2016-04-12 13:44 发表评论
]]>
Reactor模式详解http://www.aygfsteel.com/paulwong/archive/2015/09/08/427190.htmlpaulwongpaulwongTue, 08 Sep 2015 04:28:00 GMThttp://www.aygfsteel.com/paulwong/archive/2015/09/08/427190.htmlhttp://www.aygfsteel.com/paulwong/comments/427190.htmlhttp://www.aygfsteel.com/paulwong/archive/2015/09/08/427190.html#Feedback0http://www.aygfsteel.com/paulwong/comments/commentRss/427190.htmlhttp://www.aygfsteel.com/paulwong/services/trackbacks/427190.html

前记

W一ơ听到Reactor模式是三q前的某个晚上,一个室友突然跑q来问我什么是Reactor模式Q我上网查了一下,很多人都是给出NIO中的 Selector的例子,而且是NIO里Selector多\复用模型Q只是给它v了一个比较fancy的名字而已Q虽然它引入了EventLoop?念,q对我来说是新的概念Q但是代码实现却是一LQ因而我q没有很在意q个模式。然而最q开始读Netty源码Q而Reactor模式是很多介lNetty的文章中被大肆宣传的模式Q因而我再次问自己,什么是Reactor模式Q本文就是对q个问题关于我的一些理解和试着来解{?br />

什么是Reactor模式

要回{这个问题,首先当然是求助Google或WikipediaQ其中Wikipedia上说Q?#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.”。从q个描述中,我们知道Reactor模式首先?strong>事g驱动的,有一个或多个q发输入源,有一个Service HandlerQ有多个Request HandlersQ这个Service Handler会同步的输入的hQEventQ多路复用的分发l相应的Request Handler。如果用图来表达Q?br />

从结构上Q这有点cM生者消费者模式,x一个或多个生者将事g攑օ一个Queue中,而一个或多个消费者主动的从这个Queue中Poll事g来处理;而Reactor模式则ƈ没有Queue来做~冲Q每当一个Event输入到Service Handler之后Q该Service Handler会主动的Ҏ不同的Eventcd其分发l对应的Request Handler来处理?br />
更学术的Q这文章(Reactor An Object Behavioral Pattern for Demultiplexing and Dispatching Handles for Synchronous EventsQ上_“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 Dispatcher, Notifier”。这D|q和Wikipedia上的描述cMQ有多个输入源,有多个不同的EventHandlerQRequestHandlerQ来处理不同的请求,Initiation Dispatcher用于理EventHanderQEventHandler首先要注册到Initiation Dispatcher中,然后Initiation DispatcherҎ输入的Event分发l注册的EventHandlerQ然而Initiation Dispatcherq不监听Event的到来,q个工作交给Synchronous Event Demultiplexer来处理?br />

Reactor模式l构

在解决了什么是Reactor模式后,我们来看看Reactor模式是由什么模块构成。图是一U比较简zŞ象的表现方式Q因而先上一张图来表辑֐个模块的名称和他们之间的关系Q?br />

HandleQ?/strong>x作系l中的句柄,是对资源在操作系l层面上的一U抽象,它可以是打开的文件、一个连?Socket)、Timer{。由于Reactor模式一般用在|络~程中,因而这里一般指Socket HandleQ即一个网l连接(ConnectionQ在Java NIO中的ChannelQ。这个Channel注册到Synchronous Event Demultiplexer中,以监听Handle中发生的事gQ对ServerSocketChannnel可以是CONNECT事gQ对SocketChannel可以是READ、WRITE、CLOSE事g{?br />Synchronous Event DemultiplexerQ?/strong>d{待一pd的Handle中的事g到来Q如果阻塞等待返回,卌C在q回的Handle中可以不d的执行返回的事gcd。这个模块一般用操作系l的select来实现。在Java NIO中用Selector来封装,当Selector.select()q回Ӟ可以调用Selector的selectedKeys()Ҏ获取Set<SelectionKey>Q一个SelectionKey表达一个有事g发生的Channel以及该Channel上的事gcd。上囄“Synchronous Event Demultiplexer ---notifies--> Handle”的流E如果是对的Q那内部实现应该是select()Ҏ在事件到来后会先讄Handle的状态,然后q回。不了解内部实现机制Q因而保留原图?br />Initiation DispatcherQ?/strong>用于理Event HandlerQ即EventHandler的容器,用以注册、移除EventHandler{;另外Q它q作为Reactor模式的入口调用Synchronous Event Demultiplexer的selectҎ以阻塞等待事件返回,当阻塞等待返回时Q根据事件发生的Handle其分发l对应的Event Handler处理Q即回调EventHandler中的handle_event()Ҏ?br />Event HandlerQ?/strong>定义事g处理ҎQhandle_event()Q以供InitiationDispatcher回调使用?br />Concrete Event HandlerQ?/strong>事gEventHandler接口Q实现特定事件处理逻辑?br />

Reactor模式模块之间的交?/h2>单描qC下Reactor各个模块之间的交互流E,先从序列囑ּ始:

1. 初始化InitiationDispatcherQƈ初始化一个Handle到EventHandler的Map?br />2. 注册EventHandler到InitiationDispatcher中,每个EventHandler包含对相应Handle的引用,从而徏立Handle到EventHandler的映(MapQ?br />3. 调用InitiationDispatcher的handle_events()Ҏ以启动Event Loop。在Event Loop中,调用select()ҎQSynchronous Event DemultiplexerQ阻塞等待Event发生?br />4. 当某个或某些Handle的Event发生后,select()Ҏq回QInitiationDispatcherҎq回的Handle扑ֈ注册的EventHandlerQƈ回调该EventHandler的handle_events()Ҏ?br />5. 在EventHandler的handle_events()Ҏ中还可以向InitiationDispatcher中注册新的EventhandlerQ比如对AcceptorEventHandler来,当有新的clientq接Ӟ它会产生新的EventHandler以处理新的连接,q注册到InitiationDispatcher中?br />

Reactor模式实现

?a 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中,一直以Logging Server来分析Reactor模式Q这个Logging Server的实现完全遵循这里对Reactor描述Q因而放在这里以做参考。Logging Server中的Reactor模式实现分两个部分:Clientq接到Logging Server和Client向Logging Server写Log。因而对它的描述分成q两个步骤?br />Clientq接到Logging Server

1. Logging Server注册LoggingAcceptor到InitiationDispatcher?br />2. Logging Server调用InitiationDispatcher的handle_events()Ҏ启动?br />3. InitiationDispatcher内部调用select()ҎQSynchronous Event DemultiplexerQ,d{待Clientq接?br />4. Clientq接到Logging Server?br />5. InitiationDisptcher中的select()Ҏq回Qƈ通知LoggingAcceptor有新的连接到来?nbsp;
6. LoggingAcceptor调用acceptҎacceptq个新连接?br />7. LoggingAcceptor创徏新的LoggingHandler?br />8. 新的LoggingHandler注册到InitiationDispatcher?同时也注册到Synchonous Event Demultiplexer?Q等待Client发v写logh?br />Client向Logging Server写Log

1. Client发送log到Logging server?br />2. InitiationDispatcher监测到相应的Handle中有事g发生Q返回阻塞等待,Ҏq回的Handle扑ֈLoggingHandlerQƈ回调LoggingHandler中的handle_event()Ҏ?br />3. LoggingHandler中的handle_event()Ҏ中读取Handle中的log信息?br />4. 接收到的log写入到日志文件、数据库{设备中?br />3.4步骤循环直到当前日志处理完成?br />5. q回到InitiationDispatcher{待下一ơ日志写h?br />
?a 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有对Reactor模式的C++的实现版本,多年不用C++Q因而略q?nbsp;

Java NIO对Reactor的实?/h2>在Java的NIO中,对Reactor模式有无~的支持Q即使用Selectorcd装了操作pȝ提供的Synchronous Event Demultiplexer功能。这个Doug Lea已经?a target="_blank" bluelink"="" tabindex="-1" style="border: 0px none; outline: none; color: #296bcc;">Scalable IO In Java中有非常深入的解释了Q因而不再赘qͼ另外q篇文章对Doug Lea?a target="_blank" bluelink"="" tabindex="-1" style="border: 0px none; outline: none; color: #296bcc;">Scalable IO In Java有一些简单解释,臛_它的代码格式比Doug Lea的PPT要整z一些?br />
需要指出的是,不同q里使用InitiationDispatcher来管理EventHandlerQ在Doug Lea的版本中使用SelectionKey中的Attachment来存储对应的EventHandlerQ因而不需要注册EventHandlerq个步骤Q或者设|Attachment是q里的注册。而且在这文章中QDoug Lea从单U程的Reactor、Acceptor、Handler实现q个模式出发Q演化ؓHandler中的处理逻辑多线E化Q实现类似Proactor模式Q此时所有的IO操作q是单线E的Q因而再演化Z个Main Reactor来处理CONNECT事g(Acceptor)Q而多个Sub Reactor来处理READ、WRITE{事?Handler)Q这些Sub Reactor可以分别再自qU程中执行,从而IO操作也多U程化。这个最后一个模型正是Netty中用的模型。ƈ且在Reactor An Object Behavioral Pattern for Demultiplexing and Dispatching Handles for Synchronous Events?.5 Determine the Number of Initiation Dispatchers in an Application中也有相应的描述?br />

EventHandler接口定义

对EventHandler的定义有两种设计思\Qsingle-method设计和multi-method设计Q?br />A single-method interfaceQ?/strong>它将Event装成一个Event ObjectQEventHandler只定义一个handle_event(Event event)Ҏ。这U设计的好处是有利于扩展Q可以后来方便的d新的EventcdQ然而在子类的实CQ需要判断不同的Eventcd而再ơ扩展成 不同的处理方法,从这个角度上来说Q它又不利于扩展。另外在Netty3的用过E中Q由于它不停的创建ChannelEventc,因而会引vGC的不E_?br />A multi-method interfaceQ?/strong>q种设计是将不同的Eventcd?EventHandler中定义相应的Ҏ。这U设计就是Netty4中用的{略Q其中一个目的是避免ChannelEvent创徏引v的GC不稳定, 另外一个好处是它可以避免在EventHandler实现时判断不同的Eventcd而有不同的实玎ͼ然而这U设计会l扩展新的Eventcd时带来非?大的ȝQ因为它需要该接口?br />
关于Netty4对Netty3的改q可以参?a target="_blank" bluelink"="" tabindex="-1" style="border: 0px none; outline: none; color: #296bcc;">q里Q?br />ChannelHandler with no event objectIn 3.x, every I/O operation created a ChannelEvent object. For each read / write, it additionally created a new ChannelBuffer. 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.

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 handleUpstream() andhandleDownstream(), but this is not the case anymore. Every event type has its own handler method now:

Z么用Reactor模式

归功与Netty和Java NIO对Reactor的宣传,本文慕名而学习的Reactor模式Q因而已l默认Reactorh非常优秀的性能Q然而慕名归慕名Q到q里Q我q是要不得不问自己Reactor模式的好处在哪里Q即Z么要使用q个Reactor模式Q在Reactor An Object Behavioral Pattern for Demultiplexing and Dispatching Handles for Synchronous Events中是q么说的Q?br />Reactor Pattern优点

Separation of concerns: 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 byEvent Handlers. In contrast, the application-specific functionality in a hook method knows how to perform a particular type of service.

Improve modularity, reusability, and configurability of event-driven applications: 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.

Improves application portability: The Initiation Dispatcher’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 calledselect and poll [1]. In the Win32 API [16], the WaitForMultipleObjects system call performs event demultiplexing.

Provides coarse-grained concurrency control: 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 Initiation Dispatcher level often eliminates the need for more complicated synchronization or locking within an application process.

q些貌似是很多模式的共性:解耦、提升复用性、模块化、可UL性、事仉动、细力度的ƈ发控制等Q因而ƈ不能很好的说明什么,特别是它鼓吹的对性能的提升,q里q没有体现出来。当然在q篇文章的开头有描述q另一U直观的实现QThread-Per-ConnectionQ即传统的实玎ͼ提到了这个传l实现的以下问题Q?br />Thread Per Connection~点

Efficiency: Threading may lead to poor performance due to context switching, synchronization, and data movement [2];

Programming simplicity: Threading may require complex concurrency control schemes;

Portability: Threading is not available on all OS platforms. 对于性能Q它其实是W一点关于Efficiency的描qͼ即线E的切换、同步、数据的Ud会引h能问题。也是说从性能的角度上Q它最大的提升是减少了性能的用,即不需要每个Client对应一个线E。我的理解,其他业务逻辑处理很多时候也会用到相同的U程QIOd操作相对CPU的操作还是要慢很多,即Reactor机制中每ơ读写已l能保证非阻塞读写,q里可以减少一些线E的使用Q但是这减少的线E用对性能有那么大的媄响吗Q答案貌似是肯定的,q篇论文(SEDA: Staged Event-Driven Architecture - An Architecture for Well-Conditioned, Scalable Internet Service)寚w着U程的增长带来性能降低做了一个统计:

在这个统计中Q每个线E从盘中读8KB数据Q每个线E读同一个文Ӟ因而数据本w是~存在操作系l内部的Q即减少IO的媄响;所有线E是事先分配的,不会有线E启动的影响Q所有Q务在试内部产生Q因而不会有|络的媄响。该l计数据q行环境QLinux 2.2.14Q?GB内存Q?-way 500MHz Pentium III。从图中可以看出Q随着U程的增长,吞吐量在U程Cؓ8个左右的时候开始线性下降,q且?4个以后而迅速下降,其相应事件也在线E达?56个后指数上升。即1+1<2Q因为线E切换、同步、数据移动会有性能损失Q线E数增加C定数量时Q这U性能影响效果会更加明显?br />
对于q点Q还可以参?a target="_blank" bluelink"="" tabindex="-1" style="border: 0px none; outline: none; color: #296bcc;">C10K ProblemQ用以描q同时有10K个Client发vq接的问题,?010q的时候已l出?0M Problem了?br />
当然也有Q?a target="_blank" bluelink"="" tabindex="-1" style="border: 0px none; outline: none; color: #296bcc;">Threads are expensive are no longer valid.在不久的来可能又会发生不同的变化,或者这个变化正在、已l发生着Q没有做q比较仔l的试Q因而不敢随便断a什么,然而本点,即ɾU程变的影响q没有以前那么大Q用Reactor模式Q甚xSEDA模式来减线E的使用Q再加上其他解耦、模块化、提升复用性等优点Q还是值得使用的?br />

Reactor模式的缺?/h2>Reactor模式的缺点貌g是显而易见的Q?br />1. 相比传统的简单模型,Reactor增加了一定的复杂性,因而有一定的门槛Qƈ且不易于调试?br />2. Reactor模式需要底层的Synchronous Event Demultiplexer支持Q比如Java中的Selector支持Q操作系l的selectpȝ调用支持Q如果要自己实现Synchronous Event Demultiplexer可能不会有那么高效?br />3. Reactor模式在IOd数据时还是在同一个线E中实现的,即使用多个Reactor机制的情况下Q那些共享一个Reactor的Channel如果出现一个长旉的数据读写,会媄响这个Reactor中其他Channel的相应时_比如在大文g传输ӞIO操作׃影响其他Client的相应时_因而对q种操作Q用传l的Thread-Per-Connection或许是一个更好的选择Q或则此时用Proactor模式?br />

参?/h2>Reactor Pattern WikiPedia
Reactor An Object Behavioral Pattern for Demultiplexing and Dispatching Handles for Synchronous Events
Scalable IO In Java
C10K Problem WikiPedia



paulwong 2015-09-08 12:28 发表评论
]]>
Netty3架构解析http://www.aygfsteel.com/paulwong/archive/2015/09/08/427186.htmlpaulwongpaulwongTue, 08 Sep 2015 03:11:00 GMThttp://www.aygfsteel.com/paulwong/archive/2015/09/08/427186.htmlhttp://www.aygfsteel.com/paulwong/comments/427186.htmlhttp://www.aygfsteel.com/paulwong/archive/2015/09/08/427186.html#Feedback0http://www.aygfsteel.com/paulwong/comments/commentRss/427186.htmlhttp://www.aygfsteel.com/paulwong/services/trackbacks/427186.html

前记

很早以前有读Netty源码的打了Q然而第一ơ尝试的时候从Netty4开始,一直抓不到核心的框架流E,后来因ؓ其他事情忙着放下了。这ơ趁着休假重新捡vq个骨_因ؓNetty3现在q在被很多项目用,因而这ơ决定先从Netty3入手Q瞬间发现Netty3的代码比Netty4中规中矩的多Q很多概念在代码本n中都有清晰的表达Q所以半天就把整个框架的骨架搞清楚了。再?/span>Netty4对Netty3的改qȝQ回去读Netty4的源码,反而觉得轻松了Q一U豁然开朗的感觉?/span>

记得d读Jetty源码的时候,因ؓ代码太庞大,q且自己的HTTP Server的了解太,因而只能自底向上的一个一个模块的叠加Q直到最后把所以的模块q接在一赯看清它的真正核心骨架。现在读源码Q开始习惯先把骨架理清,然后延C同的器官、血肉而看清整个h体?/span>

本文从Reactor模式在Netty3中的应用Q引出Netty3的整体架构以及控制流E;然而除了Reactor模式QNetty3q在ChannelPipeline中用了Intercepting Filter模式Q这个模式也在Servlet的Filter中成功用,因而本文还会从Intercepting Filter模式出发详细介绍ChannelPipeline的设计理c本文假设读者已l对Netty有一定的了解Q因而不会包含过多入门介l,以及帮Netty做宣传的文字?/span>

Netty3中的Reactor模式

Reactor模式在Netty中应用非常成功,因而它也是在Netty中受大肆宣传的模式,关于Reactor模式可以详细参考本人的另一文?/span>《Reactor模式详解?/a>Q对Reactor模式的实现是Netty3的基本骨Ӟ因而本节会详l介lReactor模式如何应用Netty3中?/span>

如果诅RReactor模式详解》,我们知道Reactor模式由Handle、Synchronous Event Demultiplexer、Initiation Dispatcher、Event Handler、Concrete Event Handler构成Q在Java的实现版本中QChannel对应HandleQSelector对应Synchronous Event DemultiplexerQƈ且Netty3q用了两层ReactorQMain Reactor用于处理Client的连接请求,Sub Reactor用于处理和Clientq接后的dhQ关于这个概念还可以参考Doug Lea的这PPTQ?/span>
Scalable IO In JavaQ。所以我们先要解决Netty3中用什么类实现所有的上述模块q把他们联系在一LQ以NIO实现方式ZQ?/span>

模式是一U抽象,但是在实CQ经怼因ؓ语言Ҏ、框架和性能需要而做一些改变,因而Netty3对Reactor模式的实现有一套自q设计Q?br />
1. ChannelEventQ?/strong>Reactor是基于事件编E的Q因而在Netty3中用ChannelEvent抽象的表达Netty3内部可以产生的各U事Ӟ所有这些事件对象在Channels帮助cM产生Qƈ且由它将事g推入到ChannelPipeline中,ChannelPipeline构徏ChannelHandler道QChannelEvent经q个道实现所有的业务逻辑处理。ChannelEvent对应的事件有QChannelStateEvent表示Channel状态的变化事gQ而如果当前Channel存在Parent ChannelQ则该事件还会传递到Parent Channel的ChannelPipeline中,如OPEN、BOUND、CONNECTED、INTEREST_OPS{,该事件可以在各种不同实现的Channel、ChannelSink中生;MessageEvent表示从Socket中读取数据完成、需要向Socket写数据或ChannelHandler对当前Message解析(如Decoder、Encoder)后触发的事gQ它由NioWorker、需要对Message做进一步处理的ChannelHandler产生QWriteCompletionEvent表示写完成而触发的事gQ它由NioWorker产生QExceptionEvent表示在处理过E中出现的ExceptionQ它可以发生在各个构件中Q如Channel、ChannelSink、NioWorker、ChannelHandler中;IdleStateEvent由IdleStateHandler触发Q这也是一个ChannelEvent可以无缝扩展的例子。注Q在Netty4后,已经没有ChannelEventc,所有不同事仉用对应方法表达,q也意味qChannelEvent不可扩展QNetty4采用在ChannelInboundHandler中加入userEventTriggered()Ҏ来实现这U扩展,具体可以参?/span>q里?br />
2. ChannelHandlerQ?/strong>在Netty3中,ChannelHandler用于表示Reactor模式中的EventHandler。ChannelHandler只是一个标记接口,它有两个子接口:ChannelDownstreamHandler和ChannelUpstreamHandlerQ其中ChannelDownstreamHandler表示从用户应用程序流向Netty3内部直到向Socket写数据的道Q在Netty4中改名ؓChannelOutboundHandlerQChannelUpstreamHandler表示数据从Socketq入Netty3内部向用户应用程序做数据处理的管道,在Netty4中改名ؓChannelInboundHandler?br />
3. ChannelPipelineQ?/strong>用于理ChannelHandler的管道,每个Channel一个ChannelPipeline实例Q可以运行过E中动态的向这个管道中d、删除ChannelHandlerQ由于实现的限制Q在最末端的ChannelHandler向后d或删除ChannelHandler不一定在当前执行程中v效,参?/span>q里Q。ChannelPipeline内部l护一个ChannelHandler的双向链表,它以Upstream(Inbound)方向为正向,Downstream(Outbound)方向为方向。ChannelPipeline采用Intercepting Filter模式实现Q具体可以参?/span>q里Q这个模式的实现在后一节中q是详细介绍?br />
4. NioSelectorQ?/strong>Netty3使用NioSelector来存放SelectorQSynchronous Event DemultiplexerQ,每个C生的NIO Channel都向q个Selector注册自己以让q个Selector监听q个NIO Channel中发生的事gQ当事g发生Ӟ调用帮助cChannels中的Ҏ生成ChannelEvent实例Q将该事件发送到q个Netty Channel对应的ChannelPipeline中,而交l各UChannelHandler处理。其中在向Selector注册NIO ChannelӞNetty Channel实例以Attachment的Ş式传入,该Netty Channel在其内部的NIO Channel事g发生Ӟ会以Attachment的Ş式存在于SelectionKey中,因而每个事件可以直接从q个Attachment中获取相关链的Netty ChannelQƈ从Netty Channel中获取与之相兌的ChannelPipelineQ这个实现和Doug Lea?/span>Scalable IO In Java一模一栗另外Netty3q采用了Scalable IO In Java中相同的Main Reactor和Sub Reactor设计Q其中NioSelector的两个实玎ͼBoss即ؓMain ReactorQNioWorker为Sub Reactor。Boss用来处理新连接加入的事gQNioWorker用来处理各个q接对Socket的读写事Ӟ其中Boss通过NioWorkerPool获取NioWorker实例QNetty3模式使用RoundRobin方式攑֛NioWorker实例。更形象一点的Q可以通过Scalable IO In Java的这张图表达Q?br />

若与Ractor模式对应QNioSelector中包含了Synchronous Event DemultiplexerQ而ChannelPipeline中管理着所有EventHandlerQ因而NioSelector和ChannelPipeline共同构成了Initiation Dispatcher?br />
5. ChannelSinkQ?/strong>在ChannelHandler处理完成所有逻辑需要向客户端写响应数据Ӟ一般会调用Netty Channel中的writeҎQ然而在q个writeҎ实现中,它不是直接向其内部的Socket写数据,而是交给Channels帮助c,内部创徏DownstreamMessageEventQ反向从ChannelPipeline的管道中过去,直到W一个ChannelHandler处理完毕Q最后交lChannelSink处理Q以避免d写而媄响程序的吞吐量。ChannelSink这个MessageEvent提交lNetty Channel中的writeBufferQueueQ最后NioWorker会等到这个NIO Channel已经可以处理写事件时无阻塞的向这个NIO Channel写数据。这是上图的send是从SubReactor直接出发的原因?br />
6. ChannelQ?/strong>Netty有自qChannel抽象Q它是一个资源的容器Q包含了所有一个连接涉及到的所有资源的饮用Q如装NIO Channel、ChannelPipeline、Boss、NioWorkerPool{。另外它q提供了向内部NIO Channel写响应数据的接口write、连?l定到某个地址的connect/bind接口{,个h感觉虽然对Channel本n来说Q因为它装了NIO ChannelQ因而这些接口定义在q里是合理的Q但是如果考虑到Netty的架构,它的Channel只是一个资源容器,有这个Channel实例可以得到和它相关的基本所有资源,因而这Uwrite、connect、bind动作不应该再由它负责Q而是应该由其他类来负责,比如在Netty4中就在ChannelHandlerContextd了writeҎQ虽然netty4q没有删除Channel中的write接口?/span>

Netty3中的Intercepting Filter模式

如果说Reactor模式是Netty3的骨Ӟ那么Intercepting Filter模式则是Netty的中枢。Reactor模式主要应用在Netty3的内部实玎ͼ它是Netty3h良好性能的基Q而Intercepting Filter模式则是ChannelHandlerl合实现一个应用程序逻辑的基Q只有很好的理解了这个模式才能用好NettyQ甚臌得心应手?/span>

关于Intercepting Filter模式的详l介l可以参?/span>q里Q本节主要介lNetty3中对Intercepting Filter模式的实玎ͼ其实是DefaultChannelPipeline对Intercepting Filter模式的实现。在上文有提到Netty3的ChannelPipeline是ChannelHandler的容器,用于存储与管理ChannelHandlerQ同时它在Netty3中也起到桥梁的作用,卛_是连接Netty3内部到所有ChannelHandler的桥梁。作为ChannelPipeline的实现者DefaultChannelPipelineQ它使用一个ChannelHandler的双向链表来存储Q以DefaultChannelPipelineContext作ؓ节点Q?br />
public interface ChannelHandlerContext {
    Channel getChannel();
    ChannelPipeline getPipeline();
    String getName();
    ChannelHandler getHandler();
    boolean canHandleUpstream();
    boolean canHandleDownstream();
    void sendUpstream(ChannelEvent e);
    void sendDownstream(ChannelEvent e);
    Object getAttachment();
    void setAttachment(Object attachment);
}

private final class DefaultChannelHandlerContext implements ChannelHandlerContext {
    volatile DefaultChannelHandlerContext next;
    volatile DefaultChannelHandlerContext prev;
    private final String name;
    private final ChannelHandler handler;
    private final boolean canHandleUpstream;
    private final boolean canHandleDownstream;
    private volatile Object attachment;
..
}

在DefaultChannelPipeline中,它存储了和当前ChannelPipeline相关联的Channel、ChannelSink以及ChannelHandler链表的head、tailQ所有ChannelEvent通过sendUpstream、sendDownstream为入口流l整个链表:

public class DefaultChannelPipeline implements ChannelPipeline {
    private volatile Channel channel;
    private volatile ChannelSink sink;
    private volatile DefaultChannelHandlerContext head;
    private volatile DefaultChannelHandlerContext tail;

    public void sendUpstream(ChannelEvent e) {
        DefaultChannelHandlerContext head = getActualUpstreamContext(this.head);
        if (head == null) {
            return;
        }
        sendUpstream(head, e);
    }

    void sendUpstream(DefaultChannelHandlerContext ctx, ChannelEvent e) {
        try {
            ((ChannelUpstreamHandler) ctx.getHandler()).handleUpstream(ctx, e);
        } catch (Throwable t) {
            notifyHandlerException(e, t);
        }
    }

    public void sendDownstream(ChannelEvent e) {
        DefaultChannelHandlerContext tail = getActualDownstreamContext(this.tail);
        if (tail == null) {
            try {
                getSink().eventSunk(this, e);
                return;
            } catch (Throwable t) {
                notifyHandlerException(e, t);
                return;
            }
        }
        sendDownstream(tail, e);
    }

    void sendDownstream(DefaultChannelHandlerContext ctx, ChannelEvent e) {
        if (e instanceof UpstreamMessageEvent) {
            throw new IllegalArgumentException("cannot send an upstream event to downstream");
        }
        try {
            ((ChannelDownstreamHandler) ctx.getHandler()).handleDownstream(ctx, e);
        } catch (Throwable t) {
            e.getFuture().setFailure(t);
            notifyHandlerException(e, t);
        }
    }

对Upstream事gQ向后找到所有实CChannelUpstreamHandler接口的ChannelHandlerl成链(
getActualUpstreamContext()Q?/span>Q而对Downstream事gQ向前找到所有实CChannelDownstreamHandler接口的ChannelHandlerl成链(getActualDownstreamContext()Q:

    private DefaultChannelHandlerContext getActualUpstreamContext(DefaultChannelHandlerContext ctx) {
        if (ctx == null) {
            return null;
        }
        DefaultChannelHandlerContext realCtx = ctx;
        while (!realCtx.canHandleUpstream()) {
            realCtx = realCtx.next;
            if (realCtx == null) {
                return null;
            }
        }
        return realCtx;
    }
    private DefaultChannelHandlerContext getActualDownstreamContext(DefaultChannelHandlerContext ctx) {
        if (ctx == null) {
            return null;
        }
        DefaultChannelHandlerContext realCtx = ctx;
        while (!realCtx.canHandleDownstream()) {
            realCtx = realCtx.prev;
            if (realCtx == null) {
                return null;
            }
        }
        return realCtx;
    }

在实际实现ChannelUpstreamHandler或ChannelDownstreamHandlerӞ调用 ChannelHandlerContext中的sendUpstream或sendDownstreamҎ控制流E交l下一?ChannelUpstreamHandler或下一个ChannelDownstreamHandlerQ或调用Channel中的writeҎ发?响应消息?br />
public class MyChannelUpstreamHandler implements ChannelUpstreamHandler {
    public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
        // handle current logic, use Channel to write response if needed.
        
// ctx.getChannel().write(message);
        ctx.sendUpstream(e);
    }
}

public class MyChannelDownstreamHandler implements ChannelDownstreamHandler {
    public void handleDownstream(
            ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
        // handle current logic
        ctx.sendDownstream(e);
    }
}

当ChannelHandler向ChannelPipelineContext发送事件时Q其内部从当前ChannelPipelineContext节点出发扑ֈ下一个ChannelUpstreamHandler或ChannelDownstreamHandler实例Qƈ向其发送ChannelEventQ对于Downstream链,如果到达铑ְQ则ChannelEvent发送给ChannelSinkQ?br />
public void sendDownstream(ChannelEvent e) {
    DefaultChannelHandlerContext prev = getActualDownstreamContext(this.prev);
    if (prev == null) {
        try {
            getSink().eventSunk(DefaultChannelPipeline.this, e);
        } catch (Throwable t) {
            notifyHandlerException(e, t);
        }
    } else {
        DefaultChannelPipeline.this.sendDownstream(prev, e);
    }
}

public void sendUpstream(ChannelEvent e) {
    DefaultChannelHandlerContext next = getActualUpstreamContext(this.next);
    if (next != null) {
        DefaultChannelPipeline.this.sendUpstream(next, e);
    }
}

正是因ؓq个实现Q如果在一个末ChannelUpstreamHandler中先U除自己Q在向末添加一个新的ChannelUpstreamHandlerQ它是无效的Q因为它的next已经在调用前固定设|ؓnull了?/span>

ChannelPipeline作ؓChannelHandler的容器,它还提供了各U增、删、改ChannelHandler链表中的ҎQ而且如果某个ChannelHandlerq实CLifeCycleAwareChannelHandlerQ则该ChannelHandler在被dqChannelPipeline或从中删除时都会得到同志Q?br />
public interface LifeCycleAwareChannelHandler extends ChannelHandler {
    void beforeAdd(ChannelHandlerContext ctx) throws Exception;
    void afterAdd(ChannelHandlerContext ctx) throws Exception;
    void beforeRemove(ChannelHandlerContext ctx) throws Exception;
    void afterRemove(ChannelHandlerContext ctx) throws Exception;
}

public interface ChannelPipeline {
    void addFirst(String name, ChannelHandler handler);
    void addLast(String name, ChannelHandler handler);
    void addBefore(String baseName, String name, ChannelHandler handler);
    void addAfter(String baseName, String name, ChannelHandler handler);
    void remove(ChannelHandler handler);
    ChannelHandler remove(String name);
    <T extends ChannelHandler> T remove(Class<T> handlerType);
    ChannelHandler removeFirst();
    ChannelHandler removeLast();
    void replace(ChannelHandler oldHandler, String newName, ChannelHandler newHandler);
    ChannelHandler replace(String oldName, String newName, ChannelHandler newHandler);
    <T extends ChannelHandler> T replace(Class<T> oldHandlerType, String newName, ChannelHandler newHandler);
    ChannelHandler getFirst();
    ChannelHandler getLast();
    ChannelHandler get(String name);
    <T extends ChannelHandler> T get(Class<T> handlerType);
    ChannelHandlerContext getContext(ChannelHandler handler);
    ChannelHandlerContext getContext(String name);
    ChannelHandlerContext getContext(Class<? extends ChannelHandler> handlerType);
    void sendUpstream(ChannelEvent e);
    void sendDownstream(ChannelEvent e);
    ChannelFuture execute(Runnable task);
    Channel getChannel();
    ChannelSink getSink();
    void attach(Channel channel, ChannelSink sink);
    boolean isAttached();
    List<String> getNames();
    Map<String, ChannelHandler> toMap();
}

在DefaultChannelPipeline的ChannelHandler链条的处理流EؓQ?/span>


http://www.aygfsteel.com/DLevin/archive/2015/09/04/427031.html


参考:

《Netty主页?/a>
《Netty源码解读Q四QNetty与Reactor模式?/a>
《Netty代码分析?/a>
Scalable IO In Java
Intercepting Filter Pattern

paulwong 2015-09-08 11:11 发表评论
]]>
100万ƈ发连接服务器W记之Java Netty处理1Mq接会怎么?/title><link>http://www.aygfsteel.com/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.aygfsteel.com/paulwong/archive/2015/07/13/426202.html</guid><wfw:comment>http://www.aygfsteel.com/paulwong/comments/426202.html</wfw:comment><comments>http://www.aygfsteel.com/paulwong/archive/2015/07/13/426202.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/paulwong/comments/commentRss/426202.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/paulwong/services/trackbacks/426202.html</trackback:ping><description><![CDATA[     摘要: 前言每一U该语言在某些极限情况下的表C般都不太一P那么我常用的Java语言Q在辑ֈ100万个q发q接情况下,会怎么样呢Q有些好奇,更有些期盹{这ơ用经怋用的手的netty NIO框架Qnetty-3.6.5.FinalQ,装的很好,接口很全面,像它现在的域名 netty.ioQ专注于|络IO。整个过E没有什么技术含量,显分析q就更显得有些枯燥无聊,准备好,着?..  <a href='http://www.aygfsteel.com/paulwong/archive/2015/07/13/426202.html'>阅读全文</a><img src ="http://www.aygfsteel.com/paulwong/aggbug/426202.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/paulwong/" target="_blank">paulwong</a> 2015-07-13 18:26 <a href="http://www.aygfsteel.com/paulwong/archive/2015/07/13/426202.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>轻量U、高性能NIO|络通讯框架Qaround 60KQ?zbushttp://www.aygfsteel.com/paulwong/archive/2015/04/22/424600.htmlpaulwongpaulwongWed, 22 Apr 2015 07:53:00 GMThttp://www.aygfsteel.com/paulwong/archive/2015/04/22/424600.htmlhttp://www.aygfsteel.com/paulwong/comments/424600.htmlhttp://www.aygfsteel.com/paulwong/archive/2015/04/22/424600.html#Feedback0http://www.aygfsteel.com/paulwong/comments/commentRss/424600.htmlhttp://www.aygfsteel.com/paulwong/services/trackbacks/424600.htmlhttp://git.oschina.net/rushmore/zbus

Z么没有选择netty或者minaQ?br />个h观点Qnetty与minaq于庞大Q需要学习的成本比较高,debug中的chainq长Q自׃方便改写

paulwong 2015-04-22 15:53 发表评论
]]>
commonrpc 0.1 发布Q高性能分布?RPC 框架http://www.aygfsteel.com/paulwong/archive/2015/03/12/423414.htmlpaulwongpaulwongThu, 12 Mar 2015 11:02:00 GMThttp://www.aygfsteel.com/paulwong/archive/2015/03/12/423414.htmlhttp://www.aygfsteel.com/paulwong/comments/423414.htmlhttp://www.aygfsteel.com/paulwong/archive/2015/03/12/423414.html#Feedback0http://www.aygfsteel.com/paulwong/comments/commentRss/423414.htmlhttp://www.aygfsteel.com/paulwong/services/trackbacks/423414.htmlq在慕BATQ京东等公司的大量的架构吗Q让你的javapȝ引用解耦,互相独立,commonrpc 可以办到。commonrpc 是一个以netty为基Qspring 自定义shcema为基标签的rpc框架,不R入Q何业务代码,一个高性能分布式rpc框架Q支持tcp协议,http协议,同时HTTP协议支持restful 方式讉K.

paulwong 2015-03-12 19:02 发表评论
]]>
NETTY资源http://www.aygfsteel.com/paulwong/archive/2015/02/26/423039.htmlpaulwongpaulwongThu, 26 Feb 2015 01:49:00 GMThttp://www.aygfsteel.com/paulwong/archive/2015/02/26/423039.htmlhttp://www.aygfsteel.com/paulwong/comments/423039.htmlhttp://www.aygfsteel.com/paulwong/archive/2015/02/26/423039.html#Feedback0http://www.aygfsteel.com/paulwong/comments/commentRss/423039.htmlhttp://www.aygfsteel.com/paulwong/services/trackbacks/423039.htmlNetty4.0学习W记pd之一QServer与Client的通讯

Netty4.0学习W记pd之二QHandler的执行顺?/a>


Netty4.0学习W记pd之三Q构建简单的http服务


Netty4.0学习W记pd之四Q؜合用coder和handler


Netty4.0学习W记pd之五Q自定义通讯协议

Netty4.0学习W记pd之六Q多U通讯协议支持


NETTY HTTP JAX-RS服务?/span>
https://github.com/continuuity/netty-http

netty和tomcat的hello world性能比较
http://my.oschina.net/u/2302546/blog/368685

nginx+tomcat与netty优缺?/a>


NETTY官方EXAMPLE
https://github.com/netty/netty/tree/4.0/example/src/main/java/io/netty/example




paulwong 2015-02-26 09:49 发表评论
]]>
վ֩ģ壺 | | ̶| ¤| | ɽ| Ǭ| | ǧ| ɽ| | | | | | | | ˴| н| Ȫ| | ̨ɽ| | IJ| | ͼ| | ຣʡ| ̨| | ʮ| ɽ| ̨| ʡ| ͨ| ˷| | ػ| | | |