分享

Jboss Netty源码分析一

 蓝雨樱苑 2012-06-03

         本文采用版本为Jboss Netty-3.2.4.Final,Jboss Netty示例example、几十页的user guide是快速学习的入门捷径,学习Netty的过程中个人觉其思路比Apache Mina清晰且简洁,API提供了UML类图,对于相互之间的关系容易了解。

 

        言归正传,以示例EchoServer为切入点,eclipse下一步一步debug、阅读其源码并分析下Netty的执行过程,总结下运行机制。

 

Java代码  收藏代码
  1. /**Netty example*/  
  2. public class EchoServer {  
  3.   
  4.     public static void main(String[] args) throws Exception {  
  5.         // 配置Server  
  6.         ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(  
  7.                 Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));  
  8.   
  9.         // 设置pipeline factory.  
  10.         bootstrap.setPipelineFactory(new ChannelPipelineFactory() {  
  11.             public ChannelPipeline getPipeline() throws Exception {  
  12.                 return Channels.pipeline(new EchoServerHandler());  
  13.             }  
  14.         });  
  15.   
  16.         // 绑定,开始接受client连接  
  17.         bootstrap.bind(new InetSocketAddress(8080));  
  18.     }  
  19. }  
 

 

一、配置Server

 

      Bootstrap是初始化Channel的辅助类,为子类提供了通用的数据结构,ServerBootstrap 继承自Bootstrap,辅助

Server端创建Channel,接受客户端的连接(connection)ServerBootstrap 只能用作有链接的transports ,如:TCP IP,绝不能用于UDP。

 

 

Java代码  收藏代码
  1. /*对于示例可以分开写成如下形式*/  
  2. ChannelFactory channelFactory = new NioServerSocketChannelFactory(  
  3.                 Executors.newCachedThreadPool(), Executors.newCachedThreadPool());  
  4.           
  5. bootstrap = new ServerBootstrap(channelFactory);  

 


ServerBootstrap构造函数

 

Constructor Summary
ServerBootstrap() 
          Creates a new instance with no ChannelFactory set. 无参构造函数创建实例
ServerBootstrap(ChannelFactory channelFactory) 
          Creates a new instance with the specified initial ChannelFactory.使用指定的ChannelFactory创建

 

    ServerBootstrap(channelFactory)做如下工作:

 

Java代码  收藏代码
  1. public ServerBootstrap(ChannelFactory channelFactory) {  
  2.      /*调用父类构造函数*/  
  3.     super(channelFactory);  
  4. }  
 

    父类Bootstrap构造函数:

 

Java代码  收藏代码
  1. protected Bootstrap(ChannelFactory channelFactory) {  
  2. /*父类构造函数调用set属性方法*/  
  3.         setFactory(channelFactory);  
  4. }  
  5.   
  6.   
  7. public void setFactory(ChannelFactory factory) {  
  8. /*判断null*/  
  9.         if (factory == null) {  
  10.             throw new NullPointerException("factory");  
  11.         }  
  12. /*是否已经设置channelFactory*/  
  13.         if (this.factory != null) {  
  14.             throw new IllegalStateException(  
  15.                     "factory can't change once set.");  
  16.         }  
  17. /*属性赋值*/  
  18.         this.factory = factory;  
  19.     }  
 

 

创建一个ServerBootstrap,仅做了将channelFactory赋值给父类factory属性的动作。Netty是如何构造ChannelFactory,NioServerSocketChannelFactory的源码我们分析下。

同样我们先看下其API的构造函数。

 

            NioServerSocketChannelFactory创建服务端的ServerSocketChannel,采用多线程执行非阻塞IO,和Mina的设计

模式一样,都采用了Reactor模式。其中bossExecutor、workerExecutor是两个线程池,bossExecutor用来接收客户端连接,workerExecutor用来执行非阻塞的IO操作,主要是read,write。

 

Reactor模式:


图表2:反应器模式

 

NioServerSocketChannelFactory构造函数:

Constructor Summary
NioServerSocketChannelFactory(Executor bossExecutor, Executor workerExecutor) 
          Creates a new instance. 默认采用创建CPU*2个工作者线程数
NioServerSocketChannelFactory(Executor bossExecutor, Executor workerExecutor, int workerCount) 
          Creates a new instance. 通过workerCount指定工作者线程数
 

  NioServerSocketChannelFactory源码如下:

 

Java代码  收藏代码
  1. public NioServerSocketChannelFactory(  
  2.          Executor bossExecutor, Executor workerExecutor,  
  3.          int workerCount) {  
  4.      this.bossExecutor = bossExecutor;  
  5.      this.workerExecutor = workerExecutor;  
  6.      /*创建指定数量的工作者线程*/  
  7.      sink = new NioServerSocketPipelineSink(workerExecutor, workerCount);  
  8.  }  
 

  未指定工作者线程数量的构造函数采用了默认值SelectorUtil.DEFAULT_IO_THREADS,CPU数量的2倍,Runtime.getRuntime().availableProcessors() * 2。下面是在NioServerSocketPipelineSink的构造上函数中创建工作者线程。

 

   NioServerSocketPipelineSink构造函数:

 

Java代码  收藏代码
  1. NioServerSocketPipelineSink(Executor workerExecutor, int workerCount) {  
  2.     /*  
  3.      *类定义了一个工作者数组,NioWorker[] workers。 
  4.     */  
  5.     workers = new NioWorker[workerCount];  
  6.     for (int i = 0; i < workers.length; i ++) {  
  7.         workers[i] = new NioWorker(id, i + 1, workerExecutor);  
  8.     }  
  9. }  
 

 

 

至此,通过一个NioServerSocketChannelFactory创建ServerBootstrap实例做了以上工作,下面我们用一个时序图展示下步骤。

 



 图表3:时序图

描述:

1,EchoServer的Main构造一个NioServerSocketChannelFactory实例。

2,无参构造函数实例化一个NioServerSocketChannelFactory。

3,实例化一个NioServerSocketPipelineSink。

4,创建工作者线程,默认CPU2倍。

5,构造工作者线程。

6,初始化工作者线程属性等。

7,返回创建好的ChannelFactory。

8,根据ChannelFactory实例化ServerBootstrap。

9,设置父类的factory属性

10,创建完毕,返回该实例。

 

 

 

 


图标4:类的大致关系

 

 

2、设置pipeline factory

        待续

 

 

Reactor参考:

http://www.cs./~spl051/Personal_material/Practical_sessions/Ps_12/ps12.html

Scalable IO in Java

 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多