JETTY 的三大模块中,连接器实现I/O的请求响应,JETTY 既实现了BIO 的阻塞式I/O,也实现了异步非阻塞式的I/O模式,而在JETTY自身的实现了,默认采用了异步非阻塞时的NIO模型,NIO的连接器实现为SelectChannelConnector。
1 NIO 连接器的工作模型
NIO 连接器的工作模型如下图所示。Acceptor负责监听指定的端口,当有新的连接请求达到时,Acceptor会建立新的SocketChannel对象,然后调用SelecttorManager的register方法注册,SelectortManager用于管理一组SelectSet,后者维持一个特定的Selector对象用于选择注册的I/O事件,通过SelectorManager方式进行管理,使得JETTY很容易扩展以满足大规模I/O请求的需要。
当有新的SocketChannel由Acceptor注册到SelectorManager时,SelectorManager就会通知具体的SelectSet,SelectSet和Acceptor一一对应,有几个Acceptor就有几个SelectSet,在初始化的时候由Acceptor的个数执行,在启动时初始化。SelectSet会把新进来的SocketChannel加到它的changes队列中,changes队列维护了该SelectSet制定的Selectot选择的时间,自身线程会不断的轮询这个队列,处理新连接通道的建立和创建端点负责I/O读写。SocketChannel加入后,会创建对应的读操作的监听键key,下次该通道有请求时,就会触发SelectSet创建endpoint进行I/O读写操作。
2 SelectChannelConnector 连接器实现代码分析
1) 连接器相关属性
_acceptChannel ,一个ServerSocketChannel通道,用于和客户端简历连接信息
_lowResourcesConnections, 一个整型变量描述在低资源情况下的连接数目
_lowResourcesMaxIdleTime, 一个整型变量描述在低资源情况下的连接最大空闲时间
_manager : 一个SelectorManager对象实例,用于管理一组SelectSet(稍后分析)
以上是SelectorChannelConnector自身的属性,SelectorChannelConnector本身还继承自AbstractorConnector,AbstractConnector自身定义了一组属性:
_server :Server实例
_threadPool : 线程池实例
_host: String 变量表示主机名称
_port : int变量表示监听的端口
_acceptors : int 变量表示监听器的个数
_maxIdleTime : int 变量表示连接最大的空闲时间,默认为200秒
_lowResourceMaxIdleTime : int 变量表示在低资源情况下的最大空闲时间,默认为-1表示连接不保持
2)连接器初始化
SelectChannelConnector初始化非常简单 :
public SelectChannelConnector()
{
_manager.setMaxIdleTime(getMaxIdleTime());
setAcceptors(Math.max(1,(Runtime.getRuntime().availableProcessors()+3)/4));
}
SelectorChannelConnector初始化仅仅是两行代码,第一行代码用于设置manager的最大的空闲时间,getMaxIdleTime()返回Connector的最大空闲时间,因此默认为200秒。。第二行代码设置acceptor的个数,acceptor的个数根据公式Math.max(1,(Runtime.getRuntime().availableProcessors()+3)/4)算出,因此,当可用的处理器个数大于等于5个时,监听器的个数会大于1(这里需要探讨acceptor设置的公式)。
3) 连接器的启动和监听过程
上面分析了连接器的各个组件以及他们如何协同工作的过程,也简单讲述了连接器的初始化过程。连接器的各组件的关系以及监听器建立过程是在连接器启动时完成