Soul API网关源码解析08 - 数据同步篇

目标

  • 配置连接zookeeper(zk)注册中心

    • soul-admin注释websocket配置打开zk配置
    • soul-bootstrap同理注释掉websocket配置打开zk配置
  • 启动zk注册中心并且查看是否启动成功

  • zk数据节点注册原理

    • 什么是Zookeeper
    • zk设计总览
    • zk架构
    • znode存储结构
    • watch机制
  • soul-admin之zk注册流程

配置连接zookeeper注册中心

soul-admin注释websocket配置打开zk配置

image.png

soul-bootstrap同理注释掉websocket配置打开zk配置

image.png

配置之前我本地运行了端口为 2181 的zk服务

启动zk注册中心,并且查看是否启动成功

zkServer.sh start // 启动服务
 zkServer.sh stop  // 关闭服务 
zkCli.sh // 启动命令客户端
image.png

出现如上图圈出的SyncConnected代表zk启动成功

小结

经过源码大致流程分析,非zk部分流程与websocket数据同步相同最终数据更新到当前正在使用的plugin,和具体缓存。但是关于zk本身的节点注册和数据变动如何通知关心的一方这块的原理不是很清楚,临时调整方案,先去研究下zk关于这两块的实现方式,之后再来完善soul这部分。

zk数据注册原理分析

什么是Zookeeper

ZooKeeper is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services. All of these kinds of services are used in some form or another by distributed applications. Each time they are implemented there is a lot of work that goes into fixing the bugs and race conditions that are inevitable. Because of the difficulty of implementing these kinds of services, applications initially usually skimp on them, which make them brittle in the presence of change and difficult to manage. Even when done correctly, different implementations of these services lead to management complexity when the applications are deployed.

大概意思就是zk是一个维护配置信息,命名,提供分布式同步以及提供组(集群)服务的集中式服务。所有这些类型的服务都被应用在分布式服务程序中。下面就是讲zk诞生的前世吧,也就是背景。大概就是分布式应用不好管理,没有一个统一的方式方法区管理他们,由此zk诞生。

zk设计总览

本次观看的官网文档 Zookeeper 3.6 Documentation

  • 设计目标

zk很简单,它允许分布式进程(soul-admin,soul-bootstarp)通过共享分层名称空间(/soul/plugin...)相互协调,该命名空间的组织方式类似于标准的文件系统。命名空间由数据寄存器(znode)组成。它类似文件目录。与设计用于存储文件系统的目录结构又不同,因为zk是节点存储在内存中。这样就意味着zk 可以实现高吞吐量和低延迟。

  • 设计初衷

大家知道分布式协调服务很难做。进程之间很容易出现诸如竞争条件和死锁之类的问题。zk为了让后来者实施简单规避这些问题,从此诞生主要是为了减轻分布式应用程序从头开始做协调性任务。

  • zk特性

  • zk本身是可复制的。ZooKeeper itself is intended to be replicated over a set of hosts called an ensemble. 组成zk服务的服务器都是必须相互了解的。他们维护内存中的状态图像,以及持久存储中的事务日志与快照。只要大多数服务可用,zk就可用。

ZK架构

image.png

ZNode存储结构

  • 一次写入、多次读取,数据写入后不可更改。

  • 可以存储多个版本的数据,以实现更新顺序性。

  • 一次性读取整个Znode,不支持部分读取。

  • 根据数据的生命周期,具有4种节点,在创建时确定并且不能再修改。

  • 临时节点(EPHEMERAL):不支持子节点,会在客户端会话结束时被删除。

  • 临时顺序节点(EPHEMERAL_SEQUENTIAL):临时节点,但父节点会为一级子节点记录创建时间,记录节点的创建顺序。

  • 持久节点(PERSISTENT):持久存储,一般根据客户端需求删除。

  • 持久顺序节点(PERSISTENT_SEQUENTIAL):持久节点,但父节点会为一级子节点记录创建时间,记录节点的创建顺序。

Watch机制

客户端可以通过watch机制关注Znode的信息变化,实现配置管理、数据同步和分布式锁等功能。

客户端首先需要注册一个watch,来观察某个Znode。当出现数据更新或被删除、子节点发生变化等情况时,Zookeeper集群会通过异步消息向客户端发送事件通知。通知发送后,该watcher就会失效,如果此时再发送信息变化,客户端就无法获取新的通知,除非客户端在进行新的注册(这块soul就根据首次初始化watch之后,后面数据发生变化进入处理前又再次注册一次。也就解决watch使用完一次之后作废掉,再次注册原因了)。可见,watch机制能够确保消息的顺序性(旧消息被接收之前,客户端无法获得新消息)以及最终一致性,但无法确保所有的数据变化都能够被观察到。

Soul-Admin ZK注册流程

经过上面对zk特性了解之后,我们下面就分析下soul-admin端zk初始化的流程。

ZookeeperDataInit

image.png

因为实现了CommandLineRunner,在Bean初始化之后就会执行run方法。这里面run 方法主要就是初始化soul那几种基础数据Rule,Auth,Meta。

image.png

根据图和验证我们知道soul在注册数据到zk时候采用的持久节点。所以一般zk服务器不换的话,这里syncAll只会执行一次,这个syncAll里面也就是从数据库中全量拿出数据,通过昨天分析的事件分发器,被zk的监听器接收到就将数据写到zk对应的节点里面

基础数据改变数据同步

  • 数据发生变动ApplicationEvent 触发DataChanged事件
  • zk监听器接收到数据发生变化,就判断事件更新类型是否是DELETE,如果是Plugin数据变动,还要删除对应的Selector,Rule数据,如果不是删除就执行创建或者更新节点的操作
image.png
  • 判断节点数据是否存在,存在就写数据,不存在则先创建节点,然后在写数据
image.png

总结

到这里我们了解清楚了zk到底是什么东西,具体admin端关于zk初始化以及基础数据的处理化。同时数据发生变动之后是如何更新到zk节点的。中间事件通知分发原理早在前面已经介绍过了,这里就不累赘了。至于bootstrap 那边如何知道数据变化的下一章分析。

参考

soul github
soul document

你可能感兴趣的:(Soul API网关源码解析08 - 数据同步篇)