目录
- AcceptThread
- 数据结构
- 构造函数
- run()
- SelectorThread
- 数据结构
- processAcceptedConnections()
- select()
- processInterestOpsUpdateRequests()
本文开始分析 ServerCnxnFactory的工作原理,按照顺序我们这样分析:
- 建立连接
- 监听读写事件
- 处理读写就绪的事件
- 连接的过期管理
AcceptThread
首先是AcceptThread线程,当有客户端连接服务器时,该线程会监听到连接请求。
数据结构
构造函数
run()
AcceptThread本质是线程,当获得CPU资源后会执行它的run()方法,我们看下它的run()方法是如何处理监听到的事件的。
接下来我们看下当收到客户端连接请求时是如何转交给SelectThread处理的。
AcceptThread的工作就到此结束,接下来就到SelectorThread。
SelectorThread
AcceptThread
线程通过调用addAcceptedConnection()
方法将新连接交付给SelectorThread
,我们先看下该方法的内容:
该方法很简单,就是将连接添加到acceptedQueue
队列中然后唤醒selector,接下来具体分析SelectorThread
。
数据结构
它的数据结构很简单,一个selector和两个队列
acceptedQueue
存储来自客户端的连接请求- 在处理IO之前会把SelectionKey的监听事件清零,此时会把这个key存放到
updateQueue
中,等IO处理结束再恢复监听。
SelectorThread
是一个线程,核心代码在run()
方法上
run()
方法中核心代码主要是第一个循环的三个方法select()
、processAcceptedConnections()
、processInterestOpsUpdateRequests()
。为了更好的理解run()的处理逻辑,我们对着三个方法的分析调整一下顺序:
processAcceptedConnections()
,接收来自客户端的连接select()
,监听来自客户端的OP_READ事件processInterestOpsUpdateRequests()
,处理完channel的请求后恢复它监听的事件类型
processAcceptedConnections()
NIOServerCnxn实例维护每一个客户端的连接,服务端与客户端的所有通信都是由它负责的,它负责统一接收来自客户端的所有请求,并将请求内容从底层网络I/O中完整第读取出来,后续再详细分析该类。
select()
与客户端的连接建立后开始监听来自客户端的请求
继续看handleIO()
方法
select()
的过程主要是selector调用select()
方法获取IO就绪的key,然后将这些key转交给worker线程处理。这里要注意,当它监听到一个IO请求时,在完成这个请求之前会停止监听来自客户端的请求。
processInterestOpsUpdateRequests()
processInterestOpsUpdateRequests()
主要是负责更新updateQueue
中key的监听事件类型,在WorkerService处理完请求后会获取updateQueue
中的key进行更新。
SelectorThread的工作流程就介绍到,接下来到真正处理IO的WorkerService。
篇幅限制,下文继续。