美团下一代服务治理系统 OCTO2.0 的探索与实践
总第375篇
2019年 第53篇
本文根据美团基础架构部服务治理团队工程师郭继东在2019 QCon(全球软件开发大会)上的演讲内容整理而成,主要阐述美团大规模治理体系结合 Service Mesh 演进的探索实践,希望对从事此领域的同学有所帮助。
一、OCTO 现状分析
OCTO 是美团标准化的服务治理基础设施,治理能力统一、性能及易用性表现优异、治理能力生态丰富,已广泛应用于美团各事业线。关于 OCTO 的现状,可整体概括为:
- 已成为美团高度统一的服务治理技术栈,覆盖了公司90%的应用,日均调用超万亿次。
- 经历过大规模的技术考验,覆盖数万个服务/数十万个节点。
- 协同周边治理生态提供的治理能力较为丰富,包含但不限于 SET 化、链路级复杂路由、全链路压测、鉴权加密、限流熔断等治理能力。
- 一套系统支撑着多元业务,覆盖公司所有事业线。
目前美团已经具备了相对完善的治理体系,但仍有较多的痛点及挑战:
- 对多语言支持不够好。美团技术栈使用的语言主要是 Java,占比到达80%以上,上面介绍的诸多治理能力也集中在 Java 体系。但美团同时还有其他近10种后台服务语言在使用,这些语言的治理生态均十分薄弱,同时在多元业务的模式下必然会有增长的多语言需求,为每一种语言都建设一套完善的治理体系成本很高,也不太可能落地。
- 中间件和业务绑定在一起,制约着彼此迭代。一般来说,核心的治理能力主要由通信框架承载,虽然做到了逻辑隔离,但中间件的逻辑不可避免会和业务在物理上耦合在一起。这种模式下,中间件引入Bug需要所有业务配合升级,这对业务的研发效率也会造成损害;新特性的发布也依赖业务逐个升级,不具备自主的控制能力。
- 异构治理体系技术融合成本很高。
- 治理决策比较分散。每个节点只能根据自己的状态进行决策,无法与其他节点协同仲裁。
针对以上痛点,我们考虑依托于 Service Mesh 解决。Service Mesh 模式下会为每个业务实例部署一个 Sidecar 代理,所有进出应用的业务流量统一由 Sidecar 承载,同时服务治理的工作也主要由 Sidecar 执行,而所有的 Sidecar 由统一的中心化控制大脑控制面来进行全局管控。这种模式如何解决上述四个问题的呢?
- Service Mesh 模式下,各语言的通信框架一般仅负责编解码,而编解码的逻辑往往是不变的。核心的治理功能(如路由、限流等)主要由 Sidecar 代理和控制大脑协同完成,从而实现一套治理体系,所有语言通用。
- 中间件易变的逻辑尽量下沉到 Sidecar 和控制大脑中,后续升级中间件基本不需要业务配合。SDK 主要包含很轻薄且不易变的逻辑,从而实现了业务和中间件的解耦。
- 新融入的异构技术体系可以通过轻薄的 SDK 接入美团治理体系(技术体系难兼容,本质是它们各自有独立的运行规范,在 Service Mesh 模式下运行规范核心内容就是控制面和Sidecar),目前美团线上也有这样的案例。
- 控制大脑集中掌控了所有节点的信息,进而可以做一些全局最优的决策,比如服务预热、根据负载动态调整路由等能力。
总结一下,在当前治理体系进行 Mesh 化改造可以进一步提升治理能力,美团也将 Mesh 化改造后的 OCTO 定义为下一代服务治理系统 OCTO2.0(内部名字是OCTO Mesh)。
二、技术选型及架构设计
2.1 OCTO Mesh 技术选型
美团的 Service Mesh 建设起步于2018年底,当时所面临一个核心问题是整体方案最关键的考量应该关注哪几个方面。在启动设计阶段时,我们有一个非常明确的意识:在大规模、同时治理能力丰富的前提下进行 Mesh 改造需要考虑的问题,与治理体系相对薄弱且期望依托于 Service Mesh 丰富治理能力的考量点,还是有非常大的差异的。总结下来,技术选型需要重点关注以下四个方面:
- OCTO 体系已经历近5年的迭代,形成了一系列的标准与规范,进行 Service Mesh 改造治理体系架构的升级范围会很大,在确保技术方案可以落地的同时,也要屏蔽技术升级或只需要业务做很低成本的改动。
- 治理能力不能减弱,在保证对齐的基础上逐渐提供更精细化、更易用的运营能力。
- 能应对超大规模的挑战,技术方案务必能确保支撑当前量级甚至当前N倍的增量,系统自身也不能成为整个治理体系的瓶颈。
- 尽量与社区保持亲和,一定程度上与社区协同演进。
针对上述考量,我们选择的方式是数据面基于 Envoy 二次开发,控制面自研为主。
数据面方面,当时 Envoy 有机会成为数据面的事实标准,同时 Filter 模式及 xDS 的设计对扩展比较友好,未来功能的丰富、性能优化也与标准关系较弱。
控制面自研为主的决策需要考量的内容就比较复杂了,总体而言需要考虑如下几个方面:
- 截止发稿前,美团容器化主要采用富容器的模式,这种模式下强行与 Istio 及 Kubernetes 的数据模型匹配改造成本极高,同时 Istio API也尚未确定。
- 截止发稿前,Istio 在集群规模变大时较容易出现性能问题,无法支撑美团数万应用、数十万节点的的体量,同时数十万节点规模的 Kubernetes 集群也需要持续优化探索。
- Istio 的功能无法满足 OCTO 复杂精细的治理需求,如流量录制回放压测、更复杂的路由策略等。
- 项目启动时非容器应用占比较高,技术方案需要兼容存量非容器应用。
2.2 OCTO Mesh 架构设计
上面这张图展示了 OCTO Mesh 的整体架构。从下至上来看,逻辑上分为业务进程及通信框架 SDK 层、数据平面层、控制平面层、治理体系协作的所有周边生态层。
先来重点介绍下业务进程及SDK层、数据平面层:
- OCTO Proxy (数据面Sidecar代理内部叫OCTO Proxy)与业务进程采用1对1的方式部署。
- OCTO Proxy 与业务进程采用 UNIX Domain Socket 做进程间通信(这里没有选择使用 Istio 默认的 iptables 流量劫持,主要考虑美团内部基本是使用的统一化私有协议通信,富容器模式没有用 Kubernetes 的命名服务模型,iptables 管理起来会很复杂,而 iptables 复杂后性能会出现较高的损耗。);OCTO Proxy 间跨节点采用 TCP 通信,采用和进程间同样的协议,保证了客户端和服务端具备独立升级的能力。
- 为了提升效率同时减少人为错误,我们独立建设了 OCTO Proxy 管理系统,部署在每个实例上的 LEGO Agent 负责 OCTO Proxy 的保活和热升级,类似于 Istio 的 Pilot Agent,这种方式可以将人工干预降到较低,提升运维效率。
- 数据面与控制面通过双向流式通信。路由部分交互方式是增强语义的 xDS,增强语义是因为当前的 xDS 无法满足美团更复杂的路由需求;除路由外,该通道承载着众多的治理功能的指令及配置下发,我们设计了一系列的自定义协议。
控制面(美团内部名称为Adcore)自研为主,整体分为:Adcore Pilot、Adcore Dispatcher、集中式健康检查系统、节点管理模块、监控预警模块。此外独立建设了统一元数据管理及 Mesh 体系内的服务注册发现系统 Meta Server 模块。每个模块的具体职责如下:
- Adcore Pilot 是个独立集群,模块承载着大部分核心治理功能的管控,相当于整个系统的大脑,也是直接与数据面交互的模块。
- Adcore Dispatcher 也是独立集群,该模块是供治理体系协作的众多子系统便捷接入 Mesh 体系的接入中心。
- 不同于 Envoy 的 P2P 节点健康检查模式,OCTO Mesh 体系使用的是集中式健康检查。
- 控制面节点管理系统负责采集每个节点的运行时信息,并根据节点的状态做全局性的最优治理的决策和执行。
- 监控预警系统是保障 Mesh 自身稳定性而建设的模块,实现了自身的可观测性,当出现故障时能快速定位,同时也会对整个系统做实时巡检。
- 与Istio 基于 Kubernetes 来做寻址和元数据管理不同,OCTO Mesh 由独立的 Meta Server 负责 Mesh 自身众多元信息的管理和命名服务。
三、关键设计解析
大规模治理体系 Mesh 化建设成功落地的关键点有:
- 系统水平扩展能力方面,可以支撑数万应用/百万级节点的治理。
- 功能扩展性方面,可以支持各类异构治理子系统融合打通。
- 能应对 Mesh 化改造后链路复杂的可用性、可靠性要求。
- 具备成熟完善的 Mesh 运维体系。
围绕这四点,便可以在系统能力、治理能力、稳定性、运营效率方面支撑美团当前多倍体量的新架构落地。
3.1 大规模系统 Mesh 化系统能力建设
对于社区 Istio 方案,要想实现超大规模应用集群落地,需要完成较多的技术改造。主要是因为 Istio 水平扩展能力相对薄弱,内部冗余操作较多,整体稳定性建设较为薄弱。针对上述问题,我们的解决思路如下:
- 控制面每个节点并不承载所有治理数据,系统整体做水平扩展,在此基础上提升每个实例的整体吞吐量和性能。
- 当出现机房断网等异常情况时,可以应对瞬时流量骤增的能力。
- 只做必要的 P2P 模式健康检查,配合集中式健康检查进行百万级节点管理。
按需加载和数据分片主要由 Adcore Pilot 配合 Meta Server 实现。
Pilot 的逻辑架构分为 SessionMgr、Snapshot、Diplomat 三个部分,其中 SessionMgr 管理每个数据面会话的全生命周期、会话的创建、交互及销毁等一系列动作及流程;Snapshot 维护数据最新的一致性快照,对下将资源的更新同步给 SessionMgr 处理,对上响应各平台的数据变更通知,进行计算并将存在关联关系的一组数据做快照缓存。Diplomat 模块负责与服务治理系统的众多平台对接,只有该模块会与第三方平台直接产生依赖。
控制面每个 Pilot 节点并不会把整个注册中心及其他数据都加载进来,而是按需加载自己管控的 Sidecar 所需要的相关治理数据,即从 SessionMgr 请求的应用所负责的相关治理数据,以及该应用关注的对端服务注册信息。另外同一个应用的所有 OCTO Proxy 应该由同一个Pilot 实例管控,否则全局状态下又容易趋近于全量了。具体是怎么实现的呢?答案是 Meta Server,自己实现控制面机器服务发现的同时精细化控制路由规则,从而在应用层面实现了数据分片。
Meta Server 管控每个Pilot节点负责应用 OCTO Proxy的归属关系。当 Pilot 实例启动会注册到 Meta Server,此后定时发送心跳进行续租,长时间心跳异常会自动剔除。在 Meta Server 内部实现了较为复杂的一致性哈希策略,会综合节点的应用、机房、负载等信息进行分组。当一个 Pilot 节点异常或发布时,隶属该 Pilot 的 OCTO Proxy 都会有规律的连接到接替节点,而不会全局随机连接对后端注册中心造成风暴。当异常或发布后的节点恢复后,划分出去的 OCTO Proxy 又会有规则的重新归属当前 Pilot 实例管理。对于关注节点特别多的应用 OCTO Proxy,也可以独立部署 Pilot,通过 Meta Server 统一进行路由管理。
Mesh体系的命名服务需要 Pilot 与注册中心打通,常规的实现方式如左图所示(以 Zookeeper为例),每个 OCTO Proxy 与 Pilot 建立会话时,作为客户端角色会向注册中心订阅自身所关注的服务端变更监听器,假设这个服务需要访问100个应用,则至少需要注册100个 Watcher 。假设该应用存在1000个实例同时运行,就会注册 100*1000 = 100000 个 Watcher,超过1000个节点的应用在美团内部还是蛮多的。另外还有很多应用关注的对端节点相同,会造成大量的冗余监听。当规模较大后,网络抖动或业务集中发布时,很容易引发风暴效应把控制面和后端的注册中心打挂。
针对这个问题,我们采用分层订阅的方案解决。每个 OCTO Proxy 的会话并不直接与注册中心或其他的发布订阅系统交互,变更的通知全部由 Snapshot 快照层管理。Snapshot 内部又划分为3层,Data Cache 层对接并缓存注册中心及其他系统的原始数据,粒度是应用;Node Snapshot 层则是保留经过计算的节点粒度的数据;Ability Manager 层内部会做索引和映射的管理,当注册中心存在节点状态变更时,会通过索引将变更推送给关注变更的 OCTO Proxy。
对于刚刚提到的场景,隔离一层后1000个节点仅需注册100个 Watcher,一个 Watcher 变更后仅会有一条变更信息到 Data Cache 层,再根据索引向1000个 OCTO Proxy 通知,从而极大的降低了注册中心及 Pilot 的负载。
Snapshot 层除了减少不必要交互提升性能外,也会将计算后的数据格式化缓存下来,一方面瞬时大量相同的请求会在快照层被缓存挡住,另一方面也便于将存在关联的数据统一打包到一起,避免并发问题。这里参考了Envoy-Control-Plane的设计,Envoy-Control-Plane会将包含xDS的所有数据全部打包在一起,而我们是将数据隔离开,如路由、鉴权完全独立,当路由数据变更时不会去拉取并更新鉴权信息。
预加载主要目的是提升服务冷启动性能,Meta Server 的路由规则由我们制定,所以这里提前在 Pilot 节点中加载好最新的数据,当业务进程启动时,Proxy 就可以立即从 Snapshot 中获取到数据,避免了首次访问慢的问题。
Istio 默认每个 Envoy 代理对整个集群中所有其余 Envoy 进行 P2P 健康检测,当集群有N个节点时,一个检测周期内(往往不会很长)就需要做N的平方次检测,另外当集群规模变大时所有节点的负载就会相应提高,这都将成为扩展部署的极大障碍。
不同于全集群扫描,美团采用了集中式的健康检查方式,同时配合必要的P2P检测。具体实现方式是:由中心服务 Scanner 监测所有节点的状态,当 Scanner 主动检测到节点异常或 Pilot 感知连接变化通知 Scanner 扫描确认节点异常时, Pilot 立刻通过 eDS 更新节点状态给 Proxy,这种模式下检测周期内仅需要检测 N 次。Google 的Traffic Director 也采用了类似的设计,但大规模使用需要一些技巧:第一个是为了避免机房自治的影响而选择了同机房检测方式,第二个是为了减少中心检测机器因自己 GC 或网络异常造成误判,而采用了Double Check 的机制。
此外除了集中健康检查,还会对频繁失败的对端进行心跳探测,根据探测结果进行降权或摘除操作提升成功率。
3.2 异构治理系统融合设计
OCTO Mesh 需要对齐当前体系的核心治理能力,这就不可避免的将 Mesh 与治理生态的所有周边子系统打通。Istio 和 Kubernetes 将所有的数据存储、发布订阅机制都依赖 Etcd 统一实现,但美团的10余个治理子系统功能各异、存储各异、发布订阅模式各异,呈现出明显的异构特征,如果接入一个功能就需要平台进行存储或其他大规模改造,这样是完全不可行的。一个思路是由一个模块来解耦治理子系统与 Pilot ,这个模块承载所有的变更并将这个变更下发给 Pilot,但这种方式也有一些问题需要考虑,之前介绍每个 Pilot 节点关注的数据并不同,而且分片的规则也可能时刻变化,有一套机制能将消息发送给关注的Pilot节点。
总体而言需要实现三个子目标:打通所有系统,治理能力对齐;快速应对未来新系统的接入;变更发送给关注节点。我们解法是:独立的统一接入中心,屏蔽所有异构系统的存储、发布订阅机制;Meta Server 承担实时分片规则的元数据管理。
具体执行机制如上图所示:各系统变更时使用客户端将变更通知推送到消息队列,只推送变更但不包含具体值(当Pilot接收到变更通知会主动Fetch全量数据,这种方式一方面确保Mafka的消息足够小,另一方面多个变更不需要在队列中保序解决版本冲突问题。);Adcore Dispatcher 消费信息并根据索引将变更推送到关注的 Pilot 机器,当 Pilot 管控的 Proxy 变更时会同步给 Meta Server,Meta Server 实时将索引关系更新并同步给Dispatcher。为了解决 Pilot 与应用的映射变更间隙出现消息丢失,Dispatcher 使用回溯检验变更丢失的模式进行补偿,以提升系统的可靠性。
3.3 稳定性保障设计
Service Mesh 改造的系统避不开“新”和“复杂”两个特征,其中任意一个特征都可能会给系统带来稳定性风险,所以必须提前做好整个链路的可用性及可靠性建设,才能游刃有余的推广。美团主要是围绕控制故障影响范围、异常实时自愈、可实时回滚、柔性可用、提升自身可观测性及回归能力进行建设。
这里单独介绍控制面的测试问题,这块业界可借鉴的内容不多。xDS 双向通信比较复杂,很难像传统接口那样进行功能测试,定制多个 Envoy 来模拟数据面进行测试成本也很高。我们开发了 Mock-Sidecar 来模拟真正数据面的行为来对控制面进行测试,对于控制面来说它跟数据面毫无区别。Mock-Sidecar 把数据面的整体行为拆分为一个个可组合的 Step,机制与策略分离。执行引擎就是所谓的机制,只需要按步骤执行 Step 即可。YAML 文件就是 Step 的组合,用于描述策略。我们人工构造各种 YAML 来模拟真正 Sidecar 的行为,对控制面进行回归验证,同时不同 YAML 文件执行是并行的,可以进行压力测试。
3.4 运维体系设计
为了应对未来百万级 Proxy 的运维压力,美团独立建设了 OCTO Proxy 运维系统 LEGO,除 Proxy 保活外也统一集中控制发版。具体的操作流程是:运维人员在 LEGO 平台发版,确定发版的范围及版本,新版本资源内容上传至资源仓库,并更新规则及发版范围至 DB,发升级指令下发至所要发布的范围,收到发版命令机器的 LEGO Agent 去资源仓库拉取要更新的版本(中间如果有失败,会有主动 Poll 机制保证升级成功),新版本下载成功后,由 LEGO Agent 启动新版的 OCTO Proxy。
四、总结与展望
4.1 经验总结
- 服务治理建设应该围绕体系标准化、易用性、高性能三个方面开展。
- 大规模治理体系 Mesh 化应该关注以下内容:
- 适配公司技术体系比新潮技术更重要,重点关注容器化 & 治理体系兼容打通。
- 建设系统化的稳定性保障体系及运维体系。
- OCTO Mesh 控制面4大法宝:Meta Server 管控 Mesh 内部服务注册发现及元数据、分层分片设计、统一接入中心解耦并打通 Mesh 与现有治理子系统、集中式健康检查。
4.2 未来展望
未来,我们会继续在 OCTO Mesh 道路上探索,包括但不限于以下几个方面:
- 完善体系:逐渐丰富的 OCTO Mesh 治理体系,探索其他流量类型,全面提升服务治理效率。
- 大规模落地:持续打造健壮的 OCTO Mesh 治理体系,稳步推动在公司的大规模落地。
- 中心化治理能力探索:新治理模式的中心化管控下,全局最优治理能力探索。
作者简介
继东,基础架构部服务治理团队工程师。
欢迎加入美团基础架构技术交流群,跟作者零距离交流。如想进群,请加美美同学的微信(微信号:MTDPtech03),回复:OCTO,美美会自动拉你进群。
下一章:从ReentrantLock的实现看AQS的原理及应用
总第374篇 2019年 第52篇 AQS作为JUC中构建锁或者其他同步组件的基础框架,应用范围十分广泛,这篇文章会带着大家从可重入锁一点点揭开AQS的神秘面纱。 前言 Java中 ...