【Zookeeper】单机模式启动与接收数据模型源码解析

DataTree : 节点的存储形式

在这里插入图片描述

DataNode

在这里插入图片描述

服务端架构

  • 当服务端接收到命令做的事

    • 解析配置文件:先持久化命令,即事务日志、快照
    • 再更新到DataTree
  • 那我们启动服务端的时候,就会调用启动类:org.apache.zookeeper.server.quorum.QuorumPeerMain

会执行initializeAndRun()方法:

  • 解析配置
    将配置文件的内容初始化QuorumPeerConfig类
  • 开启一个定时器,根据配置清空多余的日志和快照文件
    通过new 一个Timer定时任务,每个一段时间就去删快照,只保留指定的个数(默认是3)
  • 调用ZooKeeperServerMain.main(args)开启真正的启动流程
    在这里插入图片描述

ZooKeeperServerMain.main(args)

  • initializeAndRun
    • 解析配置文件初始化到ServerConfig
    • runFromConfig:单机环境下启动Zookeeper

在这里插入图片描述

runFromConfig 单机环境下启动Zookeeper

  • 初始化FileTxnSnapLog对象:快照和日志操作工具类
  • 初始化JvmPauseMonitor
  • 初始化ZooKeeperServer
  • 启动AdminServer
  • 绑定端口,并做准备工作
    • 创建NIOServerCnxnFactory对象
    • 开启ServerSocketChannel,并绑定客户端端口
    • startup() 启动
      • 初始化WorkerService 线程池
      • 启动多个SelectorThread 负责接收读写就绪事件
      • 启动AcceptThread 负责接收连接事件
      • 根据快照和日志初始化ZKDatabase
      • 启动Session跟踪器SessionTracker
      • 初始化RequestProcessor Chain
      • 启动请求限流器RequestThrottler
  • 启动容器节点定时器
  • shutdownLatch.await()
    主线程执行完上面的逻辑就会阻塞在这里,等到zkServer被shutdown时,才会继续向下执行

绑定端口

runFromConfig 中的以下部分就是关于绑定端口的:
在这里插入图片描述

  • 创建NIOServerCnxnFactory对象
    服务端每接收到客户端的一个连接就会生成一个ServerCnxn对象 ,Zookeeper用nio或netty进行客户端与服务端的绑定。
    选择哪个方式就会拿哪个方式的工厂,默认是用nio,所以就默认创建一个NIOServerCnxnFactory。

  • 开启ServerSocketChannel,并绑定客户端端口,设置最大客户端连接限制数

  • startup()
    这里就是创建了什么工厂,就调用哪个工厂的startup方法,我们默认用的是NIOServerCnxnFactory
    在这里插入图片描述

    • start() 线程池
      • 初始化WorkerService 线程池
      • 启动SelectorThread 负责接收读写就绪事件
      • 启动AcceptThread 负责接收连接事件
    • zks.startdata() 初始化数据
      • 初始化ZKDatabase,加载数据
      • 还会把session加载出来,放到sessionWithTimeouts中
    • zks.startup()
      • 创建sessionTracker
      • 初始化RequestProcessor Chain
      • 创建requestThrottler
      • 注册jmx
      • 修改为RUNNING状态
      • notifyAll()
接收数据模型:SelectorThread和AcceptThread
  • 首先创建一个线程池
  • 启动多个SelectorThread
    有多个SelectorThread,并且一个SelectorThread会负责多个SocketChannel
  • 启动一个AcceptThread,并将SocketChannel分配给SelectorThread

AcceptThread的工作流程

AcceptThread是负责接收Socket连接的

  • AcceptThread 每接收到一个socket连接就会得到一个SocketChannel对象
  • 然后通过轮询的方式把SocketChannel分配给某个SelectorThread,分配方式是把SocketChannel对象放到SelectorThread的队列acceptQueue中
    通过offer() 添加到阻塞队列acceptQueue中
  • 唤醒Selector,让SelectorThread线程负责处理SocketChannel里的数据
    在这里插入图片描述

SelectorThread的工作流程

SelectorThread就是把SocketChannel对象包装一下,给线程池处理
服务端有多个SelectorThread线程,每个线程负责处理多个SocketChannel的读写就绪事件,SelectorThread线程会不断的从acceptedQueue队列中获取SocketChannel对象并注册读事件到SelectorThread线程中的Selector对象上,同时,SelectorThread线程也会不断的从Selector对象上获取就绪事件。

  • 循环进行如下操作
    • 遍历就绪事件,得到读就绪事件或写就绪事件就进行处理,即这里就在处理客户端的命令
      具体处理流程:把key包装成IOWorkRequest,再封装成scheduledWorkRequest,扔到之前最开始创建的线程池中去execute。程池中的线程执行时,调用的就是IOWorkRequest的doWork方法,而doWork方法中会调用到NIOServerCnxn的doIO方法。这里就是真正的处理读写事件
    • 从acceptQueue(是一个BlockingQueue)中拿SocketChannel对象
      • 注册读事件
      • 并创建NIOServerCnxn对象(Socket连接的上下文)

在这里插入图片描述

RequestProcessor

链式的后置处理器一共有三个:

  • PrepRequestProcessor
  • SyncRequestProcessor
  • FinalRequestProcessor

在这里插入图片描述

NIOServerCnxn doIO 处理数据的逻辑

NIOServerCnxn对象才是真正执行就绪事件的逻辑实现。整个模型相当于,每接收到一个就绪事件,NIOServerCnxn对象就会去处理该事件。

NIOServerCnxn做的工作就是把客户端发来的数据放到incomingBuffer中。

客户端发来的命令会被打包成Packet,其中前4个字节为这个Packet的长度

  • 先读数据包的前四个字节得到数据包的长度,存在incomingBuffer中
    首先incomingBuffer是4个字节,这样就将Packet的前四个字节读到了incomingBuffer,也就是这时incomingBuffer存的是 数据包的长度
  • readLength() 会将数据包的长度len读出来,给incomingBuffer分配len字节的空间
  • readPayload() 用incomingBuffer读取len个字节的数据放到incomingBuffer中
    这里是真正读数据的过程
    • 如果没有初始化好,readConnectRequest() 连接初始化,读ConnectRequest对象
      客户端发送连接请求后还会给服务端发送ConnectRequest,其中包括了SessionTimeOut。服务端需要读一下ConnectRequest内容,才算初始化完成。 其中会判断服务端的SessionTimeOut和传来的SessionTimeOut哪个小就用哪个。
      并构造connectResponse对象,其中会传SessionTimeOut,返回给客户端。
    • 如果是初始化好的,就readRequest() 处理命令请求,进行增删改查
      调用zkServer. 进行增删改查
      在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值