遇见Golang|ETCD 的组件架构和内部通信


文章目录

  • ETCD 常用术语
  • ETCD 核心架构
  • ETCD 网关和gRPC-gateway
    • ETCD网关:构建etcd集群的门户
    • gRPC-Gateway:为非gRPC的客户端提供HTTP接口
  • gRPC-proxy
    • 可伸缩的watch API
    • 可伸缩的lease API
    • 空间命名
  • ETCD 组件架构
  • ETCD的交互总览
  • etcd的gRPC通信接口
    • Client定义
    • 读写过程概述
      • 读请求
      • 写请求

ETCD 常用术语
术语 描述 备注
Raft etcd实现一致性的核心 etcd有etcd-raft模块
Follower Raft中的从属节点 竞争leader失败
Leader Raft中的领导协调节点 Leader 节点协调整个集群
Candidate 候选节点 当Follower接受Leader节点的消息超时会转变为Candidate
Node Raft 状态机的实例 Raft 中涉及多个节点
Member etcd实例,管理着对应的Node节点 可处理客户端请求
Peer 同一集群中的另一个Member 其他成员
Cluster etcd集群 拥有多个etcd Member
Lease 租期 关键设置的租期,过期删除
Watch 检测机制 监控键值对的变化
Term 任期 某个节点成为Leader,到下一次竞选的时间
WAL 预写式日志 用户持久化存储的日志格式
Client 客户端 向etcd发起请求的客户端
ETCD 核心架构 遇见Golang|ETCD 的组件架构和内部通信
文章图片

  • etcd 是云原生架构中的存储基石,可以有效保证数据的一致性和可靠性。
  • etcd 内存实现机制复杂,但是对外提供了简单直接的api接口
  • 使用etcd的常见分布式场景包括键值对的存储,服务注册与发现,消息订阅与发布,分布式锁等等
ETCD 网关和gRPC-gateway ETCD网关:构建etcd集群的门户
  • etcd网关是一个简单的TCP代理,可将网络数据转发到etcd集群中
  • 网关是无状态且透明的,它既不会检查客户端请求,也不会干扰集群响应,支持多个etcd服务实例,并采用简单的循环策略。
如果同一服务器上的多应用程序访问的etcd集群,每个应用程序仍然需要知道etcd集群的广播客户端断点地址。
发生etcd集群实例的变更时,只需要网关更新其端点。
总而言之:为了自动传播集群端点更改,etcd网关在每台机器上都运行,为多个应用提供访问相同的etcd集群服务。
gRPC-Gateway:为非gRPC的客户端提供HTTP接口 HTTP的方式访问etcd服务端,需要考虑安全的问题,gRPC-Gateway中提供的API接口支持开启安全认证。
有的语言客户端不支持gRPC通信协议,此时就可以使用gRPC-Gateway对外提供HTTP API接口
,通过HTTP请求,实现与gRPC调用协议同样的功能。
gRPC-proxy 可伸缩的watch API 如果客户端监视同一键或某一范围内的键,gRPC代理可以将这些客户端程序(c-watcher)合并为链接到etcd服务器的单个监视程序(s-watcher)
当watch事件发生时,代理将所有事件(s-watcher)广播到其(c-watcher)
遇见Golang|ETCD 的组件架构和内部通信
文章图片

为了有效地将多个客户端监视程序合并为一个监视程序,gRPC代理在可能的情况下将新的c-watcher合并为现有地s-watcher。也有负载均衡的效果。
另外如果没有指定监视版本,gRPC代理将不能保证c-watcher从最近的存储修订版本开始监视。
可伸缩的lease API 如果etcd工作负载涉及很多的客户端租约活动,这些流可能会导致CPU使用率过高,为了减少核心集群上的流总数,gRPC代理支持将lease流合并。
遇见Golang|ETCD 的组件架构和内部通信
文章图片

可以缓存请求的响应,这个功能可以保护etcd服务器免遭恶意for循环中滥用客户端的攻击。
空间命名 当应用程序期望对整个空间有完全控制,etcd集群与其他应用程序共享的情况下,为了使所有应用程序都不会相互地干扰地运行,代理可以对etcd键空间进行分区,以便客户端大概率访问完整的键空间。
ETCD 组件架构
包名 用途
auth 访问权限
client/clientv3 Go语言客户端SDK
embed 主要是etcd的config
etcdmain 入口程序
etcdctl 命令行客户端实现
etcdserver server主要的包
functional/hack CMD、Dockerfile 之类的杂项
integration 和etcd集群相关
lease 租约相关
mvcc etcd的底层存储,包含Watch实现
pkg、proxy etcd使用的工具集合
raft raft算法模块
wal 日志模块
scripts/security/tests/tools/version 脚本、测试等相关内容
遇见Golang|ETCD 的组件架构和内部通信
文章图片

  • client 层:etcd 的客户端
  • API 接口层:提供了客户端访问服务端的通信协议和接口定义以及服务端节点之间相互通信的协议,通过gRPC-gateway提供REST ful 代理,转换HTTP/JSON请求为gRPC的Protocol Buffer格式的消息。
  • etcd Raft层:负责Leader选举和日志复制等功能。
  • 逻辑层:包括鉴权,租约,KVserver,MVCC和Compactor压缩等核心功能特点。
  • etcd存储:实现了快照,预写式日志WAL(Write Ahead Log)
ETCD的交互总览 遇见Golang|ETCD 的组件架构和内部通信
文章图片

  • etcd Server:接收客户端的请求,在上述的etcd项目代码中对应etcd server包。etcd server中的raft模块,用于与etcd-raft库进行通信。
  • etcd Raft :etcd的raft库,raft库更重要的式负责与集群中的其他etcd server进行交互,实现分布式一致性。
遇见Golang|ETCD 的组件架构和内部通信
文章图片

首先写数据到etcd节点中,然后当前的etcd节点与集群中的其他etcd节点之间进行通信,确认存储数据成功之后回复客户端。
在raft协议中写入数据的etcd必定式leader节点,如果客户端提交数据到非leader节点时,该节点需要将请求转发到etcd leader节点处理
遇见Golang|ETCD 的组件架构和内部通信
文章图片

etcd的gRPC通信接口 Client定义
type Client struct{ Cluster// 向集群里增加etcd服务端节点之类,属于管理员操作 KV // 我们主要使用的功能,即操作K-V Lease // 租约相关操作,比如申请一个TTL=10s的租约 Auth // 管理ETCD的用户和权限 属于管理员操作 Watcher // 观察订阅,从而监听最新的数据变化 Maintenance // 维护etcd,比如主动迁移etcd的leader节点,管理员操作 UserName string // 认证的用户名 Password string // 认证的密码 }

etcd的核心API
  • KV Service :创建、更新获取和删除键值对
  • Watch Service :监视键的更改
  • Lease Service : 实现键值对过期客户端用来续租保持心跳
  • Lock Service : etcd提供分布式共享锁支持
  • Election Service :暴露客户端选举机制
读写过程概述 读请求
客户端通过负载均衡选择一个etcd节点,发出读请求,API接口层提供Range RPC方法,etcd服务端拦截gRPC 读取请求后调用相应的处理器处理请求。
  1. etcdctl会创建一个clientv3库对象,选取一个合适的etcd节点
  2. 调用KV Server模块的Range RPC方法,发送请求
  3. 拦截器拦截,主要做一些校验和监控
  4. 调用KV Server模块的Range接口获取数据
线性读:线性读是相对串行读来讲的概念,集群模式下会有多个etcd节点,不同节点可能存在一致性问题,串行读直接返回状态数据,不需要与集群中其他节点交互,这种方式速度快,开销小,但是会存在数据不一致的情况。 线性读需要集群成员之间达成共识,存在开销,响应速度相对满,但是能保证数据的一致性. etcd默认读模式是线性读。
etcd中的查询请求,查询单个键或一组键以及查询数量,到底层实际会调用Range keys方法。
遇见Golang|ETCD 的组件架构和内部通信
文章图片

  1. 在treeIndex中根据BTree快速查询该键对应索引项keyIndex,索引项中包含Revision
  2. 据查询到的版本号信息Revision,在Backend的缓存Buffer中用二分查找,如命中则直接返回
  3. 若缓存中不符合条件,在BlotDB中查找(基于BlotDB的索引),查询后返回键值对信息
写请求
客户端通过负载均衡选择一个etcd节点发起写请求etcd服务器拦截gRPC写请求,涉及校验和监控后,KV Server 向 raft模块发提案,内容为写入数据命令,经网络转发,当集群中多数节点达成一致,持久化数据后,状态变成MVCC模块执行提案内容。
  1. 客户端通过负载均衡算法选择一个etcd节点,发起gRPC调用
  2. etcd server收到客户端请求
  3. 经过gRPC拦截,Quota校验,Quota模块用于校验etcd db文件大小是否超过配额。
  4. KV Server模块将请求发送给本模块中的raft,负责与etcd raft模块进行通信发起一个提案,命令为put,foo,bar,即使用put方法将foo更新为bar
  5. 提案经过转发之后,半数节点成功持久化
  6. MVCC模块更新状态机
【遇见Golang|ETCD 的组件架构和内部通信】遇见Golang|ETCD 的组件架构和内部通信
文章图片

    推荐阅读