Zookeeper-Server端请求处理链

Zookeeper Server端对接收到的Client端请求,以及Leader接收到的Follower/Observer请求,都会以"处理链"的方式"分工/逐步"处理,这是一种良好的设计模式..不过事实上Zookeeper源码中,这部分代码写的确实比较"纠结"..

 

一. Folower端:

Follower与Client的通讯入口为ServerCnxn.doIO()方法,Follower与Leader的通讯操作入口Follower.followLeader()方法.下文中提到的请求,即为"Request"对象(将用户操作封装之后的对象)

FollowerZookeeperServer实例就是Follower为Client请求服务的对象.任何一个请求都将会依次经过如下"处理器"或过程:

1)   ZookeeperServer.processPacket(Request)方法开始处理请求,如果请求符合要求,将会被交付给"处理器".

2)   FollowerRequestProcessor(线程):作为Follower的首个"处理器",将Client请求队列化,因为其本身即为线程,则在线程run方法中,则从队列中逐个take出请求,并交付给"下一个处理器"(nextProcessor),对于write操作(create,delete,setData...)同时也将请求转发给Leader一份.

3)   Follower.followLeader()中,如果来自Leader的消息类型为"proposal",则将此消息交付给SyncRequestProcessor处理器.

4)   SyncRequestProcessor(线程):对于2)处理器转发给Leader的请求,Leader会经过处理后给所有的Followers发送"Proposal"(提议),Proposal中将会包含此次请求的zxid,cxid等.SyncRequestProcessor主要做了一件事情:将请求写入txnLog中.如果事务日志写入成功,则将请求转发给5)处理器

5)   SendAckRequestProcessor:因为在3)中,Follower已经接收到"提议",则在此处理器中,直接回馈Leader一个ACK包,按照惯例,此包仍然会包括zxid(此zxid来自proposal).

6)   Follower.followLeader()中,如果来自Leader的消息类型为"commit",则将此消息交付给CommitProcessor处理器.此处进行了严格的请求次序控制,如果发现乱序情况,则直接导致系统退出(乱序的特征:pendingTxns.element().zxid,其中pendingTxns是个队列,表示proposal队列,即commit的顺序必须和proposal的顺序一致)

7)   CommitProcessor(线程): 对于来自Leader的commit请求,会被队列化,那么在CommitProcessor线程的run方法中,则会逐个处理"commit"请求.此处理器很简单,它的特点就是让请求处理"逐个进行"传递给下一个处理器.

8)   FinalRequestProcessor:将数据变更操作持久化,操作ZKDatabase,如果有必要,则触发相应的watches.

 

二.Observer端: 和Follower很像,但是它没有SendAckRequestProcessor,当接收到commit类型的请求时,直接提交就行.它不参与proposal和ack.

 

二.Leader端:

Leader端和Follower端在交互上形成对应.Leader与Follower通讯入口为LearnerHandler.run();

1)   对于Follower转发给Leader的write操作,请求类型为Leader.REQUEST,则触发此请求添加到请求队列中,此后将有"处理器链"依次处理.

2)   PreRequestProcessor(线程):将请求队列化,是请求的预处理阶段,因为Leader可以断言所有的write操作必将带来额外的影响,比如节点的创建会影响其父节点的version变更,比如Sequential节点创建需要计算序列号码等.此处理器并没有做实际的工作,主要作用就是生成一个zxid,并交付给请求....继续下一个处理器.

3)   ProposalRequestProcessor:将请求封装成一个"Proposal"依次发送给所有的Follower,发送操作也是有LearnerHandler来做...此后,将有将请求交付给SyncRequestProcessor.

4)   SyncRequestProcessor(线程):和Follower一样,记录txnLog.

5)   AckRequestProcessor:是Leader对请求的补充操作,Leader对请求直接做"ACK"操作,意味着任何一个Proposal,Leader都会立即提交ACK.

6)   Leader此时将会获得Follower交付的ACK请求,将会直接使用leader.processAck(serverId,zxid..)处理,此方法的主要作用就是,对请求队列中亟待"commit"的请求进行确认,直到"大多数"Follower都对某个请求进行了ACK,此请求才会被commit;如果对一个已经commited的请求进行确认(即当前ack请求的zxid小于先已提交的zxid),将会忽略(下一个处理器,将会告知其立即提交)...

7)   CommitProcessor(线程):如果LearnerHandler接收到ACK请求时,都会执行Leader.commit()方法,此方法的最要作用就是针对"多数派"的请求,则向Follower/Observer发送Commit请求;此后,把此请求交付给下一个处理器ToBeAppliedRequestProcessor.

8)   ToBeAppliedRequestProcessor:根据命名,我们也能知道,此处理器就是在"即将实施变更"之前,做一些额外的工作,在向所有的Follower发送Commit之前,Leader特意把此请求添加一个队列中(为了防止,在最后时机发送乱序情况,比如发送commit时遇到异常),如果"请求"到达ToBeAppliedRequestProcessor,说明当前commit请求被如期发送给了所有的所有的Follower(事实上有可能正在发送),那么ToBeAppliedRequestProcessor所做的就是把队列头部的Commit移除,并继续传递给下一个处理器.

9)   FinalRequestProcessor:和Follower一样,在本地ZKDatabase中持久化此变更请求.

 

这就是Follower和Leader进行的"二阶段"提交和事务控制的全过程,不过因为IO操作本身就存在很多"异常可能";那么Follower和Leader所做的,就是控制好请求被执行的顺序,也就是确保事务性和全局数据一致性;如果Follower发现乱序或者IO异常,唯一能做的,就是重新和Leader同步;Leader能做的就是阻塞后续请求或者发起选举.

<think>我们正在讨论的是ZooKeeper的启动命令。用户希望了解在Linux系统中执行`bin/zookeeper-server-start.sh config/zookeeper.properties &`的具体含义。 注意:根据引用[1]和[2]的上下文,用户之前可能接触过ZooKeeper的安装和配置。引用[1]展示了启动zkServer的命令`zkServer.sh start`,引用[2]展示了ZooKeeper解压后的目录结构。 但是,用户现在询问的是另一个启动命令:`bin/zookeeper-server-start.sh config/zookeeper.properties &`。这个命令常见于Kafka附带的ZooKeeper启动方式(因为Kafka内置了ZooKeeper),而引用中展示的是独立ZooKeeper的启动方式。 因此,我们需要解释这个命令的各个部分,并注意它与独立ZooKeeper启动命令的区别。 命令分解: 1. `bin/zookeeper-server-start.sh`:启动脚本。 2. `config/zookeeper.properties`:配置文件。 3. `&`:让命令在后台运行。 注意:在Kafka的发行版中,通常会附带一个ZooKeeper,其启动脚本就是`zookeeper-server-start.sh`,而配置文件是`zookeeper.properties`。而独立安装的ZooKeeper通常使用`zkServer.sh`启动,配置文件是`zoo.cfg`。 因此,我们需要向用户说明: - 这个命令是启动ZooKeeper服务器的,但它是Kafka发行版中自带的ZooKeeper的启动方式。 - 解释每个参数的作用。 - 解释后台运行符号(&)的作用。 同时,根据引用[1]中独立ZooKeeper的启动方式,我们可以对比说明。 回答结构: 1. 命令用途:启动ZooKeeper服务器(通常用于Kafka自带的ZooKeeper)。 2. 详细分解命令的每个部分。 3. 解释后台运行符号(&)的作用。 4. 与独立ZooKeeper启动命令(zkServer.sh)的对比。 5. 执行该命令的预期输出和效果。 6. 注意事项(比如配置文件路径是否正确,权限问题等)。 生成相关问题: 1. 如何停止这个后台运行的ZooKeeper服务器? 2. 如何查看ZooKeeper服务器的运行日志? 3. 如何配置ZooKeeper? 4. ZooKeeper在Kafka中的作用是什么? 注意:在回答中,我们引用了用户提供的引用[1]和[2],但要注意引用[1]是独立ZooKeeper的启动,而引用[2]是解压目录,所以我们在解释时要注意区分。</think>### ZooKeeper 启动命令详解:`bin/zookeeper-server-start.sh config/zookeeper.properties &` 在 Linux 系统中,该命令用于启动 ZooKeeper 分布式协调服务,常见于 Kafka 等分布式系统的环境部署。以下是命令的逐部分解析: --- #### **1. `bin/zookeeper-server-start.sh`** - **作用**:ZooKeeper 的官方启动脚本,位于安装目录的 `bin/` 子目录下。 - **路径说明**: - 默认安装路径如引用[2]所示:`/usr/zk/apache-zookeeper-3.5.x-bin/bin/` - 执行时需确保当前在 ZooKeeper 安装目录或使用绝对路径 - **功能**: - 加载 JVM 参数(如内存配置) - 初始化 ZooKeeper 服务环境 - 启动 Java 进程运行 `org.apache.zookeeper.server.quorum.QuorumPeerMain` 主类 --- #### **2. `config/zookeeper.properties`** - **作用**:指定 ZooKeeper 的配置文件。 - **关键配置项**: ```properties dataDir=/tmp/zookeeper # 数据存储目录 clientPort=2181 # 客户连接口 tickTime=2000 # 心跳时间(毫秒) initLimit=10 # 初始化集群连接超时(tickTime倍数) syncLimit=5 # 请求响应超时(tickTime倍数) ``` - **路径要求**: - 默认在 `conf/` 目录下(如引用[1]中的 `/home/hadoop/opt/app/zookeeper/conf/zoo.cfg`) - 可自定义路径,但需确保权限正确 --- #### **3. `&` 符号** - **作用**:将进程放入**后台运行**,释放当前终- **优势**: -关闭后服务仍运行 - 可继续执行其他命令 - **验证运行**: ```bash jps -l | grep QuorumPeerMain # 查看 ZooKeeper 进程 ``` --- #### **4. 命令完整执行流程** ```mermaid graph TD A[执行启动脚本] --> B[加载 JVM 环境] B --> C[解析 zookeeper.properties] C --> D[初始化数据目录] D --> E[启动 QuorumPeerMain 进程] E --> F[绑定口 2181] F --> G[进入后台运行] ``` --- #### **5. 与独立 ZooKeeper 启动的对比** | 特性 | 本命令 | 独立启动命令 `zkServer.sh`[^1] | |--------------------------|--------------------------------|--------------------------------------| | **适用场景** | Kafka 内置 ZooKeeper | 独立 ZooKeeper 集群 | | **配置文件** | `zookeeper.properties` | `zoo.cfg` | | **日志输出** | 输出到启动终 | 自动重定向到日志文件 | | **管理方式** | 需手动管理进程 | 内置服务管理(start/stop/status) | --- #### **6. 执行示例与验证** ```bash # 进入安装目录执行 cd /usr/zk/apache-zookeeper-3.5.8-bin bin/zookeeper-server-start.sh config/zookeeper.properties & # 验证启动(预期输出包含“binding to port 0.0.0.0/0.0.0.0:2181”) tail -f logs/zookeeper.out # 客户连接测试 bin/zkCli.sh -server 127.0.0.1:2181 ``` --- #### **注意事项** 1. **权限问题**: - 确保用户对 `dataDir` 目录有读写权限 - 启动用户需拥有脚本执行权限(`chmod +x bin/*.sh`) 2. **配置文件检查**: -口冲突,修改 `clientPort` - 集群部署需配置 `server.x=host:port1:port2` 3. **内存调整**: - 在 `bin/zookeeper-server-start.sh` 中修改 JVM 参数: ```bash export KAFKA_HEAP_OPTS="-Xmx2G -Xms2G" # 调整内存分配 ``` --- ### 相关问题 1. ZooKeeper 集群部署需要修改哪些配置参数? 2. 如何优雅停止通过 `&` 启动的后台 ZooKeeper 进程? 3. ZooKeeper 日志文件的位置和解析方法是什么? 4. 为什么 Kafka 需要依赖 ZooKeeper? 5. 如何监控 ZooKeeper 的运行状态? [^1]: 独立 ZooKeeper 的启动方式参考 [^2]: ZooKeeper 安装目录结构示例
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值