启动流程
启动类:org.apache.zookeeper.server.quorum.QuorumPeerMain
- 调用ZooKeeperServerMain.main(args)
- 把配置解析成ServerConfig对象
- 初始化FileTxnSnapLog对象:快照和日志操作工具类
- 初始化JvmPauseMonitor
- 初始化ZooKeeperServer
- 启动AdminServer
- 创建NIOServerCnxnFactory对象
- 开启ServerSocketChannel,并绑定客户端端口
- 初始化WorkerService线程池
- 启动多个SelectorThread线程
- 启动AcceptThread线程
- 根据快照和日志初始化ZKDatabase
- 启动Session跟踪器SessionTracker
- 初始化RequestProcessor Chain
- 启动请求限流器RequestThrottler
数据接收模型
AcceptThread线程负责接收Socket连接,没接收到一个Socket连接会生成一个SocketChannel对象,并生成一个NIOServerCnxn对象,然后会把SocketChannel对象分配给某个SelectorThread线程,分配方式是把SocketChannel对象添加到SelectorThread中的acceptedQueue队列中。
服务端有多个SelectorThread线程,每个线程负责处理多个SocketChannel的读写就绪事件,SelectorThread线程会不断的从acceptedQueue队列中获取SocketChannel对象并注册读事件到SelectorThread线程中的Selector对象上,同时,SelectorThread线程也会不断的从Selector对象上获取就绪事件。
每获取到一个就绪事件,就会把该事件先封装为一个IOWorkRequest对象,然后会把IOWorkRequest对象封装为ScheduledWorkRequest对象,ScheduledWorkRequest是一个线程,然后会把ScheduledWorkRequest扔给线程池进行处理。
线程池中的线程执行时,调用的就是IOWorkRequest的doWork方法,而doWork方法中会调用NIOServerCnxn的doIO方法。
NIOServerCnxn对象才是真正执行就绪事件的逻辑实现。整个模型相当于,没接收到一个就绪事件,NIOServerCnxn对象就会去处理该事件。
当客户端向服务端发送命令是,NIOServerCnxn就会处理读就绪事件,NIOServerCnxn就会从SocketChannel中取读取数据,并进行处理。