Zookeeper-请求处理链

    • 背景
    • 单机版初始化
    • PrepRequestProcessor
      • 基本功能
      • 线程通信
    • SyncRequestProcessor
      • 基本功能
      • 线程通信
    • FinalRequestProcessor
      • 基本功能
    • 总结
    • 参考

背景

Zookeeper中使用责任链模式处理客户端提交的请求,本文介绍常用的RequestProcessor如何工作?各线程间如何通信?

注:下文中使用事务代表会改变服务器状态的请求,如创建节点,更新数据

单机版初始化

单机版服务器在初始化ZooKeeperServer时,创建并启动了请求处理链,代码如下:

    /**
     * 设置单机版服务器的请求处理链
     * {@link PrepRequestProcessor}->{@link SyncRequestProcessor}->{@link FinalRequestProcessor}
     */
    protected void setupRequestProcessors() {
        RequestProcessor finalProcessor = new FinalRequestProcessor(this);
        RequestProcessor syncProcessor = new SyncRequestProcessor(this,
                finalProcessor);
        ((SyncRequestProcessor) syncProcessor).start();
        firstProcessor = new PrepRequestProcessor(this, syncProcessor);
        ((PrepRequestProcessor) firstProcessor).start();
    }

单机版服务器包含3个请求处理器,从前往后依次为PrepRequestProcessor->SyncRequestProcessor->FinalRequestProcessor

PrepRequestProcessor

基本功能

PrepRP是服务器的请求预处理器,能够识别出当前客户端是否是事务请求,对于事务请求,PrepRP对其进行一系列预处理,如创建请求事务头,事务体,会话检查,ACL检查等.
由于其检查请求是否是事务请求,因此其代码中存在大量的switch... case ...,代码重复且庞杂,因此就不贴源码了.

线程通信

PrepRP继承了Thread,因此其是一个单独的线程,通过PrepRP.submittedRequests与其他线程通信,submittedRequests中存放待处理的请求,调用processRequest()即可将request添加至submittedRequests中:

    @Override
    public void processRequest(Request request) {
        submittedRequests.add(request);
    }

我们来逆向推下该方法的调用链:
PrepRequestProcessor.processRequest()<-ZooKeeperServer.submitRequest()<-ZooKeeperServer.processPacket()<-NIOServerCnxn.readRequest()<-NIOServerCnxn.readPayload()<-NIOServerCnxn.doIO()
不知道你对最后一个方法NIOServerCnxn.doIO()是否有印象,该方法在worker thread中被调用,用于读取客户端发送的数据,因此submittedRequests就是worker thread和prepRP thread通信的工具.

SyncRequestProcessor

基本功能

SyncRP的主要功能就是生成快照文件和将事务写入事务日志中.详见Zookeeper-持久化

线程通信

SyncRP也继承了Thread,通过queuedRequests与prepRP thread通信,调用processRequest()即可将request添加至queuedRequests中:

    /**
     * @param request 将要被处理的request
     */
    @Override
    public void processRequest(Request request) {
        //将request加入请求队列
        queuedRequests.add(request);
    }

FinalRequestProcessor

基本功能

FinalRP主要完成两个功能:

  1. 创建客户端请求的响应
  2. 将事务应用到内存数据中去

代码较为简单,就不贴源码了.

总结

参考

你可能感兴趣的:(ZooKeeper)