Mina 源码阅读:Server端基于NIO的处理流程

  源码面前,了无秘密。继之前阅读了Prototype、Spring、Tomcat、以及JDK的部分、Digester等等源码之后,学习一门技术,了解源码成了必备流程。也深深的感受到了源码面前,了无秘密的含义,同时也体会到它给我带来的好处。同时,也希望所有开发者,不论前端后端,如果有时间的话,都尽量看看源码吧。

接下来进入正题,这里要对Mina流程做一个分析。因为是指对NIO流程做了分析,所以这里说的也是NIO的执行流程。

先看一下Mina中主要类的大致结构:

接下来看看Mina的整个生命周期:

1、NioSocketAdaptor初始化分析

初始化时,设置相关依赖,例如:listeners, sessionconfig,handler, executor等,这个过程没什么可说的。

2、启动并接收请求

启动的入口是bind(SocketAddress),先来看看这部分的序列图:

这一阶段,

2.1 将ServerSocketChannel交由Selector来管理。对应序列图中的regiesterHandlers()操作。

2.2 接收SocketChanel

1)使用ServerSocketChannel接收SocketChannel。

2)将接收到的SocketChannel封装成IoSession,

3)添加到newSessions队列中。

此外,IoSession会以attachment的方式捆绑到与SocketChannel关联的SelectionKey中。这样做的目的是在进行Selector.select()之后,可以根据key直接拿到IoSession。

对应于序列图中的processHandler()操作。

3、处理请求分析

处理请求是由IoProcessor完成的,先来看看这部分的序列图:

这一阶段:

3.1 调用selector.select(),查看是否有可处理的SocketChannel

如果没有,就结束本轮处理。如果有,才进行后续操作。

3.2处理最新添加的session,方法是handlernewsessions()。过程是:

1)  从newSessions队列中取出IoSession,

2)  设置为非阻塞,并以 READ方式注册到Selector中,这才由Selector来接管这些SocketChannel。

3)为IoSession创建FilterChain

4)将Session放到managedSession集合中。

5)触发Session创建完毕事件。

3.3 交通管制处理。

本过程对应操作是updateTrafficMask()。

有时,我们需要在程序中控制是否进行写读操作,或者暂停读操作。要实现这个功能,可以使用IoSession的resumeRead()或者supendRead()。然而,程序中虽然调用了这两种方法,但是要想真正的对IO进行控制,还得通过注册感兴趣的操作来完成。这一点程序中并没有完成。

这一过程中,其实就是完成帮助应用程序完成未完成的操作。

3.4 根据兴趣事件进行相应处理。

这一过程对应序列图中的process()操作。

1)  拿到所有的通过selector.select(TIME_OUT)筛选出来的可以处理的SelectionKey

2)  根据SelectionKey,取到与之捆绑的IoSession。

3)  处理感兴趣的事件。

如果对读感兴趣,进入读取数据、业务处理流程。从序列图中,可以看出从SocketChannel读取数据,然后经过FilterChain,最后到达IoHandler。

如果对写感兴趣,进入属性数据处理流程。对于所有的对写感兴趣的IoSession,然后放到flushingSessions队列中。

4)对每一个Session处理完兴趣操作后,都有从3.1选择到的Set<SelectionKey>中移除关联的SelectionKey。

3.5 处理对写事件感兴趣的Session。

这一过程对应的是序列图中的flush()操作。

如果应用程序中使用了session.write()操作,例如示例程序。该session就会被放到flushingSessions队列中。

该过程操作是:

1)  就是将flushingSessions队列中的session取出来

2)  清除写兴趣

3)  处理session中的写请求队列(writeRequestQueue),也就是将writeRequestQueue中的每一个写请求中数据写到SocketChannel中。

4)  如果没有写完毕,还有剩余,就再次注册写兴趣。

5)  如果没有写完毕,就再放到flushingSeesions队列中。

3.6 清理需要移除的Session

这个过程对应序列图中的removeSessions()。

在3.2到3.5过程中,如果哪个过程出现了Exception,或者与客户端的连接断开了等情况下,相关联的Session都会被放到removingSessions队列中。

这个过程的处理是:

1)从removingSessions队列中取出每一个Session

2)如果Session处于处理阶段,清理writeRequestQueue,调用SelectionKey.cancel()来取消Selector对它的管理。

3)如果Session还处于未处理阶段,也就是也存在于newSessions队列中,就从newSessions队列移除之。

3.7 做空闲处理

对应于序列图中的notifyIdleSessions()操作。

时间: 2024-07-31 11:47:44

Mina 源码阅读:Server端基于NIO的处理流程的相关文章

Hadoop RPC源码阅读-服务端Server

RPC服务端的实例代码: public class Starter { public static void main(String[] args) throws IOException { RPC.Builder build = new RPC.Builder(new Configuration()); build.setBindAddress("localhost").setPort(10000).setProtocol(LoginServiceInterface.class).s

MINA源码阅读之Future系

首先Future系是对某个异步操作完成的监听:即setValue()的完成情况监听:get/setValue其实是对result字段封装,由此,可以这样讲,Future系其实对于对result字段状态的监听: Future又是如何被使用的的呢? ????让我们看一下源码中举例: * IoSession session = ...; * CloseFuture future = session.close(true); * // Wait until the connection is close

MINA源码阅读之ACP

Processor在XXAcceptor以及XXConnector中所扮演的只能就是:作为Acceptor以及Connetor所创建的Session的Processor: IoAcceptor作为他所创建的IoSession的IoService: NioProcessor在selector中创建的监听器类型为"OP_Read":NioAcceptor在Selector中所创建的类型为"OP_ACCEPT",NioConnector类型为"OP_CONN&q

LinkedHashMap源码阅读笔记(基于jdk1.8)

LinkedHashMap是HashMap的子类,很多地方都是直接引用HashMap中的方法,所以需要注意的地方并不多.关键的点就是几个重写的方法: 1.Entry是继承与Node类,也就是LinkedHashMap与HashMap的根本区别所在,Node是链表形式,只有next与下一个元素进行连接,而Entry的链表有before和after两个连接点. static class Entry<K,V> extends HashMap.Node<K,V> { Entry<K,

Yii源码阅读笔记(二十一)——请求处理流程

Yii2请求处理流程: 首先:项目路径/web/index.php (new yii\web\Application($config))->run();//根据配置文件创建App实例,先实例化yii\web\Application(),然后调用run()方法 该语句可分为两步: $application = new yii\web\Application($config);//实例化app $application->run();//调用run()方法 $config 为配置文件,通过 req

NIO框架之MINA源码解析(五):NIO超级陷阱和使用同步IO与MINA通信

1.NIO超级陷阱 之所以说NIO超级陷阱,就是因为我在本系列开头的那句话,因为使用缺陷导致客户业务系统瘫痪.当然,我对这个问题进行了很深的追踪,包括对MINA源码的深入了解,但其实之所以会出现这个问题,它的根不是MINA的原因,而是JDK底层的问题. JDK底层在实现nio时,为了能够唤醒等待在io上的线程,在windows平台使用了两个端口建立连接发消息实现.看如下代码: [java] view plain copy print? public class NIOTest { @Test p

NIO byteBUffer 讲解 及Mina 源码分析

1.传统的socket: 阻塞式通信模式 tcp连接: 与服务器连接时 .必须等到连接成功后 才返回 . udp连接: 客户端发送数据 ,必须等到发送成功后返回 . 每建立一个 Scoket连接时, 同事创建一个新线程对该 Socket进行单独通信(采用阻塞式通信 ) 这种方式具有很高的响应速度,并且控制起来也很简单,在连接数较少的时候非常有效,但是如果 对每一个连接都产生一个线程的无疑是对系统资源的一种浪费,如果连接数较多将会出现资源不足的情况 2.1NIO 设计背后的基石:反应器模式,用于事

NIO框架之MINA源码解析(一):背景

?? "你们的agent占了好多系统的端口,把我们的很多业务系统都给整死了,给我们造成了很大的损失,要求你们的相关领导下周过来道歉"   --   来自我们的一个客户. 怎么可能呢,我们都不相信,我们的agent只占一个端口啊! 事实胜过雄辩,经过查证,确实是由于我们的agent占了好多系统的端口,我看了一下日志,基本把系统可用的端口占完了! 为什么呢?MINA框架私自开的! 由于我们的agent端使用了NIO通信框架MINA,但并没有使用好,造成了这一几乎毁灭行的灾难. 还是先看代码

如何阅读Java源码 阅读java的真实体会

刚才在论坛不经意间,看到有关源码阅读的帖子.回想自己前几年,阅读源码那种兴奋和成就感(1),不禁又有一种激动. 源码阅读,我觉得最核心有三点:技术基础+强烈的求知欲+耐心. 说到技术基础,我打个比方吧,如果你从来没有学过Java,或是任何一门编程语言如C++,一开始去啃<Core Java>,你是很难从中吸收到营养的,特别是<深入Java虚拟机>这类书,别人觉得好,未必适合现在的你. 虽然Tomcat的源码很漂亮,但我绝不建议你一开始就读它.我文中会专门谈到这个,暂时不展开. 强烈