etcd watch 机制源码解析——客户端篇

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

下图是本文讨论内容的目录树结构:

例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


提示:以下是本篇文章正文内容,下面案例可供参考

一、ETCD机制

1.1 etcd

etcd 是一个分布式 KV 存储组件,协议层通过 raft 算法保证了服务的强一致性和高可用性,同时,etcd 还提供了针对于存储数据的 watch 监听回调功能,基于这一特性,etcd 适合用于作为配置管理中心或者服务注册/发现模块.
示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。
etcd 官方文档

etcd 的开源地址为
在这里插入图片描述

1.2 watch 机制

在这里插入图片描述

所谓 watch 机制,指的是应用方可以针对存储在 etcd 中特定范围的数据创建 watch 监听器,在 watch 过程中,当对应数据发生变化时,etcd 会根据 watch 记录追溯到应用方,对变更事件进行同步.

建立在这样的机制之上,watch 机制主要能够胜任以下的几类应用场景

1.3 分布式锁

在这里插入图片描述
在分布式场景中,当不同的物理节点尝试对共同的临界资源进行并发保护,形成串行访问的秩序时,需要使用到分布式锁技术. 分布式锁的实现模式可以分为两大类:

  • 主动轮询型:类比于单机锁中的主动轮询 + cas 乐观锁模型,取锁方持续对分布式锁发出尝试获取动作,如果失败就发起重试,直到取锁成功;
  • watch 回调型:在取锁方经历一轮取锁而不得的尝试后,会 watch 订阅分布式锁的释放事件,随后不再发起主动取锁的尝试;直到分布式锁被释放后,取锁方感知到这一变化后,才会重新发起尝试取锁的动作.

在单机环境中,主动轮询和 watch 回调两种锁模型各有优劣,所谓的”优“和”劣“也是相对而言,需要对 cpu 空转以及阻塞协程两种行为的损耗做出权衡.

然而,在分布式场景中,我个人的理解是,watch 回调型的分布式锁是要优于主动轮询模型的. 这是因为分布式场景中”轮询“这一动作的成本相比于单机锁而言要高很多,背后存在的行为可能是一次甚至多次网络 IO 请求. 这种情况下,取锁方基于 watch 回调的方式,在确保锁被释放、自身有机会取锁的情况下,才会重新发出尝试取锁的请求,这样能在很大程度上避免无意义的轮询损耗.

当然,基于 watch 回调模型实现的分布式锁背后可能还存在其他的问题,比如:当有多个应用方同时 watch 同一把锁的释放事件,最终锁被释放时可能会引发“惊群效应”. 针对于分布式锁的实现策略本身也是一个有深度的话题,后续我会单开一个篇章进行讨论.

在这里,我真正想说的是,etcd 的 watch 机制,正是满足了 watch 回调类型分布式锁的实现条件. 我们把在 etcd 中添加一组 kv 对这一行为标志为”加锁成功“,则对于取锁而不得者,可以选择使用 etcd 的 watch 机制,创建一个 watch 监听对应 kv 数据的释放事件,直到被 watch 回调之后才再次尝试取锁. 这一流程正是 watch 回调型分布式锁的执行思路.

1.4 配置中心

在这里插入图片描述

watch 机制的另一类应用场景是分布式配置中心. 比如我在前文 “基于 etcd 实现 grpc 服务注册与发现” 当中聊到的,我们可以将 etcd 作为 grpc 服务的注册中心. 同一个 grpc 服务组在 etcd 中会以相同的服务名作为共同的标识键前缀,与各服务节点的信息建立好映射关系,以实现所谓的“服务注册”功能.

在客户端使用“服务发现”功能时,则会在 etcd 中通过服务名取得对应的服务节点列表缓存在本地,然后在客户端本地基于负载均衡策略选择 endpoint 进行连接请求. 在这个过程中,客户端还会利用到 etcd 的 watch 功能,在服务端节点发生变化时,及时感知到变更事件,然后对本地缓存的服务端节点列表进行更新,以保证客户端能够始终持有实时性较高的服务端地址信息.

在这里插入图片描述

二、客户端架构

2.1 探讨范围

在这里插入图片描述
首先,我们再次明确本文的讨论范围.

etcd 本身是客户端+服务端实现的 C-S 架构. 本文的讨论内容仅限于客户端部分,其中会涉及的内容点包括:

  • 应用方如何利用 etcd 客户端 sdk 与 etcd 服务端搭建通信架构
  • etcd 客户端如何将应用方创建 watch 的请求发往 etcd 服务端
  • 当 etcd 服务端传来 watch 回调事件时, etcd 客户端如何将事件准确推送到创建 watch 的应用方手中

关于更底层的部分,etcd 服务端是基于何种方式实现对数据变更的感知、如何与已有的 watch 建立关联以及如何寻找到归属的应用方身份,这些实现细节对于本文而言暂时只是个黑匣子, 具体内容在”etcd watch 机制——服务端篇“

2.2 C-S 长连接

在这里插入图片描述
首先,etcd 客户端和 etcd 服务端之间,是通过一条 grpc 长连接保持通信的. 这是因为两者之间的交互可能非常频繁,这条长连接双工管道,在客户端 -> 服务端的方向上,可能存在来自应用方多次发送的创建/删除 watch 的请求;在服务端 -> 客户端的方向上,可能持续发送因为因数据变更引起的 watch 回调事件. 由此可见,在双方请求如此频繁的情况下,使用 grpc 长连接是更加合适的方式. 倘若每笔请求都单独建立连接处理,这样引起的性能损耗无疑会高昂很多.

2.3 创建 watch 链路

在这里插入图片描述
当应用方首次尝试通过 etcd 客户端发起创建 watch 的请求时,首先会进行 etcd 客户端与 etcd 服务端间通信架构的初始化,在之后的请求中可以统一复用. 在这部分准备工作中,客户端侧会创建并异步运行 grpc 长连接代理对象 watcherGrpcStream;同时会启动协程 serveWatchClient,持续轮询处理来自 etcd 服务端的响应.

在创建 watch 的主链路中,etcd 客户端会创建好一个 channel(称之为 upch) 提前返回给应用方,后续 watch 监听的数据发生变更时,应用方可以通过这个 channel 接收到 watch 回调事件.

接下来,etcd 客户端会通过 watcherGrpcStream 将创建 watch 的请求通过 grpc 长连接推送到 etcd 服务端,并且 watcherGrpcStream 会针对每个 watch 异步启动一个 watchSubStream 进行对应 watch 下回调事件的监听和处理.

2.4 watch 回调链路

每当 watch 监听的数据发生变更后,etcd 服务端会通过 grpc 长连接将变更事件推送到 etcd 客户端.

etcd 客户端会通过常驻的 serveWatchClient 协程接收到 watch 回调事件,接下来 watcherGrpcStream 会根据回调事件所属的 watch 将其分配给对应的 watchSubStream,最终通过 endpointManager 的周转,并通过应用方持有的 upch,将回调事件推送到应用方的手中.


总结

提示:这里对文章进行总结:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值