ServerCnxnFactory 连接管理工厂的介绍

ServerCnxnFactory 是 ZooKeeper 中用于管理和处理客户端连接的连接管理工厂。它负责接受和处理来自客户端的连接请求,并将请求分派给适当的处理程序。ServerCnxnFactory 是 ZooKeeper 的核心组件之一,它在整个 ZooKeeper 的运行过程中起着重要的作用。

ServerCnxnFactory 连接管理工厂的初始化

在 ZooKeeper 的启动过程中,会通过调用 org.apache.zookeeper.server.ZooKeeperServer 启动方法 start() 来进行初始化。在 start() 方法中,会创建 ServerCnxnFactory,并将其与监听的 IP 地址和端口绑定。下面是 ServerCnxnFactory 的初始化代码:

int maxClientCnxns = ConfigurationManager.getInstance().getInt(ConfigKey.MAX_CLIENT_CNXNS.getKey(), 60);
int tickTime = ConfigurationManager.getInstance().getInt(ConfigKey.TICK_TIME.getKey(), 2000);

InetSocketAddress addr = new InetSocketAddress(ip, clientPort);
factory = ServerCnxnFactory.createFactory(addr, maxClientCnxns);
factory.startup(zkServer);
Java

在上面的代码中,首先通过配置管理器获取最大客户端连接数(maxClientCnxns)和心跳时间(tickTime)。然后创建一个 InetSocketAddress 对象,用于表示绑定的地址和端口。最后调用 ServerCnxnFactory 的 createFactory() 方法创建 ServerCnxnFactory 实例,并调用 startup() 方法启动 ServerCnxnFactory。

ServerCnxnFactory 连接管理工厂的处理连接请求

ServerCnxnFactory 接受并处理来自客户端的连接请求。它使用 Java 的 NIO 库来实现非阻塞 IO。ServerCnxnFactory 维护一个 ServerSocketChannel 对象,该对象用于接受客户端的连接请求。一旦有新的连接请求到达,ServerSocketChannel 会触发一个 SelectionKey 的 ACCEPT 事件,然后 ServerCnxnFactory 会调用 accept() 方法获取新连接的 SocketChannel,然后创建一个 ServerCnxn 实例来处理该连接。下面是 ServerCnxnFactory 处理连接请求的代码:

// 接受新的连接请求
SelectionKey key = channel.register(selector, SelectionKey.OP_ACCEPT);
while (!Thread.currentThread().isInterrupted()) {
    // 处理连接请求
    int numKeys = selector.select(1000);
    Set<SelectionKey> selected;
    synchronized (this) {
        if (selectorKeys.size() == 0) {
            continue;
        }
        selected = new HashSet<SelectionKey>(selectorKeys);
        selectorKeys.clear();
    }

    for (Iterator<SelectionKey> it = selected.iterator(); it.hasNext();) {
        SelectionKey selectionKey = it.next();
        if ((selectionKey.readyOps() & SelectionKey.OP_ACCEPT) != 0) {
            // 接受新的连接请求
            ServerSocketChannel ssc = (ServerSocketChannel) selectionKey.channel();
            SocketChannel sc = ssc.accept();
            // 创建 ServerCnxn 实例处理连接
            factory.createConnection(sc);
        }
    }
}
Java

在上面的代码中,首先通过 ServerSocketChannel 的 register() 方法注册一个 ACCEPT 事件的 SelectionKey。接着使用一个循环来等待连接请求的到来。通过调用 selector 的 select() 方法阻塞等待直到有事件到达,然后获取到达的事件的 SelectionKey 集合。然后遍历集合,对每个事件进行处理,如果是 ACCEPT 事件,则通过 accept() 方法获取新的 SocketChannel,并通过 createConnection() 方法创建一个 ServerCnxn 实例来处理该连接。