1. etcd 项目结构和功能

etcd 项目代码的目录结构如下:

$ tree
├── auth
├── build
├── client
├── clientv3
├── contrib
├── embed
├── etcdctl
├── etcdmain
├── etcdserver
├── functional
├── hack
├── integration
├── lease
├── logos
├── mvcc
├── pkg
├── proxy
├── raft
├── scripts
├── security
├── tests
├── tools
├── vendor
├── version
└── wal

每个模块的功能如下:

etcd 核心的模块有 leasemvccraftetcdserver,其余都是辅助的功能。其中 etcdserver 是其他模块的整合。

2. etcd 整体架构

etcd 整体架构图如下:

2.1 客户端层

包括 clientv3etcdctl 等客户端。用户通过命令行或者客户端调用提供了 RESTful 风格的 API,降低了 etcd 的使用复杂度。

除此之外,客户端层的负载均衡(etcd V3.4 版本的客户端默认使用的是 Round-robin,即轮询调度)和节点间故障转移等特性,提升了 etcd 服务端的高可用性。需要注意的是,etcd V3.4 之前版本的客户端存在负载均衡的 Bug,如果第一个节点出现异常,访问服务端时也可能会出现异常,建议进行升级。

2.2 API 接口层

API 接口层提供了客户端访问服务端的通信协议和接口定义,以及服务端节点之间相互通信的协议。

etcdV3V2 两个版本。

  • etcd V3 使用 gRPC 作为消息传输协议;
  • etcd V2 默认使用 HTTP/1.x 协议。

对于不支持 gRPC 的客户端语言,etcd 提供 JSONgrpc-gateway 。通过 grpc-gateway 提供 RESTful代理,转换 HTTP/JSON 请求为 gRPCProtocol Buffer 格式的消息。

2.3 etcd Raft 层

负责 Leader 选举和日志复制等功能,除了与本节点的 etcd Server 通信之外,还与集群中的其他 etcd 节点进行交互,实现分布式一致性数据同步的关键工作。

2.4 逻辑层

etcd 的业务逻辑层,包括鉴权、租约、KVServerMVCCCompactor 压缩等核心功能特性。

2.5 etcd 存储

实现了快照、预写式日志 WALWrite Ahead Log)。etcd V3 版本中,使用 BoltDB 来持久化存储集群元数据和用户写入的数据。

3. 各个模块之间的交互

下图中展示了 etcd 处理一个客户端请求涉及的模块和流程。

从上至下依次为 客户端 → API 接口层 → etcd Serveretcd raft 算法库。我们根据请求处理的过程,将 etcd Serveretcd raft 算法库单独说明。

3.1 etcd Server

接收客户端的请求,在上述的 etcd 项目代码中对应 etcdserver 包。请求到达 etcd Server 之后,经过 KVServer 拦截,实现诸如日志、Metrics 监控、请求校验等功能。

etcd Server 中的 raft 模块,用于与 etcd-raft 库进行通信。

applierV3 模块封装了 etcd V3 版本的数据存储;WAL 用于写数据日志,WAL 中保存了任期号、投票信息、已提交索引、提案内容等,etcd 根据 WAL 中的内容在启动时恢复,以此实现集群的数据一致性。

3.2 etcdraft

etcdraft 库。raftLog 用于管理 raft 协议中单个节点的日志,都处于内存中。

raftLog 中还有两种结构体 unstablestorage,这两种结构体分别用于不同步骤的存储,区别如下

  • unsable 中存储不稳定的数据,表示还没有 commit
  • storage 中都是已经被 commit 了的数据;

除此之外,raft 库更重要的是负责与集群中的其他 etcd Server 进行交互,实现分布式一致性。

3.3 交互细节

在上图中,客户端请求与 etcd 集群交互包括如下两个步骤:

  • 首先是写数据到 etcd 节点中;

  • 其次是当前的 etcd 节点与集群中的其他 etcd 节点之间进行通信,确认存储数据成功之后回复客户端;

请求流程可划分为以下的子步骤:

  1. 客户端通过负载均衡算法选择一个 etcd 节点,发起 gRPC 调用;

  2. etcd Server 收到客户端请求;

  3. 经过 gRPC 拦截、Quota 校验,Quota 模块用于校验 etcd db 文件大小是否超过了配额;

  4. 接着 KVServer 模块将请求发送给本模块中的 raft,这里负责与 etcd raft 模块进行通信;

  5. 发起一个提案,命令为 put foo bar,即使用 put 方法将 foo 更新为 bar

  6. raft 中会将数据封装成 raft 日志的形式提交给 raft 模块;

  7. raft 模块会首先保存到 raftLogunstable 存储部分;

  8. raft 模块通过 raft 协议与集群中其他 etcd 节点进行交互。

需要注意的是,在 raft 协议中写入数据的 etcd 必定是 leader 节点,如果客户端提交数据到非 leader 节点时,该节点需要将请求转发到 etcd leader 节点处理。

响应流程的步骤如下:

  1. 提案通过 RaftHTTP 网络模块转发,集群中的其他节点接收到该提案;

  2. 在收到提案之后,集群中其他节点向 leader 节点应答“我已经接收这条日志数据”;

  3. Leader 收到应答之后,统计应答的数量,当满足超过集群半数以上节点,应答接收成功;

  4. etcd raft 算法模块构造 Ready 结构体,用来通知 etcd Server 模块,该日志数据已经被 commit

  5. etcd Server 中的 raft 模块(交互图中有标识),收到 Ready 消息后,会将这条日志数据写入到 WAL 模块中;

  6. 正式通知 etcd Server 该提案已经被 commit

  7. etcd Server 调用 applierV3 模块,将日志写入持久化存储中;

  8. etcd Server 应答客户端该数据写入成功;

  9. etcd Server 调用 etcd raft 库,将这条日志写入到 raftLog 模块中的 storage

上述过程中,提案经过网络转发,当多数 etcd 节点持久化日志数据成功并进行应答,提案的状态会变成已提交。

在应答某条日志数据是否已经 commit 时,为什么 etcd raft 模块首先写入到 WAL 模块中?

这是因为该过程仅仅添加一条日志,一方面开销小,速度会很快;另一方面,如果在后面 applierV3 写入失败,etcd 服务端在重启的时候也可以根据 WAL 模块中的日志数据进行恢复。etcd Serverraft 模块获取已提交的日志条目,由 applierV3 模块通过 MVCC 模块执行提案内容,更新状态机。

整个过程中,etcd raft 模块中的 raftLog 数据在内存中存储,在服务重启后失效;客户端请求的数据则被持久化保存到 WALapplierV3 中,不会在重启之后丢失。

参考:
https://kaiwu.lagou.com/course/courseInfo.htm?courseId=613#/detail/pc?id=6403

etcd 笔记(05)— etcd 代码结构、各模块功能、整体架构、各模块之间的交互、请求和应答流程相关推荐

  1. 福利模块功能实现及考勤模块准备

    为什么80%的码农都做不了架构师?>>>    今天完成了福利模块业务相关功能实现,福利模块主要实现功能有: 福利状态:确定员工缴纳状态和基数 福利计算:福利操作员计算公积金和社保 ...

  2. python笔记05: 程序结构

    程序结构 三大结构 顺序 分支 循环 分支 单路分支 分支的基本语法 if 条件表达式:语句1语句2语句3...... 条件表达式就是计算结果必须为布尔值的表达式 表达式后面的冒号不能少 注意if后面 ...

  3. python的requests模块功能_python中requests模块的使用方法

    本文实例讲述了python中requests模块的使用方法.分享给大家供大家参考.具体分析如下: 在HTTP相关处理中使用python是不必要的麻烦,这包括urllib2模块以巨大的复杂性代价获取综合 ...

  4. 《大型网站技术架构:核心原理与案例分析》笔记05

    <大型网站技术架构:核心原理与案例分析>笔记05 网站的课扩展性架构: 扩展性:指对现有系统影响最小的情况下,系统功能可持续扩展或提升的能力.表现在系统基础设施稳定不需要经常变更,应用之间 ...

  5. 肖然:DDD分层架构的代码结构实战

    不同于其它的架构方法,领域驱动设计DDD(Domain Driven Design)提出了从业务设计到代码实现一致性的要求,不再对分析模型和实现模型进行区分.也就是说从代码的结构中我们可以直接理解业务 ...

  6. 黑马程序员之ASP.NET学习笔记:Http状态代码及其含义

    -----------------------------------2345王牌技术员联盟.2345王牌技术员联盟.期待与您交流!---------------------------------- ...

  7. 系统架构设计模块拆分维度和原则

    在我们从零开始做一个新系统的时候,会首先进行系统功能模块架构设计,那么是直接做一个大而全的垂直的MVC系统,使用一个war包进行发布管理,还是需要按一些规则进行模块拆分,设计成SOA或者微服务系统比较 ...

  8. Python模块和包:导入制作模块、name、模块定位顺序(文件名与模块名重复、功能名与功能名重复、函数名与功能名重复、变量名与模块名重复)、from 模块名 import *__all__列表、包

    一.模块 Python 模块(Module),是⼀个 Python ⽂件,以 .py 结尾,包含了 Python 对象定义和Python语句. 模块能定义函数,类和变量,模块⾥也能包含可执⾏的代码. ...

  9. WiFi选型_主设备WiFi模块,从设备WiFi模块功能介绍

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.主设备WiFi模块 主设备WiFi模块功能介绍 二.从设备WiFi模块 从设备WiFi模块功能介绍 前言 在物联网 ...

最新文章

  1. esxi 6.7 7.0 区别_摩托车国产车和合资车有什么区别?
  2. javascript如何判断变量的数据类型
  3. android布局layout,Android布局(FrameLayout、GridLayout)
  4. Django框架(20.Django的视图函数的request参数以及QueryDict对象)
  5. python200行代码_如何用200行Python代码“换脸”
  6. html图片宽度高度等比例绽放,css图片自动绽放大小,左右,上下居中
  7. 数据结构 - 队列(非环形队列,以及优化成环形队列)
  8. java kcp,重新认识KCP - osc_rreaoxa0的个人空间 - OSCHINA - 中文开源技术交流社区
  9. 红橙Darren视频笔记 界面优化与屏幕适配(下)
  10. Unity,UDK,Unreal Engine4或者CryENGINE——我应该选择哪一个游戏引擎
  11. 环境配置:Qt5.5+VS2013+OpenCv3.1.0+Win7(64bit)
  12. (重磅)最快的Hadoop完全分布式运行
  13. 解决图片三像素的问题
  14. Qt之QSS(白色靓丽)
  15. 浏览器怎么置顶_Windows 10 窗口置顶 bug 解决方案汇总
  16. fatal: empty string is not a valid pathspec, please use . instead if you meant to match all paths
  17. OpenCV(0)---机器学习库
  18. Windows下如何正确清理C盘?
  19. 惠普服务器如何选择光驱启动不了系统,惠普笔记本bios设置光盘启动方法
  20. 应届生web前端面试题_前端开发应届生面试指南(含各大公司具体指南及面试真题)...

热门文章

  1. sql特殊字符转义,oracle中将字符 ‘ 转义
  2. 2022-2028年中国安防行业研究及前瞻分析报告
  3. 2022-2028年中国自动化设备市场研究及前瞻分析报告
  4. Git 常用操作(3)- 本地分之显示、创建、切换、合并和删除操作
  5. 【JavaScript总结】JavaScript语法基础:DOM
  6. RuntimeError: Assertion cur_target 0 cur_target n_classes failed
  7. 卷积神经网络(CNN)张量(图像)的尺寸和参数计算(深度学习)
  8. 全文翻译(四) TVM An Automated End-to-End Optimizing Compiler
  9. 国内操作系统OS分析(上)
  10. CVPR2020论文解读:CNN合成的图片鉴别