导读:服务治理目前越来越被企业建设所器重,特地当初云原生,微服务等各种技术被更多的企业所利用,本文内容是百度小程序团队基于大模型服务治理实战经验的一些总结,同时联合以后较火的分布式开源 kv 产品 etcd,不仅会深刻分析 ectd 两大核心技术 Raft 与 boltdb 的实现原理,也会披露服务治理实在实际的教训,心愿帮忙大家在服务治理的路线上取得更多帮忙。
全文 8243 字,预计浏览工夫 21 分钟。
一、服务治理概念介绍
服务治理是 IT 治理的一部分,它关注服务生命周期中的相干因素,其重点环节包含服务注册和发现、服务平滑降级、流量监控、流量管控、故障定位、安全性等。
服务是须要 ” 治理 ” 的,然而治理是须要老本的,如果一个服务的业务逻辑简略,运行流程清晰,呈现问题也能及时定位和回滚,那么该服务治理的老本可能非常低,甚至只须要人工解决就行,然而在简单业务中,服务的提供者和服务的使用者可能别离运行在不同的过程中(甚至在不同的物理节点上),并由不同的团队开发和保护。团队合作和服务协同,都须要进行大量的协调工作。协调工作越多,复杂度越高,这样就有了服务治理的需要,通过建设对立的服务治理平台,就能够有无效的晋升业务的服务治理能力,包含协同的规范化、实时监控,一直优化调用链路的效率,以及辅助升高依赖复杂度,躲避危险等。在大型业务零碎中,服务治理曾经是技术架构中必不可缺的一部分,也是整个业务零碎最重要的基础设施之一。
上图是网上流传的 netflix 的服务拓扑图,图中稀稀拉拉的红色小点就是 netflix 的服务节点,节点之间的连线表明服务之间有调用,节点和连线形成了简单的服务调用链,如此宏大的利用零碎必须要通过一个强力的服务治理平台来进行治理。
服务治理实质上是对服务生命周期的管控,因此服务治理平台的外围需要就是如何解决服务生命周期中的痛点问题,其包含以下几个方面:
1、注册和发现
服务调用方在调用服务之前必须要失去服务提供方的地址,也就是调用方须要通过一种形式“发现“服务提供方,这就是服务发现。而要实现服务发现,就须要将服务提供方的信息存储到某个载体,这个存储的动作即是”服务注册“,而存储的载体则称为”服务注册核心“。在任何一个服务治理平台中,” 注册核心 ” 是必不可少的一个模块。服务注册和发现是服务治理中最根底的性能,在服务生命周期中,它负责服务的初始环节。
2、流量监控
在服务注册发现之后,就是服务的调用,大量的服务调用,造成了流量。流量监控就是对泛滥服务间的调用关系、状态的清晰掌控。其次要包含了调用拓扑关系、调用追踪、日志、监控告警等,服务治理通过调用拓扑来整体监控服务调用关系,通过建设监控体系来疾速发现、定位问题,从而在整体上感知业务零碎的运行状况。在服务生命周期中,流量监控负责服务的运行态感知。
3、流量调度
在业务零碎运行过程中,常常会有比方促销、秒杀、明星绯闻等热点问题,或者机房断网、断电、零碎大范畴降级等突发事件,带来业务零碎中部分服务的流量突增突降,这样就须要对服务的流量进行调度和治理。流量治理包含两个方面:从宏观的单个服务来说,就是服务调用过程的治理,包含在何时采纳何种平衡负载策略、路由策略以及熔断限流策略,这些策略统称为调用策略;从宏观上来说,就是流量散发的治理,能够依据某些流量特色和流量占比进行灰度公布、蓝绿公布等,这些称为流量散发策略。服务调用策略、流量散发策略,都须要通过流量监控收集的调用数据进行剖析,从而制订出决策,而后在服务治理平台上落地。流量调度负责服务的运行态治理。
4、服务管制
流量调度的策略如何在服务的提供方和调用方失效,能够重启失效,也能够在运行态实时失效,这就是看服务治理平台对服务的管制力度,服务治理平台在充沛建设服务治理能力后,能实时把服务治理的策略向服务进行散发并立刻失效。
5、服务平安
每个服务都承载本身的业务职责,一些业务敏感的服务,须要对其余服务的拜访进行认证与鉴权,也就是平安问题。
本文把领有成千上万的服务称之为大型利用零碎,该零碎的特色是大量的服务、大量的服务实例、以及海量的服务调用,服务治理平台在治理这类业务零碎的服务时,须要面对 以下微小的挑战:
1. 高可靠性
大型业务零碎,海量的服务调用,盘根错节的调用关系,对服务的可靠性要求很高,很多基层的服务都要求 99.99% 的可靠性,因此保护这些服务的服务治理平台,其可靠性的要求也十分高,而要达到这么高的可靠性,服务治理平台自身也须要做到多级部署、多地热备、降级隔离、平滑上线等计划。
2. 高性能
在保障可靠性的前提下,服务治理还必须有很高的性能,比方在监控数据中,疾速精确的感知到某个服务的呈现了单点故障,从而可能将流量散发到该服务的其余过程下来。如果业务零碎的服务数不多,调用量不高,那么监控数据量也不会很大,服务的单点故障很容易就能查到,然而在实时的海量调用数据中,一些惯例的查问伎俩要花费大量的工夫,等感知到单点故障时,可能曾经造成了不可挽回的业务损失。所以性能是考量服务治理平台治理能力的一项重要指标,如何保障高性能,高速的存储、多级缓存、线性部署都是必不可少的。
3. 高扩大
高扩大蕴含两个方面:大型利用零碎的服务,可能是由多个团队在开发运维,其程度和技术能力也是参差不齐的,因此服务治理平台须要提供兼容和扩大的能力,通过扩展性,尽可能的把不同的服务治理起来;同时,在业务零碎服务量增长时,服务治理平台也应该具备同步扩大的能力,来保障其高牢靠和高性能。
面对海量服务的治理挑战,服务治理平台也须要有一个弱小好用的存储工具来应答,etcd 就是一个不错的抉择。
二、etcd 介绍
2.1 etcd 倒退背景与相干竞品介绍
2013 年 CoreOS 守业团队在构建一款开源,轻量级的操作系统 ContainerLinux 时,为了应答用户服务多正本之间协调的问题,自研开发的一款用于配置共享和服务发现的高可用 KV 分布式存储组件——ETCD。
上面咱们也针对 Zookeeper 和 Consul 两个选型做了一下比照:
· ZooKeeper
ZooKeeper 从高可用性,数据一致性,性能这三个方面而言是完全符合需要的,但 CoreOS 还是保持自研 etcd 的起因总结有以下两点:
1. ZooKeeper 不反对通过 API 平安地变更成员,须要人工批改节点配置并重启过程. 如果操作有误,有可能导致脑裂等线上故障,同时 CoreOS 对适配云环境,集群规模的平滑调整,运行时配置的在线变更都是有冀望指标的,这方面 ZooKeeper 的保护老本比拟高。
- 高负载读写性能,ZooKeeper 在大规模的实例连贯状况下性能体现并不佳。
etcd 名字是由“/etc”文件夹和”d”分布式系统组成。“/etc”文件夹是用来存储单系统配置数据的,而“etcd”用于存储大规模分布式系统的配置数据,etcd 集群可提供高稳定性,高可靠性,高伸缩性和高性能的分布式 KV 存储服务。etcd 是基于复制状态机实现的,由 Raft 一致性模块,日志模块,基于 boltdb 长久化存储的状态机组成,可利用于分布式系统的配置管理,服务发现,分布式一致性等等。
ZooKeeper 与 etcd 一样,可解决分布式系统一致性和元数据存储等问题,然而 etcd 相较于 ZooKeeper 有以下几点劣势:
1. 动静集群成员关系重新配置
2. 高负载下稳固的读写能力
3. 多版本并发控制数据模型
4. 牢靠的键监控
5. Lease(租约)原语将连贯和会话拆散
6. 分布式锁保障 API 安全性
7. ZooKeeper 应用本人的 RPC 协定,应用受限;而 etcd 客户端协定是基于 gRPC 的,可反对多种语言。
· Consul
Consul 与 etcd 解决的是不同的问题,etcd 用于分布式一致性 KV 存储,而 Consul 侧重于端到端的服务发现,它提供了内置的健康检查,失败检测和 DNS 服务等等,另外 Consul 通过 RESTfulHTTPAPIs 提供 KV 存储能力. 然而当 KV 使用量达到百万级时,会呈现高提早和内存压力等问题。
一致性算法方面,etcd、Consul 基于 Raft 算法实现数据复制,ZooKeeper 则是基于 Zab 算法实现。Raft 算法由 Leader 选举,日志同步,安全性组成,而 Zab 协定则由 Leader 选举、发现、同步、播送组成。
分布式 CAP 方面,etcd、Consul 和 ZooKeeper 都是 CP 零碎,产生网络分区时,无奈写入新数据。
下表是针对三者的要害能力做了一下比照剖析:
2.2 etcd 核心技术介绍
基于 Raft 协定实现数据高可用和强一致性
晚期数据存储服务引入多正本复制技术计划来解决单点问题,然而无论是主从复制还是去中性化复制,都存在肯定的缺点。主从复制运维艰难,且一致性与可用性难以兼顾;去中心化复制,存在各种写入抵触问题须要业务解决。而分布式一致性算法,正是解决多正本复制存在问题的要害。分布式一致性算法,又称为共识算法,最早是基于复制状态机背景下提出来的。Paxos 作为第一个共识算法,过于简单,不容易了解,难以在工程上落地。斯坦福大学的 Diego 提出的 Raft 算法,通过将问题拆解为三个子问题,易于了解,升高了工程落地难度。这三个子问题是:Leader 选举,日志复制,安全性。
Leader 选举
etcd(版本 3.4+)中 Raft 协定定义集群节点有 4 种状态:Leader、Follower、Candidate、PreCandidate。
失常状况下,Leader 节点会依照心跳间隔时间,定时播送心跳音讯给 Follower 节点,以维持 Leader 身份。Follower 收到后回复心跳应答包音讯给 Leader。Leader 都会带有一个任期号(term),任期示意从一次选举开始,博得选举的节点在该任期内担当 Leader。任期号枯燥递增,在 Raft 算法中充当逻辑时钟,用于比拟各个节点数据新旧,辨认过期 Leader 等等。
当 Leader 节点异样时,Follower 节点会接管 Leader 的心跳音讯超时,当超时工夫大于竞选超时工夫后,会进入 PreCandidate 状态,不自增任期号,仅发动预投票(民意调查,避免因为节点数据远远落后于其余节点而发动有效选举),取得大多数节点认可后,进入 Candidate 状态. 进入 Candidate 状态的节点,会期待一个随机工夫,而后发动选举流程,自增任期号,投票给本人,并向其余节点发送竞选投票信息。
当节点 B 收到节点 A 竞选音讯后,有 2 种状况:
1. 节点 B 判断节点 A 的数据至多和本人一样新,节点 A 任期号大于节点 B 任期号,并且节点 B 未投票给其余候选者,即可投票给节点 A,节点 A 取得集群大多数节点反对,可成为新 Leader。
2. 如果节点 B 也发动了选举,并投票给本人,那么它将回绝投票给节点 A。此时若没有节点能够失去大多数投票反对,则只能期待竞选超时,开启新一轮选举。
日志复制
Raft 日志构造如下图所示:
Raft 日志由有序索引的一个个条目组成,每个日志条目蕴含了任期号和提案内容.Leader 通过保护两个字段来追踪各个 Follower 的进度信息. 一个是 NextIndex,示意 Leader 发送给该 Follower 节点的下一个日志条目索引; 另一个是 MatchIndex,示意该 Follower 节点已复制的最大日志条目索引。
本文以 Client 提交“hello=world”提案,至接管到响应的整个流程为例,简略介绍 etcd 日志复制流程:
1. 当 Leader 接管到 Client 提交的提案信息后,生成日志条目,同时遍历各个 Follower 的日志进度,生成对各个 Follower 追加日志的 RPC 音讯;
2. 通过网络模块将追加日志的 RPC 音讯播送给各个 Follower;
3. Follower 接管到追加日志音讯并长久化之后,回复 Leader 已复制最大日志条目索引,即 MatchIndex;
4. Leader 接管到 Follower 应答后,更新对应 Follower 的 MatchIndex;
5. Leader 依据各个 Follower 提交的 MatchIndex 信息,计算出日志条目已提交索引地位,该地位代表日志条目被一半以上节点长久化;
6. Leader 通过心跳告知各个 Follower 已提交日志索引地位;
7. 当 Client 的提案,被标识为已提交后,Leader 回复 Client 该提案通过。
通过以上流程,Leader 同步日志条目给各个 Follower,保障 etcd 集群的数据一致性。
安全性
etcd 通过给选举和日志复制减少了一系列规定,来保障 Raft 算法的安全性。
选举规定:
1. 一个任期号,只能有一个 Leader 被选举,Leader 选举须要集群一半以上节点反对;
2. 节点收到选举投票时,如果候选者最新日志条目标任期号小于本人,回绝投票,任期号雷同然而日志比本人短,同样回绝投票。
日志复制规定:
1. Leader 齐全个性,如果某个日志条目在某个任期号中已被提交,则这个日志条目必然呈现在更大任期号的所有 Leader 中;
2. 只附加准则,Leader 只能追加日志条目,不能删除已长久化的日志条目;
3. 日志匹配个性,Leader 发送日志追加信息时,会带上前一个日志条目标索引地位 (用 P 示意) 和任期号,Follower 接管到 Leader 的日志追加信息后,会校验索引地位 P 的任期号与 Leader 是否统一,统一能力追加。
boltdb 存储技术
ectd 的另一个核心技术是 boltdb 存储,提供高效的 b + 树的检索能力,同时反对事务操作,他是撑持 etcd 高性能读写的要害能力之一。
boltdb 的实现参见了 LMDB(LightningMemory-MappedDatabase)设计思路,基于高效疾速的内存映射数据库计划. 基于 B + 树的结构设计。数据文件设计上 bolt 应用一个独自的内存映射的文件,实现一个写入时拷贝的 B + 树,这能让读取更快。而且,BoltDB 的载入工夫很快,特地是在从 crash 复原的时候,因为它不须要去通过读 log(其实它压根也没有)去找到上次胜利的事务,它仅仅从两个 B + 树的根节点读取 ID。
文件存储设计
因为采纳了单文件映射存储,所以 bolt 对文件按指定长度进行分块解决,每块存储不同的内容类型。默认应用 4096 字节的长度进行分块。每一块的结尾有独自的 pageid(int64)标识。
文件块的类型有以下几种:
数据文件全景构造
阐明:
- metapage 固定在 page0 与 page1 地位
- Pagesize 大小固定在 4096 字节
- bolt 的文件写入采纳了本地序(小端序)的模式,比方 16 进制 0x0827(2087)写入的内容为 2708000000000000
单文件计划的劣势就是不须要做文件的合并删除等操作,只须要在原文件上追加扩大长度就能够了。
查问设计
boltdb 提供了十分高效的查问能力,能够先看一下它的对象设计:
从对象设计上,boltdb 在加载时,会先 loadmeta 数据进内存,而后依据 bucket,来定位数据块所在的地位,而后再依据 key 的值,来定位 branchnode 的地位,而后定位到叶子值节点。
咱们以查问为例,来解说一下,上面是一个根本的查问示例代码:
tx, err := db.Begin(true) // 开启事务
if err != nil {return}
b := tx.Bucket([]byte("MyBucket")) // 依据名称查问 bucket
v := b.Get([]byte("answer20")) // 依据 key 进行查问
fmt.Println(string(v))
tx.Commit()
对应下面的代码,上面的序列图,能够更具体的理解一次查问的操作流程:
下面最要害的代码就是 search 办法,上面是次要的代码片断,已增加了正文阐明不便浏览。
func (c *Cursor) search(key []byte, pgid pgid) {p, n := c.bucket.pageNode(pgid)
if p != nil && (p.flags&(branchPageFlag|leafPageFlag)) == 0 {panic(fmt.Sprintf("invalid page type: %d: %x", p.id, p.flags))
}
// 把以后查问节点 (page,node) 压入栈
e := elemRef{page: p, node: n}
c.stack = append(c.stack, e)
// If we're on a leaf page/node then find the specific node.
if e.isLeaf() {c.nsearch(key)
return
}
// if node cached seach by node's inodes field
if n != nil {c.searchNode(key, n)
return
}
// recursively to load branch page and call search child node again
c.searchPage(key, p)
}
三、百度基于 etcd 打造大规模服务治理建设思路
3.1 具体的挑战
天路是百度小程序团队开发打造的面向大型业务服务治理需要的一套解决方案,其指标之一就是打造成百度的服务治理标准样板。天路由注册核心、可视化治理平台、SDK 框架、对立网关、tianlu-mesher 五个局部组成,目前曾经接入了 150+ 产品线,实例数已达数十万级别。随着接入平台的团队数增多、以及服务实例的快速增长,大量团队间如何轻松的合作以及实现大规模服务治理平台的高可用、高性能始终是天路继续面临的挑战。
3.2 整体架构建设思路与计划
天路作为一个服务治理平台,核心理念是为所有的服务提供便捷的调用,对立的服务监控治理,简化服务的开发和保护老本。咱们从以下不同的方面思考基于 etcd 打造大规模服务治理平台:高可用、高性能、高扩大、易用性。
· 高可用
- 思考到 etcd 跨机房调用的高网络延时,咱们采纳单机房部署,同时咱们也实现了主备集群切换的计划,解决在单机房实例全副宕机的状况下,etcd 集群不可用的问题。
- 为了升高平台对 etcd 的强依赖,咱们做了 etcd 降级应用缓存的计划。在监控到 etcd 集群的性能无奈反对以后平台的时候,应用缓存存储实例数据,可能让运维人员在复原 etcd 之前,零碎不受影响失常运行;etcd 复原之后,切换回 etcd 集群持续工作。
· 高性能
- etcd 集群的 kv 查问性能很高,qps 能达到 10000 以上。为了解决在极其并发下的性能问题,注册核心采纳多级缓存晋升查问效率,升高对 etcd 的拜访压力。
- 服务间调用应用直连的形式,申请不须要通过注册核心进行转发,调用根本没有工夫损耗。
· 高扩大
- 思考到未来服务实例数达到百万级别,咱们须要思考架构的高扩展性。
· 易用性
- 用户通过可视化的治理平台能够查看已注册的服务,也可通过治理平台实时更新服务治理策略的配置,实时调整服务治理策略。
- 将调用日志接入 trace 平台,用户可通过 traceId 在 trace 平台查到整个调用链的记录,便于出错时进行疾速的问题定位。
- 多语言 SDK,反对多种 rpc 技术,包含百度自研的 rpc 技术 brpc(https://github.com/baidu/Jpro…【java/go sdk】)和 http jsonrpc 协定等
架构计划图
3.3 要害的指标与运维指标
此外针对更好的施行服务治理平台的运维,还须要以下的要害考核指标与运维要求。
要害指标:
· 可用性达 99.99 以上;
· 平响 100ms 以下。
运维指标:
-
故障发现早
· 配置监控告警,包含注册核心实例衰弱、etcd 平响、内存和 cpu 监控。
-
故障解决快
· 主动解决:通过 noah 的回调机制,主动解决一些故障,进步处理速度。
· 手动解决:值班机制。
四、总结
服务治理目前越来越被企业建设所器重,特地当初云原生,微服务等各种技术被更多的企业所利用,然而要真正在利用好,交融好,还是有十分多的挑战,除了一套成熟的服务治理产品外,包含团队整体对服务治理的认知,技术教训的深淀,遵循服务化的设计能力程度的能力等,都会影响到最终的施行成果。本文也仅在服务治理产品选型上给大家一些启发,心愿在服务治理的路线上帮大家走得更好更稳。
举荐浏览:
|百度爱番番数据分析体系的架构与实际
|托管页前端异样监控与治理实战
|Flux 架构思维在度咔 App 中的实际
———- END ———-
百度 Geek 说
百度官网技术公众号上线啦!
技术干货 · 行业资讯 · 线上沙龙 · 行业大会
招聘信息 · 内推信息 · 技术书籍 · 百度周边
欢送各位同学关注