<返回更多

带你去看美团架构

2020-06-01    
加入收藏

文章整理:加米谷大数据

一、MNS 1.0 简介

带你去看美团架构

 

图 1 MNS 1.0 架构

从架构上看,MNS 1.0 主要分为三层:首先是嵌入业务内部的 SDK,用作业务自定义调用;然后是驻守在每个机器上的 SgAgent,以代理的方式将一些易变的、消耗性能的计算逻辑与业务进程分离开来,从而降低 SDK 对业务的侵入,减少策略变动对业务的干扰;远端是集中式的组件,包括健康检查模块 Scanner,鉴权缓存模块 MNSC,以及基于 ZooKeeper(以下简称 ZK)打造的一致性组件 MNS-ZK,作为通知和存储模块。在层级之间设立多级缓存,利用“边缘计算”思想拆分逻辑,简化数据,尽量将路由分配等工作均摊到端上,从而降低中心组件负载。

更多详情大家可参考《美团大规模微服务通信框架及治理体系 OCTO 核心组件开源》一文中的 OCTO-NS 部分。

在体量方面,MNS 1.0 已经接入了美团所有的在线应用,涉及上万项服务、数十万个节点,并覆盖了美团所有的业务线,日均调用达万亿级别,目前我们已将其开源。

总的来讲,作为公司级核心服务治理组件,MNS 1.0 在架构上带有明显的 CP 属性,在保持架构简洁、流程清晰的同时,还支持了业务大量迭代的需求,较好地帮助公司业务实现了服务化、标准化的目标。

二、MNS 1.0 遇到的问题和挑战

带你去看美团架构

 

图 2 近三年美团业务增长数据

但是随着美团业务的快速增长,公司的服务数、节点数、服务信息量、服务变动频次等维度都在快速增长,有些服务甚至呈现出跨数量级的增长。在这样的情况下,命名服务也面临着一些新的问题和挑战:

  1. 可用性 :公司业务持续高速增长,很多都需要进行跨地域的部署。在 MNS 1.0 架构下,地域之间的专线如果断连,会发生一个地域命名服务整体不可用的情况;其次,强一致组件存在单点问题,Leader 出现故障,整个集群中断服务;另外,在多客户端和大数据传输的命名服务场景下,CP 系统恢复困难,RTO 达到小时级别。MNS 1.0 曾经出现过后端集中式组件单机连接超过十万且活跃链接数过半的情况,出现问题之后,现场恢复的负荷可想而知,这些都给命名系统的可用性带来很大的风险。
  2. 扩展性 :相对于需要支持的业务数量,MNS 1.0 整体平行扩展能力不足。MNS-ZK 的单集群规模上限不超过 300(实际只能达到 250 左右,这与 ZooKeeper 内部的 myid 等机制有关),否则同步性能会急剧恶化;其次,集群写入不可扩展,参与写入节点越多性能越差;另外,服务信息快照在固定的时间片内持续增长,增加 IO 压力的同时也延长了迁移的同步时间。而扩展性上的短板,导致 MNS 1.0 难以应对突发的流量洪峰,易出现“雪崩”。
  3. 性能 :写入操作受 CP 属性限制,串行性能较低。MNS-ZK 整体到 7000 左右的写量就已接近上限。其次,在热点服务场景下,数据分发较慢,这跟数据粒度较粗也有一定关系。而数据粒度粗、量大,也会在组件间传输消息时,导致临时对象频繁生成,引起 GC。另外,MNS 1.0 的后端集群负载还存在均衡性问题,一是因为原架构中缺乏集中管控服务,无法进行动态的集群与数据拆分伸缩,二是因为强一致属性下,集群节点间基于 Session 的迁移现场较重,很容易因一个节点挂掉而引起连锁反应。
带你去看美团架构

 

图 3 命名服务应该是 AP 系统

从可用性、扩展性、性能等三个方面,MNS 1.0 暴露出很多的问题,究其根源,原来的命名服务作为一个 CP 系统,为获得“数据一致性”而牺牲了部分情况下的可用性。其实,对于命名服务而言,一致性并没有这么重要,最多是调用方在一定时间内调多了或调漏了服务方而已,这个后果在不可靠网络的大前提下,即使命名服务没有出现问题,也可能经常会出现。借助端的自我检查调整机制,其影响可以说微乎其微。而另一方面,如果是一个机房或一个地域的调用方和服务方没有问题,但是因为这个区域和命名服务主集群断开了链接,从而导致本域内不能互调,这个就显得不太合理了。

所以总结一下,我们认为, 命名服务的本质是建立和增强服务本身的连通性,而不是主动去破坏连通性 。命名服务本质上应该是一个 AP 系统。

其实,业界对命名服务 AP/CP 模式都有相应实现和应用,很多企业使用 CP 模式,原因可能有以下几点:

  1. 架构行为简单 :CP 系统在出现分区时行为比较简单,冷冻处理,粗暴但相对不容易出错。
  2. 启动门槛低 :一些成熟的开源一致性组件,比如 ZK、etcd 都是 CP 系统,能够开箱即用,在数据规模可控的情况下,基本能够满足企业的需求。

另外,我们了解到,一些公司使用特殊的方式弱化了这个问题,比如将 CP 系统进一步拆分到更小的域中(比如一个 IDC),缩小分区的粒度,而全局有多个 CP 系统自治。当然,这个可能跟调用方服务方的跨度限制或者说调用配套部署有关系,但也有可能带来更复杂的问题(比如 CP 系统之间的数据同步),这里就不做详细的讨论了。

除去 MNS 1.0 本身的架构缺陷,我们还需要面临另一个问题,当初在项目启动时,云原生尚处于起步阶段,而如今,一些基于云原生理念兴起的网络基础设施,尤其是 Service Mesh 在美团快速发展,也需要 MNS 进行改造去适配新的流量通道和管控组件,这也是此次 MNS 2.0 演进的目标之一。

综上,我们以 AP 化、Mesh 化为主要目标,正式开始了从 MNS 1.0 向 MNS 2.0 的演进。

三、MNS 2.0

1. 整体架构

带你去看美团架构

 

图 4 MNS 2.0 整体架构

MNS 2.0 的整体架构自上而下主要分为四层:

  1. 业务系统层 :这一层与 MNS 1.0 架构类似,依然是嵌入到业务系统中的 SDK 或框架,但是不再感知服务列表和路由计算,从而变得更加的轻薄。
  2. 代理接入层 :这一层主要变化是加入了 Service Mesh 的 Sidecar 和 MNS-API。前者将命名服务的部分链路接入 Mesh;后者为 MNS 增加了更丰富的 HTTP 调用,帮助一些没有使用 SDK 或框架的业务快速接入到命名服务。整个代理接入层的改造使得 MNS 对接入业务更加亲和。
  3. 控制服务层 :新增注册中心控制服务,这也是 MNS 2.0 的核心。主要分为以下三个模块:a. 网关管控模块 :提供集中式的鉴权、限流 / 熔断、统计等 SOA 服务化的管控能力,同时避免海量代理组件直连存储层。b. 数据分发模块 :数据的通道,包括注册数据的上传、订阅数据的下发,可进行精细化数据拆分和平行扩展来适配热点服务。c. 变更捕获模块 :服务注册发现的审计,包括对第三方系统进行事件通知和回调,支持多元化的服务数据营运需求。另外,控制服务层还包括全链路 SLA 监控等新的子模块,以及健康检查 Scanner 这样的传统 MNS 组件。
  4. 数据存储层 :我们进一步丰富了命名服务的存储和分发介质,提高了数据层的整体性能。主力存储使用 K/V 存储系统(美团 Cellar 系统)替代 MNS-ZK,有效地提高了数据的吞吐能力,支持网络分区后的数据读写以及宕机灾备,同时保留 ZK 做一些轻量级的 Notify 功能。新增的关系型数据库和消息队列(美团 Mafka 系统),配合控制层的变更捕获模块,提供更方便的数据挖掘结构和外部扇出。
  5. 旁路于上面 4 层的是外部营运设施,主要是业务端的可视化 Portal,用户可以在上面对自身服务进行监控和操作,美团的基础研发部门也可以在上面进行一些集中式的管控。

综上所述,MNS 2.0 整体架构在兼容 1.0 的前提下,重点变化是: 新增了控制服务层并对底层存储介质进行拆解 。下面,我们来看一下服务注册发现功能在 MNS 2.0 中的实现流程:

带你去看美团架构

 

图 5 MNS 2.0 中的服务注册发现流程

  1. 服务注册 :代理接入层透传业务注册请求,经过控制服务层的管控模块(Gateway)一系列 SOA 和审计流程后,写入注册数据到存储层。
  2. 数据感知 :控制服务监听数据变动,服务注册写入新信息后,分发模块(Delivery)更新内存中的缓存,数据流经过捕获模块(CDC)将注册信息关系化后存储到 DB。
  3. 服务发现 :代理层请求经过控制服务的管控模块(Gateway)效验后,从分发模块(Delivery)的缓存中批量获取服务端注册信息。Cache Miss 场景时从存储层读取数据。
  4. 外部交互层 :外部系统当下通过代理层接入整个 MNS 体系,避免直连存储带来的各类风险问题。未来,营运平台可直接使用准实时 DB 数据,以 OLAP 方式进行关系化数据的分析。

接下来,我们一起来看下 MNS2.0 的主要演进成果。

2. 演进成果

2.1 流量洪峰 & 平行扩展

流量洪峰对于不同领域而言有不同的时段。对于 O2O 领域比如美团来说,就是每天中午的外卖高峰期,然后每天晚上也会有酒旅入住的高峰等等。当然,基于其它的业务场景,也会有不同的高峰来源。比如通过“借势营销”等运营手段,带来的高峰量可能会远超预期,进而对服务造成巨大的压力。

带你去看美团架构

 

图 6 流量洪峰

MNS 1.0 受制于 MNS-ZK 集群数量上限和强一致性的要求,无法做到快速、平行扩展。MNS 2.0 的数据存储层重心是保证数据安全读写和分布式协调,在扩展能力层面不应该对其有太多的要求。MNS 2.0 的平行扩展能力主要体现在控制服务层,其具体功能包括以下两个方面:

集群分片 :控制服务提供全量注册数据的 分片能力 ,解决命名服务单独进行大集群部署时不能进行业务线隔离的风险。MNS-Control 网关模块分为 Master 和 Shard 等两类角色,协作提供大集群分片能力。

带你去看美团架构

 

图 7 控制服务数据分片示意图

网络分区可用 :MNS 1.0 阶段,网络分区对可用性的影响巨大,分区后 MNS-ZK 直接拒绝服务。新架构将存储迁移到 KV 系统后,在网络专线抖动等极端情况下,各区域依然能正常提供数据读取功能。同时,我们与公司存储团队共建 C++ SDK 的地域就近读写功能。一方面,提高跨域服务注册发现的性能,另一方面,实现了网络分区后,各区域内命名服务可读、可写的目标,提高了系统的可用性,整个命名服务对网络的敏感度降低。

带你去看美团架构

 

图 8 命名服务的平行扩展

目前,控制服务层在平行扩缩容时间和集群原地恢复时间等方面,都达到了分钟级,集群也没有节点上限,从而能够有效应对突发的流量,防止服务出现“雪崩”。

2.2 推送风暴 & 性能提升

另一个典型的场景是推送“风暴”,在服务集中发布、出现网络抖动等情况下,会导致命名服务出现 " 一横一纵 " 两种类型的放大效应:横向是“关注放大”,类似于社交网络中某大 V 消息需要分发给众多的粉丝,服务越核心,放大的效果越明显。纵向是“级联放大”,命名服务的上下游会逐级进行拷贝发送,甚至一级上下游会针对一个消息有多次的交互(Notify+Pull)。

带你去看美团架构

 

图 9 命名服务领域的消息放大现象

“关注放大”和“级联放大”本身都是无法避免的,这是由系统属性决定,而我们能做的就是从两方面去平滑其带来的影响:

正面提升核心模块性能,增强吞吐、降低延迟

  1. 结构化聚合注册信息 :控制服务的数据分发模块,在内存中存储结构化的服务注册信息,提供批量数据的读取能力;降低多次网络 RTT 传输单个数据以及数据结构转化带来的高耗时。
  2. 高并发的吞吐能力 :控制服务通过无锁编程处理关键路径的竞争问题,借助应用侧协程机制,提供高并发、低延迟的数据分发功能。
  3. 与存储团队共建,实现 KV 系统就近区域读写,提高命名服务的服务注册(数据写入)性能。

另外,包括前面提到的控制服务集群的平行扩展能力,其实也是整体性能提升的一种方式。

侧面疏通,区分冷热数据,降低推送的数据量,提高效能

自然界中普遍存在“80/20 法则”,命名服务也不例外。服务注册信息的结构体中元素,80% 的改动主要是针对 20% 的成员,比较典型的就是服务状态。因此,我们将单个整块的服务信息结构体,拆分为多个较小的结构体分离存储;当数据变动发生时,按需分发对应的新结构体,能够降低推送的数据量,有效减少网络带宽的占用,避免代理组件重复计算引起的 CPU 开销,数据结构变小后,内存开销也得到显著降低。

那是否需要做到完全的“按需更新”,仅推送数据结构中变动的元素呢?我们认为,完全的“按需更新”需要非常精细的架构设计,并会引入额外的计算存储开销。比如,我们需要将变动成员分开存储以实现细粒度 Watcher,或用专门服务识别变动元素然后进行推送。

同时,还要保证不同成员变动时,每次都要推送成功,否则就会出现不一致等问题。在组件计算逻辑所需的数据发生变化时,也会带来更多的改动。在命名服务这样的大型分布式系统中,“复杂”、“易变”就意味着稳定性的下降和风险的上升。所以根据“80/20 法则”,我们进行尺度合理的冷热数据分离,这是在方案有效性和风险性上进行权衡后的结果。

带你去看美团架构

 

图 10 冷热数据分拆推送

经过改造,MNS 2.0 相比 MNS 1.0 的吞吐能力提升 8 倍以上,推送成功率从 96% 提升到 99%+,1K 大小服务列表服务发现的平均耗时,从 10s 降低到 1s,TP999 从 90s 下降到 10s,整体优化效果非常明显。

2.3 融入 Service Mesh

在 MNS 2.0 中,我们将代理服务 SgAgent 部分注册发现功能合并到了 Mesh 数据面,其流程如下图所示:

带你去看美团架构

 

图 11 命名服务与 Service Mesh 的融合

关于美团服务治理功能与 Service Mesh 结合的技术细节,这部分的内容,我们今年会单独做一个专题来进行分享,感兴趣的同学可以关注“美团技术团队”微信公众号,敬请期待。

2.4 无损迁移

除了上面说到的 MNS 2.0 的这些重点演进成果之外,我们还想谈一下整个命名服务的迁移过程。像 MNS 这样涉及多个组件、部署在公司几十万个机器节点上、支撑数万业务系统的大规模分布式系统,如何进行平滑的数据迁移而不中断业务正常服务,甚至不让业务感知到,是 MNS 2.0 设计的一个重点。围绕业务服务无感知、具备快速回滚能力、新 / 老体系互备数据不丢失等要求,我们设计了如下图所示的迁移流程:

带你去看美团架构

 

图 12 MNS 2.0 的无损迁移

MNS 2.0 整体以服务为粒度进行迁移操作,设置标志位说明服务所处的状态,由接入代理层组件识别该标志做出相应的处理。标志位包括:

  1. 未迁移标志 :服务注册 / 发现走 MNS 1.0 的流程,注册信息存储到重构前的 MNS-ZK 中。
  2. 迁移中标志 :服务注册并行走 MNS 1.0 和 MNS 2.0 流程,数据同时写入新旧两个地方,服务发现执行 MNS 2.0 流程。
  3. 已迁移标志 :服务注册 / 发现全部走 MNS 2.0 流程,注册信息仅存储到 MNS 2.0 的数据层。该阶段无法进行平滑的回滚,是项目长期验证后最终的迁移状态。

上述可以总结为 :聚焦单个服务,阶段性迁移服务发现流量,从而达到类似系统新功能发布时“灰度上线”的能力。当然,这个策略还涉及一些细节在其中,比如,分开存储在双写时需要重点去保证异常情况下的最终一致性等等,鉴于篇幅原因,这里就不详细展开讨论了,而且业界针对这种情况都有一些成熟的做法。

另外,我们通过优化命名服务发布系统的发版形式,实现自动化的流量灰度策略,降低了人力成本,同时构建了自动化的迁移工具、巡检工具,高效地进行自动化的数据迁移工作,能够快速巡检迁移后的链路风险,保障新 MNS 2.0 的稳定上线。

2.5 演进总结

在美团命名服务这样的大型分布式系统优化过程中,具体到架构和功能设计层面,我们也做了不少的权衡和取舍,前面我们也提到,放弃了增量式的精准变动信息推送方式。在考虑性能的前提下,也没有使用数据多维度营运能力更好的 MySQL 作为主要存取介质等等。取舍的核心原则是: 改造目标时强调业务收益,落地过程中减少业务感知 。

目前,MNS 2.0 主要成果如下:

四、命名服务对业务的赋能

命名服务本身作为基础的技术中台设施,在坚持“以客户为中心”,升级自身架构的同时,也从如下几个方面对美团的多个业务进行赋能。

4.1 单元化 & 泳道

单元化(SET 化)是业界比较流行的容灾扩展方案,关于美团单元化的详细内容,可参考 OCTO 团队在本次 ArchSummit 中的另一个专题分享《SET 化技术与美团点评实践解密》。这里主要是从命名服务对单元化支撑的角度去解答这个问题。

带你去看美团架构

 

图 13 命名服务对单元化的支持

如上图所示,业务多种来源的外网流量在通过网关进入内网后,会借助命名服务提供的能力(SDK/Agent),并按照业务自定义的核心数据维度和机器属性,给流量打上单元化标签,然后路由到标签匹配的下一跳,从而实现了单元间流量隔离。一个单元内部,从服务节点到各种存储组件,都依赖于命名服务提供的单元识别和路由能力来完成隔离,所以命名服务在单元化中主要起底层支撑的作用。

目前单元化在美团的重点业务,比如外卖、配送已经建设的比较完备,通过一定的单元冗余度,能在一个单元出现问题时,切换到另一个可用的镜像单元,显著提高了业务整体可用性。

接下来,我们再来看一下泳道场景。目前泳道在美团这边主要用于业务做完代码 UT 之后的线下集成测试阶段,同时结合容器,实现一个即插即用的上下游调用环境去验证逻辑。命名服务在其中起到的作用与单元化类似,根据泳道发布平台对机器的配置,自动编排上下游的调用关系。如下图所示:

带你去看美团架构

 

图 14 泳道流量示意图

当下一跳存在泳道节点时,测试流量进入泳道。反之,测试流量回流到主干。每个节点重复上述过程。

4.2 平滑发布 & 弹性伸缩

命名服务另外一个重要场景是服务的平滑发布,我们与发布平台配合,控制发布流量的自动摘除与恢复,实现服务发布操作的自动化与透明化。具体流程如下图所示:

带你去看美团架构

 

图 15 命名服务支持平滑发布

早期的发布流程,存在异常调用的风险,上线过程中存在一段服务实例不可用的“时间窗口”,此时流量再进入可能导致调用失败,然后会报错。为保证发布的稳定性,需要操作人员手动进行流量排空,流程上效率低、易出错,浪费业务团队的时间。针对这项业务痛点,命名服务向发布系统提供针对服务实例的流量管控能力,实现进程重启前自动摘除并清空来源请求,升级完毕后,提供自动流量恢复的平滑发布功能。智能地解决发版过程中的异常调用问题,提高公司的服务上线效率,降低了业务团队的运维成本。

弹性伸缩是容器一个很大的卖点。但是在伸缩过程中有很多问题需要考虑,比如扩缩容策略,包括调用亲和度配置,路由均衡等等。命名服务和容器化合作,提供业务的上下游调用关系、分组设置信息、容器下线流量无损摘除等服务,同时保障伸缩服务注册及时、高效。如下图所示:

带你去看美团架构

 

图 16 命名服务支持弹性伸缩

4.3 服务数据

MNS 服务数据对业务的赋能主要分为两个部分,一是将自身运行状态以业务可理解的 SLA 暴露出来,方便业务评估命名服务健康状况。对于命名服务来说,SLA 指标主要有 推送成功率和 推送耗时 两种(其实,推送耗时也可以看做成功率的一个衡量维度,这里暂时不做太详细的区分)。

MNS 1.0 精准量化运行状况的困难在于,一方面 MNS 的发布 / 订阅机制重度依赖 ZK,受限于 ZK 的自身实现和链路上众多不同组件的异构性,及时获取完整链路的推送行为数据很困难。另一方面,由于节点数众多,全量采集服务发现数据,对公司的监控上报系统以及采集之后的计算也是很大的负担。

在 MNS 2.0 中,我们首先在架构上显著弱化了 ZK 的地位,它基本上只作为一致性通知组件。我们自研的 MNS-Control 可以充分 diy 埋点场景,保证了主要推送行为抓取的可控性。其次,我们采用了分级采样计算,在全面梳理了公司现有的服务节点数比例后,将典型的服务列表数划分为几个档次,比如 1000 个节点的服务为一档,100 个又为一档,并创建相应的非业务哨兵服务,然后在不同机房选取适量的采样机器定期注册 + 拉取来评估整体的运行情况。这样既做到了上报量的精简,又兼顾了上报数据的有效性。详细操作流程,如下图所示:

带你去看美团架构

 

图 17 MNS 2.0 SLA 采集

命名服务存储的服务信息有很高的业务价值,从中可以知道服务的部署情况、发布频次以及上下游拓扑信息等等。所以“赋能”的第二个部分在于,借助这些信息,我们可以挖掘出业务服务部署运维上不合理的地方或风险点,不断推动优化,从来避免一些不必要的损失。目前已经在推动的项目包括:

在架构上,MNS 2.0 依赖 DB 和其它一些数仓介质,进行多种维度的数据上卷和下钻,并结合一些定制的风险策略逻辑去帮助业务发现和规避问题,目前这个事情也在进行中。

带你去看美团架构

 

图 18 MNS 2.0 数据赋能

五、未来展望

未来,美团命名服务主要会朝两个方向发展:

声明:本站部分内容来自互联网,如有版权侵犯或其他问题请与我们联系,我们将立即删除或处理。
▍相关推荐
更多资讯 >>>