背景
Zookeeper作为一个服务器,自然要与客户端进行网络通信,如何高效的与客户端进行通信,让网络IO不成为ZooKeeper的瓶颈是ZooKeeper急需解决的问题,ZooKeeper中使用ServerCnxnFactory
管理与客户端的连接,其有两个实现,一个是NIOServerCnxnFactory
,使用Java原生NIO实现;一个是NettyServerCnxnFactory
,使用netty实现;使用ServerCnxn
代表一个客户端与服务端的连接.
ServerCnxnFactory
注:下文或注释中的连接就是客户端发起的TCP连接,也即SocketChannel
类
ZooKeeper可以通过设置系统属性zookeeper.serverCnxnFactory
配置ServerCnxnFactory的实现类,默认使用NIOServerCnxnFactory
NIOServerCnxnFactory
实现思路
一般使用Java NIO的思路为使用1个线程组监听OP_ACCEPT
事件,负责处理客户端的连接;使用1个线程组监听客户端连接的OP_READ
和OP_WRITE
事件,处理IO事件(netty便是如此实现).
但ZooKeeper并不是如此划分线程功能的,NIOServerCnxnFactory
启动时会启动四类线程
- accept thread:该线程接收来自客户端的连接,并将其分配给selector thread(启动一个线程)
- selector thread:该线程执行select(),由于在处理大量连接时,select()会成为性能瓶颈,因此启动多个selector thread,使用系统属性
zookeeper.nio.numSelectorThreads
配置该类线程数,默认个数为 核心数/2−−−−−−−√ 核 心 数 / 2 (至少一个) - worker thread:该线程执行基本的套接字读写,使用系统属性
zookeeper.nio.numWorkerThreads
配置该类线程数,默认为