`
longxiaoyan
  • 浏览: 75907 次
  • 性别: Icon_minigender_1
  • 来自: 桂-京
社区版块
存档分类
最新评论

MINA源代码分析之启动与绑定(转)

    博客分类:
  • Mina
 
阅读更多
最近认真看了看MINA的源代码,阅读代码过程中学到了不少新东西,对于多线程和NIO有了更深的了解。鉴于在网上无法找到相关的源代码分析,
让我在刚开始看时走了不少弯路,因此在看代码时特意做笔记。
以下便是我的笔记,主要讲述了MINA的启动与绑定SocketAddress时其内部实际做的工作。
对于其中一些并不重要的部分在这边略去了,对于消息到达后最终如何流转到IoHandler部分在这次里面并没有涉及,这部分下次再谈。
在看源代码的过程中,有一个小小的心得,采用Debug的方式来看处理流程比直接看代码要有效的多!
当然Debug时,也得记下执行的路径。在Debug过程中,顺便复习了一下类的装载和初始化过程。
下面是笔记的具体内部:
MINA初始化调用过程  -- 对应于NioAcceptor acceptor = new NioAcceptor(); 语句。
1.AbstractIoService的<clinit>方法, (最先初始化继承树中最顶层super class,先调用<clinit>方法)
2.初始化DefaultSocketSessionConfig对象,先调<clinit>初始化所有类变量,再调用构造方法
3.执行AbstractPollingIoAcceptor初始化
    3.1初始化SimpleProcessorPool,生成一个若干的IoProcessor对象
        3.1.1 初始化SimpleProcessorPool中的实例变量,执行初始化方法<init>,生成Executor对象
        3.1.2 通过reflection 调用 newInstance方法初始化IoProcessor,具体过程如下:
            3.1.2.1 执行AbstractPollingIoProcessor的<clinit>方法初始化类变量
            3.1.2.2 执行<init>方法,初始化各实例变量,包括如下Queue:          
newSessions,removingSessions,flushingSessions,trafficControllingSessions,disposalFuture。
            3.1.2.3 执行构造方法AbstractPollingIoProcessor(Executor executor),初始化threadName,设置executor对象。
            3.1.2.4 执行NioProcessor构造方法  Selector.open();
    3.2 调用AbstractIoService的初始化方法,先初始化各实例对象,包括IoServiceListener(用于监听
future),IoFilterChainBuilder,IoSessionDataStructureFactory,IoServiceStatistics,IoServiceListenerSupport,
创建Executor对象。
    3.3 调用AbstractIoAcceptor的初始化方法<init>
        3.3.1 初始化LocalAddresses队列,boundAddresses Set(管理请求绑定的SocketAddress的容器),以及绑定的对象锁
    3.4 调用AbstractPollingIoAcceptor的<init>方法,执行初始化
        3.4.1 初始化registerQueue(注册请求队列),cancelQueue(取消请求队列),boundHandles(socketAddress,ServerSocketChannel的Map)。
        3.4.2 关联IoProcessor对象
        3.4.3 初始化Selector  Selector.open(),并将selectable设置为true
3.5 执行NioSocketAcceptor的构造方法中其它的操作,调用DefaultSocketSessionConfig的init方法。
绑定SocketAddress过程  -- 对应于代码中的  acceptor.bind(new SocketAddress(null,80));
1 调用AbstractIoAcceptor类中的bind方法,
    调用AbstractPollingIoAcceptor中的bind0方法,bind0过程如下:
    a.创建新的AcceptorOperationFuture对象的实例
    b.将这个实例放到registerQueue中,供后面的方法处理
    c.startupAcceptor 创建一个新的线程,具体的工作为inner class Acceptor, Acceptor处理过程下面讲述。
    d.selector.wakeup 继续select操作
    e.返回已经绑定的Set<SocketAddress>
2.绑定成功后触发fireServiceActivated事件。
AbstractPollingIoAcceptor.Acceptor类处理流程
    1 先select
    2 处理注册绑定请求 registerHandles(),该方法在AbstractPollingIoAcceptor中。
        a.从registerQueue中取出future
        b.通过Future中的取出的SocketAddress创建ServerSocketChannel,并绑定。
        c.以SocketAddress为key将绑定后的ServerSocketChannel放到Map中,供后面处理。
        d.该Future设置为done,并将Selector wakeup.
    3 判断是否有SelectionKey需要处理,如果需要,则进行处理,processHandles() 方法:
        a.通过NioSocketAcceptor.accept得到一个SocketChannel,生成一个NioSocketSession对象。
        b.finishSessionInitialization,设置该NioSocketSession的属性,
        c.包括AbstractIoSession中的WriteRequestQueue,
        d.调用AbstractPollingIoProcessor.add()方法,将该Session添加到newSessions容器中, 通过Executor对象创建一个新的线程处理,具体处理类
AbstractPollingIoProcessor.Process类。Process线程处理流程下面详细描述。
    4 处理取消请求,unregisterHandles()方法,从cancelQueue中取数据进行处理,关闭ServerSocketChannel,SelectionKey.cancel()。
    5 判断是否仍有在监听的请求,如是没有,释放相关资源,并退出。
AbstractPollingIoProcessor.Processor处理流程
    1、调用NioProcess中的selector进行select操作,
    2、处理newSessions中的IoSession对象 (AbstractPollingIoProcessor.add())
        a.从newSessions中得到session,为这些session注册READ事件
        b.为每个个session创建filter chain
        c.触发IoServiceListenerSupport的sessionCreate事件。
    3、为SocketChannel注册合适的事件  updateTrafficMask()方法
        a.根据SelectionKey的状态注册该Session感兴趣的事件
        b.read事件注册时,判断是否已经注册过,如果没有,则注册。
        c.调用setInterestedInWrite方法通过该session的writeQueue中的请求,注册WRITE事件。
    4、如果之前select有数据,则处理session,process()方法,具体处理如下:
        如果是读,用read()方法处理
            a.读取数据,并触发filterChain的messageReceived方法,将数据通过filterChain流转到最后的Handler去处理。
            b.如果没有可读数据,将session对象放入removeSessiong队列。
        如果是写出,用write()方法处理,直接放入flushingSessions队列,由后面步骤进行处理。
    5、处理flushingSessions队列中的请求,将数据写到SocketChannel中,并触发FilterChain中的fireMessageSent事件。
    6、处理removeSessiong队列中的请求,将不需要的session Close掉,如果session在还有数据,则触发FilterChain的fireMessageSent方法。
关闭SocketChannel连接,distory掉IoSession,并触发fireSessionDestroyed事件。
    7、notifyIdleSessions方法,最终调用filterChain的fireSessionIdle方法。
    8、判断是否仍然存在打开的session,如果没有则做退出操作。
通过MINA的启动和流程可以看到,在多线程环境中应用了大量的Queue,Set,Map的对象来存储需要接下来进行的操作,这样做的原因应
该是出于性能考虑。也有利于子线程与父线程之间的通信,有利于减少代码之间的依赖。其中还存在大量的子线程回调父线程的方法来完成一些操作,和平时用到的
直接生成一个新的工作线程去处理,之后便不管有非常大的区别。这种模式下,死锁的问题的判断就显得很重要。
由于代码量比较大,超过了我的理解范围,在很多时候仍然没有把这个框架完全吃透。
分享到:
评论

相关推荐

    JAVA上百实例源码以及开源项目源代码

    Tcp服务端与客户端的JAVA实例源代码 2个目标文件 摘要:Java源码,文件操作,TCP,服务器 Tcp服务端与客户端的JAVA实例源代码,一个简单的Java TCP服务器端程序,别外还有一个客户端的程序,两者互相配合可以开发出超多...

    JAVA上百实例源码以及开源项目

     Java二进制IO类与文件复制操作实例,好像是一本书的例子,源代码有的是独立运行的,与同目录下的其它代码文件互不联系,这些代码面向初级、中级Java程序员。 Java访问权限控制源代码 1个目标文件 摘要:Java源码,...

    java开源包8

    JOpenID是一个轻量级的OpenID 2.0 Java客户端,仅50KB+(含源代码),允许任何Web网站通过OpenID支持用户直接登录而无需注册,例如Google Account或Yahoo Account。 JActor的文件持久化组件 JFile JFile 是 JActor ...

    java开源包10

    JOpenID是一个轻量级的OpenID 2.0 Java客户端,仅50KB+(含源代码),允许任何Web网站通过OpenID支持用户直接登录而无需注册,例如Google Account或Yahoo Account。 JActor的文件持久化组件 JFile JFile 是 JActor ...

    java开源包1

    JOpenID是一个轻量级的OpenID 2.0 Java客户端,仅50KB+(含源代码),允许任何Web网站通过OpenID支持用户直接登录而无需注册,例如Google Account或Yahoo Account。 JActor的文件持久化组件 JFile JFile 是 JActor ...

    java开源包11

    JOpenID是一个轻量级的OpenID 2.0 Java客户端,仅50KB+(含源代码),允许任何Web网站通过OpenID支持用户直接登录而无需注册,例如Google Account或Yahoo Account。 JActor的文件持久化组件 JFile JFile 是 JActor ...

    java开源包2

    JOpenID是一个轻量级的OpenID 2.0 Java客户端,仅50KB+(含源代码),允许任何Web网站通过OpenID支持用户直接登录而无需注册,例如Google Account或Yahoo Account。 JActor的文件持久化组件 JFile JFile 是 JActor ...

    java开源包3

    JOpenID是一个轻量级的OpenID 2.0 Java客户端,仅50KB+(含源代码),允许任何Web网站通过OpenID支持用户直接登录而无需注册,例如Google Account或Yahoo Account。 JActor的文件持久化组件 JFile JFile 是 JActor ...

    java开源包6

    JOpenID是一个轻量级的OpenID 2.0 Java客户端,仅50KB+(含源代码),允许任何Web网站通过OpenID支持用户直接登录而无需注册,例如Google Account或Yahoo Account。 JActor的文件持久化组件 JFile JFile 是 JActor ...

    java开源包5

    JOpenID是一个轻量级的OpenID 2.0 Java客户端,仅50KB+(含源代码),允许任何Web网站通过OpenID支持用户直接登录而无需注册,例如Google Account或Yahoo Account。 JActor的文件持久化组件 JFile JFile 是 JActor ...

    java开源包4

    JOpenID是一个轻量级的OpenID 2.0 Java客户端,仅50KB+(含源代码),允许任何Web网站通过OpenID支持用户直接登录而无需注册,例如Google Account或Yahoo Account。 JActor的文件持久化组件 JFile JFile 是 JActor ...

    java开源包7

    JOpenID是一个轻量级的OpenID 2.0 Java客户端,仅50KB+(含源代码),允许任何Web网站通过OpenID支持用户直接登录而无需注册,例如Google Account或Yahoo Account。 JActor的文件持久化组件 JFile JFile 是 JActor ...

    java开源包9

    JOpenID是一个轻量级的OpenID 2.0 Java客户端,仅50KB+(含源代码),允许任何Web网站通过OpenID支持用户直接登录而无需注册,例如Google Account或Yahoo Account。 JActor的文件持久化组件 JFile JFile 是 JActor ...

    java开源包101

    JOpenID是一个轻量级的OpenID 2.0 Java客户端,仅50KB+(含源代码),允许任何Web网站通过OpenID支持用户直接登录而无需注册,例如Google Account或Yahoo Account。 JActor的文件持久化组件 JFile JFile 是 JActor ...

    Java资源包01

    JOpenID是一个轻量级的OpenID 2.0 Java客户端,仅50KB+(含源代码),允许任何Web网站通过OpenID支持用户直接登录而无需注册,例如Google Account或Yahoo Account。 JActor的文件持久化组件 JFile JFile 是 JActor ...

Global site tag (gtag.js) - Google Analytics