乐趣区

关于后端开发:OCTO-20美团基于Service-Mesh的服务治理系统详解

OCTO 是美团外部的服务治理平台,蕴含服务通信框架、命名服务、服务数据中心和用户治理平台等组件,为公司内全副服务提供了整套的服务治理计划和对立的服务治理体验。咱们在之前的几篇文章中别离从不同的角度介绍了 OCTO 平台的建设状况。包含:

  • 《美团命名服务的挑战与演进》介绍了美团命名服务(MNS)从 1.0 到 2.0 演进的初衷、实现计划以及落地的成果,并介绍了命名服务作为一个技术中台组件,对业务的重要价值以及推动业务降级的一些成绩。
  • 《美团 OCTO 万亿级数据中心计算引擎技术解析》介绍了美团自研的 OCTO 数据中心计算引擎的演进历程及架构设计,同时具体地介绍其全面晋升计算能力、吞吐能力、升高运维老本所采纳的各项技术计划。
  • 《团大规模微服务通信框架及治理体系 OCTO 外围组件开源》介绍了 OCTO 的外围组件 OCTO-RPC(JAVA 通信框架)、OCTO-NS(命名服务)和 OCTO-Portal(用户治理平台)的开源状况。
  • 《简单环境着落地 Service Mesh 的挑战与实际》从更高的视角介绍了美团以后的服务治理零碎的发展史、所面临的窘境和优化思路。对 Service Mesh 在美团大规模简单服务场景下的落地做了深刻的剖析。

本文将持续介绍 OCTO 零碎在 Service Mesh 化演进方面的工作。次要从数据面的角度,具体介绍各项技术计划的设计思路。

1 整体架构

咱们先看看 OCTO 2.0 的整体架构,如下图所示:

基础设施是指美团现有的服务治理零碎 OCTO1.0,包含 MNS、KMS(鉴权治理服务)、MCC(配置管理核心)、Rhino(熔断限流服务)等。这些零碎接入到 OCTO 2.0 的管制立体,防止过多重构引入的不必要老本。

OCTO 2.0 管制立体摒弃了社区的 Istio,齐全自研。数据立体基于开源 Envoy 革新。运维零碎负责数据面组件的降级、公布等运维工作。更多的整体选型及起因可参考之前团队的文章:《美团下一代服务治理零碎 OCTO2.0 的摸索与实际》。

对 OCTO 2.0 中的性能,咱们分为 Mesh 和服务治理两个维度,上面咱们来重点看下流量劫持、无损重启、服务路由等几个常见的问题,并论述美团是如何联合现有比较完善的服务治理零碎来解决这些问题的。

2 Mesh 性能

2.1 流量劫持

OCTO 2.0 并未采纳 Istio 的原生计划,而是应用 iptables 对进出 POD 的流量进行劫持。次要考量了以下两个因素:

  1. iptables 本身存在性能损失大、管控性差的问题:

    • iptables 在内核对于包的处理过程中定义了五个“hook point”,每个“hook point”各对应到一组规定链,outbond 流量将两次穿梭协定栈并且通过这 5 组规定链匹配,在大并发场景下会损失转发性能。
    • iptables 全局失效,不能显式地禁止相干规定的批改,没有相干 ACL 机制,可管控性比拟差。
  2. 在美团现有的环境下,应用 iptables 存在以下几个问题:

    • HULK 容器为富容器状态,业务过程和其余所有根底组件都处于同一容器中,这些组件应用了各种各样的端口,应用 iptables 容易造成误拦挡。
    • 美团当初存在物理机、虚拟机、容器等多个业务运行场景,基于 iptables 的流量劫持计划在适配这些场景时复杂度较高。

鉴于上述问题,咱们最终采纳了 Unix Domain Socket 直连形式来实现业务过程和 OCTO-Proxy 之间的流量转发。

在服务消费者一方,业务过程通过轻量的 Mesh SDK 和 OCTO-Proxy 所监听的 UDS 地址建设连贯。在服务提供者一方,OCTO-Proxy 代替业务过程监听在 TCP 端口上,业务过程则监听在指定的 UDS 地址上。

该计划的长处是 Unix Domain Socket 相比于 iptable 劫持领有更好的性能和更低的运维老本。毛病是须要 Mesh SDK 的反对。

2.2 服务订阅

原生 Envoy 的 CDS/EDS 申请是全量服务发现模式,行将零碎中所有的服务列表都申请到数据面中。因为大规模集群中服务数量太多,真正所需的只是多数服务,所以须要革新成按需服务发现模式,仅申请须要拜访的后端服务的节点列表。

在业务过程启动后,须要通过 HTTP 的形式向 OCTO-Proxy 发动订阅申请。OCTO-Proxy 将所申请的后端服务 Appkey 更新到 XDS 中,XDS 再向管制面申请特定的服务资源。

为了减少整个过程中的健壮性,升高后续运维老本,咱们做了局部适配。例如,OCTO-Proxy 的启动速度有可能慢于业务过程,所以在 Mesh SDK 中减少了申请的重试逻辑;将 Mesh SDK 和 OCTO-Proxy 之间的 http 申请革新成了同步申请,避免 Pilot 资源下发延时带来的问题;Mesh SDK 的订阅信息也会保留在本地文件中,以便 OCTO-Proxy 热重启或者故障重启时应用。

2.3 无损热重启

2.3.1 流量损失场景

如何在根底组件降级过程中提供继续、不间断的服务,做到业务流量无损及业务无感知,是所有根底组件面临的一大难题。这个问题对于 OCTO-Proxy 这种处于流量外围链路上的组件更加重要。社区原生的 Envoy 本身曾经反对了热重启性能但并不彻底,在某些场景下还是不能做到齐全的流量无损。

下图别离在短连贯和长连贯两种场景下来阐明 OCTO-Proxy 热重启时的流量损耗问题。

对于短连贯,所有新的连贯会在新的 OCTO-Proxy 上创立,旧 OCTO-Proxy 上已有的连贯在响应到来后被动断开。旧 OCTO-Proxy 的所有短连贯逐步断开,这就是“Drain”(排空)的过程。连贯排空之后,旧 OCTO-Proxy 被动退出,新的 OCTO-Proxy 持续工作。整个过程中的流量,齐全无损。

对于长连贯形式,SDK 和旧 OCTO-Proxy 维持一条长连接不断开,并继续应用该连贯发送申请。旧 OCTO-Proxy 过程最终退出时,该连贯被动断开,此时可能尚有局部响应未返回,导致 Client 端申请超时。因而,Envoy 的热重启对长连贯场景的反对并不完满。

为了反对根底组件在降级过程中提供不间断的服务,业界目前次要应用的是滚动公布(Rolling Update)的形式:服务器分批进行服务,执行更新,而后从新将其投入使用,直到集群中所有实例都更新为新版本。在此过程中会被动摘掉业务流量,保障降级过程中业务流量不失落。

美团外部因为要兼容物理机、虚拟机、容器,业界云原生应用 K8s 滚动降级的形式不太实用,所以在现有环境下,如何保障服务治理零碎的高可用性以及业务的高可靠性是一个十分辣手的事件。

2.3.2 适配计划

以后计划是把业务服务分为两种角色,即对外提供服务的 Server 端角色和对外发动申请的 Client 端角色,针对两种不同的角色采纳不同的热更新反对。

Client 端 OCTO-Proxy 热更新:老的 OCTO-Proxy 在进入热重启状态后,对后续“新申请”间接返回含“热重启”标记的响应协定,Client SDK 在收到含“热重启”标记的响应协定时,应被动切换新连贯并申请重试(以防止以后 Client SDK 持有的旧连贯因为旧 OCTO-Proxy 热重启流程实现后被被动敞开的问题)。这里须要留神,Client SDK 须要“妥善”解决旧连贯所在链路上遗留的所有“应答”协定。

通过这种 Client SDK 和 OCTO-Proxy 间的交互配合,能够反对 Client 端在 OCTO-Proxy 降级过程中保障流量的安全性。

Server 端 OCTO-Proxy 热更新:Server 侧 OCTO-Proxy 在热重启开始后,即会被动向 Client 侧 OCTO-Proxy 发送 ProxyRestart 音讯,告诉 Client 侧 OCTO-Proxy 被动切换新连贯,防止以后 Client 侧 OCTO-Proxy 持有的旧连贯因为 Server 侧旧 OCTO-Proxy 热重启流程实现后被强制敞开的问题。Client 端 OCTO-Proxy 在收到“被动切换新连贯”的申请后,应即时从可用连接池中移除,并“妥善”解决旧连贯所在链路上遗留的所有“应答”协定(激进起见可标记连贯不可用,并维持一段时间,比方 OCTO-Proxy 默认 drainTime)。

2.4 数据面运维

2.4.1 LEGO 运维计划

云原生环境中,Envoy 运行在规范的 K8S Pod 中,通常会独立出一个 Sidecar 容器。能够应用 K8s 提供的能力来实现对 Envoy Sidecar 容器的治理,例如容器注入、健康检查、滚动降级、资源限度等。

美团外部所应用的容器运行时模式为“单容器模式”,即一个 Pod 内只蕴含一个容器(不思考 Pause 容器)。因为业务过程以及所有的根底组件都运行在一个容器中,所以只能采纳过程粒度的治理措施,无奈做到容器粒度的治理。咱们通过自研的 LEGO 平台解决了 OCTO-Proxy 的运维问题。

咱们对 LEGO-Agent 做了定制化革新,减少了对 OCTO-Proxy 的热重启过程的反对。另外,LEGO-Agent 还负责对 OCTO-Proxy 的健康检查、故障状态重启、监控信息上报和版本公布等。绝对于原生 K8S 的容器重启形式,过程粒度重启会有更快的速度。

LEGO 零碎的另一个长处是,能够同时反对容器、虚拟机和物理机等多种运行时环境。

2.4.2 云原生运维计划

目前,咱们也正在摸索 OCTO-Proxy 云原生的运维计划,在此场景下最大的区别就是从过程粒度运维转变为了容器粒度运维,与业务利用做到了更好的解耦,同时可享受不可变基础设施等理念带来的红利,然而此场景带来的一个问题就是如何治理容器粒度的热重启。

为此,咱们通过自研的 Operator 对 OCTO-Proxy 容器进行全生命周期的运维治理,并且冀望通过 Operator 对 OCTO-Proxy 进行热重启,具体流程如下:

然而在施行过程中这个计划是有问题的,起因是 K8s 在底层设计上是不反对对运行中的 Pod 进行容器的增删操作,如果须要实现该计划,将须要对 K8s 底层组件进行定制化批改,这样将带来肯定危险以及与社区的不兼容性。为了保障与社区的兼容性,咱们对此热重启计划进行革新,最终应用双容器驻留热重启计划:

  1. 首先,咱们在启动 Pod 时,给 OCTO-Proxy 不再只调配一个容器,而是调配两个容器,其中一个容器为失常运行状态,另一个容器为 standby 状态。
  2. 当须要对 OCTO-Proxy 进行热重启降级时,咱们批改 standby 容器的镜像为最新 OCTO-Proxy 的镜像,此时开始热重启流程。
  3. 当热重启流程完结后,新容器进入失常工作状态,而旧容器进入期待状态,最终,咱们将旧容器的镜像批改为 standby 镜像,完结整个热重启流程。

该计划利用一开始就驻留双容器在 Pod 内,防止了 K8s 对运行中 Pod 不能增删容器的限度,实现了在 Pod 中对 OCTO-Proxy 进行容器粒度的热重启。

3 将来布局

目前接入 OCTO2.0 零碎的服务数量数千,天粒度流量数十亿。随着 OCTO2.0 在公司的一直推广,越来越多的服务开始接入,对咱们的稳定性和运维能力提出了更高的要求。如何更粗疏的理解线上 OCTO-Proxy 以及所称在的业务零碎的健康状况、如何在呈现故障时能更及时的监测到并疾速复原是咱们最近 OCTO2.0 零碎建设的重点。除此之外,将来 OCTO2.0 的布局重点还包含:

  • 运维、公布和稳定性建设朝云原生化方向摸索。
  • 反对公司外部 Http 服务的 Mesh 化,升高对中心化网关的依赖。
  • 全链路 mTLS 反对。

作者简介

舒超、世朋、来俊,均来自美团基础架构部根底开发组,从事 OCTO2.0 的开发工作。

团队简介

美团根底技术部 - 中间件研发核心 - 根底开发组,致力于研发公司级、业界当先的基础架构组件,研发范畴涵盖分布式框架、命名服务、Service Mesh 等技术畛域。欢送感兴趣的同学发送简历至:edp.itu.zhaopin@meituan.com。

浏览美团技术团队更多技术文章合集

前端 | 算法 | 后端 | 数据 | 平安 | 运维 | iOS | Android | 测试

退出移动版