如何实现OCTO2.0 的探索与实践

发布时间:2021-12-27 16:53:45 作者:柒染
来源:亿速云 阅读:126

这篇文章将为大家详细讲解有关如何实现OCTO2.0 的探索与实践,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

一、OCTO 现状分析

OCTO 是美团标准化的服务治理基础设施,治理能力统一、性能及易用性表现优异、治理能力生态丰富,已广泛应用于美团各事业线。关于 OCTO 的现状,可整体概括为:

目前美团已经具备了相对完善的治理体系,但仍有较多的痛点及挑战:

如何实现OCTO2.0 的探索与实践

针对以上痛点,我们考虑依托于 Service Mesh 解决。Service Mesh 模式下会为每个业务实例部署一个 Sidecar 代理,所有进出应用的业务流量统一由 Sidecar 承载,同时服务治理的工作也主要由 Sidecar 执行,而所有的 Sidecar 由统一的中心化控制大脑控制面来进行全局管控。这种模式如何解决上述四个问题的呢?

总结一下,在当前治理体系进行 Mesh 化改造可以进一步提升治理能力,美团也将 Mesh 化改造后的 OCTO 定义为下一代服务治理系统 OCTO2.0(内部名字是OCTO Mesh)。

二、技术选型及架构设计

2.1 OCTO Mesh 技术选型

美团的 Service Mesh 建设起步于2018年底,当时所面临一个核心问题是整体方案最关键的考量应该关注哪几个方面。在启动设计阶段时,我们有一个非常明确的意识:在大规模、同时治理能力丰富的前提下进行 Mesh 改造需要考虑的问题,与治理体系相对薄弱且期望依托于 Service Mesh 丰富治理能力的考量点,还是有非常大的差异的。总结下来,技术选型需要重点关注以下四个方面:

如何实现OCTO2.0 的探索与实践

针对上述考量,我们选择的方式是数据面基于 Envoy 二次开发,控制面自研为主。

数据面方面,当时 Envoy 有机会成为数据面的事实标准,同时 Filter 模式及 xDS 的设计对扩展比较友好,未来功能的丰富、性能优化也与标准关系较弱。
控制面自研为主的决策需要考量的内容就比较复杂了,总体而言需要考虑如下几个方面:

2.2 OCTO Mesh 架构设计

如何实现OCTO2.0 的探索与实践

上面这张图展示了 OCTO Mesh 的整体架构。从下至上来看,逻辑上分为业务进程及通信框架 SDK 层、数据平面层、控制平面层、治理体系协作的所有周边生态层。

先来重点介绍下业务进程及SDK层、数据平面层:

如何实现OCTO2.0 的探索与实践

控制面(美团内部名称为Adcore)自研为主,整体分为:Adcore Pilot、Adcore Dispatcher、集中式健康检查系统、节点管理模块、监控预警模块。此外独立建设了统一元数据管理及 Mesh 体系内的服务注册发现系统 Meta Server 模块。每个模块的具体职责如下:

三、关键设计解析

大规模治理体系 Mesh 化建设成功落地的关键点有:

围绕这四点,便可以在系统能力、治理能力、稳定性、运营效率方面支撑美团当前多倍体量的新架构落地。

3.1 大规模系统 Mesh 化系统能力建设

如何实现OCTO2.0 的探索与实践

对于社区 Istio 方案,要想实现超大规模应用集群落地,需要完成较多的技术改造。主要是因为 Istio 水平扩展能力相对薄弱,内部冗余操作较多,整体稳定性建设较为薄弱。针对上述问题,我们的解决思路如下:

如何实现OCTO2.0 的探索与实践

按需加载和数据分片主要由 Adcore Pilot 配合 Meta Server 实现。

Pilot 的逻辑架构分为 SessionMgr、Snapshot、Diplomat 三个部分,其中 SessionMgr 管理每个数据面会话的全生命周期、会话的创建、交互及销毁等一系列动作及流程;Snapshot 维护数据最新的一致性快照,对下将资源的更新同步给 SessionMgr 处理,对上响应各平台的数据变更通知,进行计算并将存在关联关系的一组数据做快照缓存。Diplomat 模块负责与服务治理系统的众多平台对接,只有该模块会与第三方平台直接产生依赖。
控制面每个 Pilot 节点并不会把整个注册中心及其他数据都加载进来,而是按需加载自己管控的 Sidecar 所需要的相关治理数据,即从 SessionMgr 请求的应用所负责的相关治理数据,以及该应用关注的对端服务注册信息。另外同一个应用的所有 OCTO Proxy 应该由同一个Pilot 实例管控,否则全局状态下又容易趋近于全量了。具体是怎么实现的呢?答案是 Meta Server,自己实现控制面机器服务发现的同时精细化控制路由规则,从而在应用层面实现了数据分片。

如何实现OCTO2.0 的探索与实践

Meta Server 管控每个Pilot节点负责应用 OCTO Proxy的归属关系。当 Pilot 实例启动会注册到 Meta Server,此后定时发送心跳进行续租,长时间心跳异常会自动剔除。在 Meta Server 内部实现了较为复杂的一致性哈希策略,会综合节点的应用、机房、负载等信息进行分组。当一个 Pilot 节点异常或发布时,隶属该 Pilot 的 OCTO Proxy 都会有规律的连接到接替节点,而不会全局随机连接对后端注册中心造成风暴。当异常或发布后的节点恢复后,划分出去的 OCTO Proxy 又会有规则的重新归属当前 Pilot 实例管理。对于关注节点特别多的应用 OCTO Proxy,也可以独立部署 Pilot,通过 Meta Server 统一进行路由管理。

如何实现OCTO2.0 的探索与实践

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 的负载。

如何实现OCTO2.0 的探索与实践

Snapshot 层除了减少不必要交互提升性能外,也会将计算后的数据格式化缓存下来,一方面瞬时大量相同的请求会在快照层被缓存挡住,另一方面也便于将存在关联的数据统一打包到一起,避免并发问题。这里参考了Envoy-Control-Plane的设计,Envoy-Control-Plane会将包含xDS的所有数据全部打包在一起,而我们是将数据隔离开,如路由、鉴权完全独立,当路由数据变更时不会去拉取并更新鉴权信息。

预加载主要目的是提升服务冷启动性能,Meta Server 的路由规则由我们制定,所以这里提前在 Pilot 节点中加载好最新的数据,当业务进程启动时,Proxy 就可以立即从 Snapshot 中获取到数据,避免了首次访问慢的问题。

如何实现OCTO2.0 的探索与实践

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 承担实时分片规则的元数据管理。

如何实现OCTO2.0 的探索与实践

具体执行机制如上图所示:各系统变更时使用客户端将变更通知推送到消息队列,只推送变更但不包含具体值(当Pilot接收到变更通知会主动Fetch全量数据,这种方式一方面确保Mafka的消息足够小,另一方面多个变更不需要在队列中保序解决版本冲突问题。);Adcore Dispatcher 消费信息并根据索引将变更推送到关注的 Pilot 机器,当 Pilot 管控的 Proxy 变更时会同步给 Meta Server,Meta Server 实时将索引关系更新并同步给Dispatcher。为了解决 Pilot 与应用的映射变更间隙出现消息丢失,Dispatcher 使用回溯检验变更丢失的模式进行补偿,以提升系统的可靠性。

3.3 稳定性保障设计

如何实现OCTO2.0 的探索与实践

Service Mesh 改造的系统避不开“新”和“复杂”两个特征,其中任意一个特征都可能会给系统带来稳定性风险,所以必须提前做好整个链路的可用性及可靠性建设,才能游刃有余的推广。美团主要是围绕控制故障影响范围、异常实时自愈、可实时回滚、柔性可用、提升自身可观测性及回归能力进行建设。

如何实现OCTO2.0 的探索与实践

这里单独介绍控制面的测试问题,这块业界可借鉴的内容不多。xDS 双向通信比较复杂,很难像传统接口那样进行功能测试,定制多个 Envoy 来模拟数据面进行测试成本也很高。我们开发了 Mock-Sidecar 来模拟真正数据面的行为来对控制面进行测试,对于控制面来说它跟数据面毫无区别。Mock-Sidecar 把数据面的整体行为拆分为一个个可组合的 Step,机制与策略分离。执行引擎就是所谓的机制,只需要按步骤执行 Step 即可。YAML 文件就是 Step 的组合,用于描述策略。我们人工构造各种 YAML 来模拟真正 Sidecar 的行为,对控制面进行回归验证,同时不同 YAML 文件执行是并行的,可以进行压力测试。

3.4 运维体系设计

如何实现OCTO2.0 的探索与实践

为了应对未来百万级 Proxy 的运维压力,美团独立建设了 OCTO Proxy 运维系统 LEGO,除 Proxy 保活外也统一集中控制发版。具体的操作流程是:运维人员在 LEGO 平台发版,确定发版的范围及版本,新版本资源内容上传至资源仓库,并更新规则及发版范围至 DB,发升级指令下发至所要发布的范围,收到发版命令机器的 LEGO Agent 去资源仓库拉取要更新的版本(中间如果有失败,会有主动 Poll 机制保证升级成功),新版本下载成功后,由 LEGO Agent 启动新版的 OCTO Proxy。

四、总结与展望

4.1 经验总结

4.2 未来展望

未来,我们会继续在 OCTO Mesh 道路上探索,包括但不限于以下几个方面:

关于如何实现OCTO2.0 的探索与实践就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

推荐阅读:
  1. 什么是css模块化?怎么实现css模块化?
  2. python实现PCA降维的示例详解

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

上一篇:基于Redis缓存怎么实现分布式锁

下一篇:java的单链表环操作有哪些

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》