服务网格(Service Mesh)的概念自 2017 年初提出之后,受到了业界的广泛关注,作为微服务的下一代发展架构在社区迅速发酵,并且孵化出了诸如 Istio 等广受业界关注的面向于云原生 (Cloud Native) 的微服务架构。那么,服务网格在百度的落地情况又如何呢?本文整理自百度服务网格技术负责人乔元才在百度技术沙龙上的主题演讲《服务网格在百度核心业务大规模落地实践》。 从微服务到服务网格
何谓微服务?据维基百科的定义:微服务是一种软件架构风格,它是以专注于单一责任与功能的小型功能区块为基础,利用模块化的方式组合出复杂的大型应用程序,各功能区块使用与语言无关的 API 集相互通信。
Service Mesh 最早在 2016 年 9 月 29 日由开发 Linkerd 的 Buoyant 公司首次提出,Service Mesh 是用于处理服务间通信的基础设施层,它负责通过构成现代云原生应用程序的复杂拓扑结构来可靠地传递请求。
因此 Service Mesh 也被称为微服务时代的 TCP 协议。
第一代微服务的常见架构如下图所示:
在黄色的容器内有服务 A、服务 B。A 和 B 都包含自己的业务逻辑,如果想要 A 调用 B,同时试图对这个服务进行治理,通常会在业务的内部集成一个 SDK,来实现服务发现、负载均衡、服务路由、重试、熔断限流等功能。
但是,这个架构存在三个主要问题:
第一,开发成本。因为 A 和 B 的服务已经是微服务了,它们可能是由不同语言开发的而且各自的框架可能也不同,如果希望把绿色的部分进行升级或者提供新的功能,就需要重复的迭代和开发。
第二,升级成本。因为 SDK 的部分跟业务耦合在一起,在新增一些能力时需要重新部署业务的模块。
第三,部署成本。由于相关治理的功能需要耦合在业务的配置里面,所以很难做到实时的下发配置,服务间拓扑关系和治理配置无法统一管理。
Service Mesh 是如何解决这些问题的?
如下图左侧所示,它通过将 SDK 、开发框架提供的服务治理能力下沉到一个和业务进程独立的轻量级网络代理中,由这个网络代理作为微服务通信的基础设施层,它可以提供业务无关、语言无关、独立演进,透明升级的特性。这个轻量级的网络进程被称作 Sidecar 代理,是服务网格的数据面。
同时如右侧所示,通过一个对 Sidecar 进行统一控制和管理的服务控制平面,来提供对微服务治理和运维的统一入口。
这种架构实现了服务治理技术和业务逻辑的解耦,是云原生时代微服务治理技术的发展方向,也得到了越来越多的公司的关注。
百度微服务治理的现状和痛点百度在服务网格以及微服务相关的探索大概可以追溯到 2013 年,当时在内部独立部署了流量转发系统,同时在一些业务有所推广实施;2016 年 Service Mesh 这个概念被首次提出,因为百度本身有相关需求,便尝试引入 Mesh 的概念,于是内部自研了一套遵循社区 Mesh 概念的通过 Golang 开发的包含控制面和数据面的 BMesh 系统,在搜索服务前端服务上线,不过没有在特别多业务推广;直到 2019 年,百度内部做了拥抱开源的决定,希望基于社区方案:Istio + Envoy 进行深度定制开发。
目前,百度核心业务线已全面完成了微服务架构改造,基于微服务构建了包括百度信息流、百度 App、百度地图、百度小程序等核心业务的应用架构;微服务模块大量采用 C++、Golang、PHP、Java 等语言来开发和快速迭代;而且百度长期积淀了许多自研和二次开发的开源微服务框架:bRPC、GDP、ODP、SpringCloud 等, 这些微服务间通信除了标准的 HTTP、GRPC 协议外,广泛地采用了大量的私有协议,比如 baidu-std、Nshead 等。
所以百度的核心业务线形成了多开发语言、多开发框架和多通信协议构成的复杂的异构系统,传统的基于入侵的微服务框架已经不能满足这种复杂系统的服务治理要求——升级 Mesh 迫在眉睫!
在升级之前,有一些重点问题需要综合考虑:
改造成本
各种各样的微服务框架网格化改造和适配
各种各样的通信协议支持
性能问题和资源问题
因为 Sidecar 的引入,微服务间的通信链路变长,业务延迟增加,甚至某些敏感业务无法接受 Sidecar 带来的额外损耗。
Sidecar 自身会消耗资源,增加业务的成本。
规模问题
随着 Sidecar 规模的增长,开源的控制平面计算开销变大,导致 Mesh 配置下发时间变长,甚至无法工作。
百度服务网格整体方案如何解决这些问题?
在服务网格的技术选型问题上,百度选择了开源的 Istio + Envoy 作为网格控制面和数据面,在其上进行深度的定制和开发。
但是 Istio + Envoy 的社区方案和 K8S 的技术生态进行了深度绑定。而在百度内部有自研的基础技术平台,包括对标 K8S 的 PaaS 部署系统、Trace 系统、监控系统和 Naming 系统等,这些都是业务模块包括 Istio + Envoy 部署运行的依赖系统。所以,将 Istio + Envoy 和内部依赖系统进行了深度的技术融合,打通了公司基础技术平台,降低了业务接入成本。
在数据面和控制面之上,又建设了 Mesh 控制中心,即微服务的配置管理中心,提供服务治理和运维的统一入口;基于底层架构的建设,向上提供了流量复制、负载均衡、过载保护、流量镜像等系统能力。
这些系统能力在核心业务的服务治理、运维止损、容量管理、混沌工程和服务可观测等场景中得到了应用,并且取得了不错的业务收益和使用效果。
那么,实现这样一套系统,我们需要解决哪些问题呢?
网格接入优化方案首先是流量劫持方案的问题,在社区方案中,一般是通过 Naming Service(如:DNS 服务)获取到目标 Server 的真实地址。同时,通过配置 iptables 进行流量劫持,将客户端的请求直接转发给 Sidecar。但是,当 iptables 配置有大量匹配规则时有性能的问题,而且无法动态修改客户端访问服务端的行为,如:重试、超时等,且没有办法平滑的在 Mesh 和非 Mesh 模式切换。
在百度内部采用了另外一种劫持的方案,首先 Sidecar 启动的时候会将自己注册给 Naming Service(在百度内部叫 BNS),在框架经过 Naming Service 查询的时候,框架的内部集成了一个和 Naming Service 对接的小模块,这个小模块从 Naming Service 拿到的就是 Sidecar 的地址,动态的改变了目标服务器的地址,直接将目标的 IP 变成 Sidecar 的地址(loopbackIp),同时,还会覆盖客户端的重试、超时等参数,这一切对业务来说都是无感的。
这样就可以很便捷的调整客户端服务治理参数、切换 Mesh 和非 Mesh 模式。因为如果 Sidecar 挂掉了,会在 Naming 系统里把自己解除注册,这样上游的框架会自然而然的访问下游服务的真实地址了。
第二,对自有协议的支持的问题。在社区里面是支持不同的协议,比如 HTTP、Thrift、Dubbo,但会涉及重复的开发。如果要支持一个新协议,可能需要重新实现超时控制、重试、请求路由、流量镜像等。百度内部将这通用的部分单独剥离出来:于是支持一个新的协议变得简单起来,我们只需要将下图中绿色的部实现简单的 Codec,即:将这个协议进行编解码就可以,大大降低开发支持新协议的成本。
最后是对多框架和协议的支持问题。Mesh 对协议的要求包括具有请求特征信息扩展的能力,可以实现请求特征路由;具有元信息扩展能力:能够在框架和 Sidecar 间传递信息(如:一致性哈希的 Code),在上下游服务模块间传递信息(如:TraceID,SpanID) 内部传统的老协议如何接入 Mesh?通过框架实现协议升级,用可扩展的 baidu-std 协议封装老协议进行传输,到达下游服务之后再由框架拆解开报文。
服务网格性能优化针对代理架构如下图所示,社区方案是从 APP1 进入 Sidecar 再到下游服务的 Sidecar 再到 APP2,这里面经过了两次 Sidecar,会有两倍延迟或者两倍资源开销,在百度内部可能并没有这么复杂,没有对这个很高要求的场景,多数情况下只经过 Sidecar 一次。比如,APP1 经过 Sidecar 后直接到达了 APP2,并没有再次经过 Sidecar。
另外一种模式,内部很敏感的业务并不希望经过 Sidecar。比如,APP2 通过框架直接访问到 APP3,并没有经过任何的 Sidecar。下图左是经过一次 Sidecar 的模式(在百度内部称为一跳)这是通过 NamingService 注册再访问本地 IP。而下图右 Proxyless 模式 Sidecar 会将自己服务的参数以及目标服务的 IP 通过 NamingService 下发给框架,框架拥有下游服务的 IP 以及服务治理的全部参数,可以直接完成访问。
针对数据面性能方面的优化,社区的 Envoy 在性能方面并不是特别优越,所以。百度整合了一个 bRPC 开源框架作为内核去转发流量,在上层 bRPC 框架依然兼容了 xDS 协议(服务治理参数的协议),便于同步社区的新设计、新变化,做到了鱼和熊掌都可以兼得的效果,经过升级内核的版本以后,在各个延时、长尾以及 CPU 使用率上都有很好的优化。
最后是控制面性能优化,控制面在没有配置 Sidecar CRD 的情况下,会下发所有的服务列表,我们通过内部的关键路径优化,实际上只会下发 Sidecar 关注的下游,大大减少控制面对配置计算以及下发的性能优化。
经过上述改造后,最后就完成了百度内部对 Mesh 的整体优化和修改。
业务收益及案例启示经过上图所展示的高级服务治理策略,在 SLA 以及故障恢复时间上都有很高的优化。在此基础上还有全局的智能容灾系统,可以优化高级服务策略参数
服务可观测性方面,可以通过框架传递 TraceID、SpanID 等,再通过 Sidecar 再采集到内部的 Trace 平台和监控平台,可以在内部的监控平台上展示 Trace,方便监控以及进行故障的排查和追踪。
自动止损方面,整个系统结合内部的监控平台,监控平台将这些指标存储在自己的平台上,稳定性预案平台根据监控平台的指标异常进行实时调参,执行流量降级、切机房、切流等。同时这个效果会实时反馈给监控平台,包括稳定性预案平台持续的对系统进行调参,形成闭环。
混沌工程方面,会通过控制平面下发给故障任务,然后控制平面将命令下发给 Sidecar,Sidecar 通过这个命令注入一些延迟,这样去影响内部的系统,内部系统同样会产生监控的指标,这些指标再上报给监控平台,然后混沌平台再通过这些指标评估系统的弹性以及容错等。
系统容量评估方面,容量平台可以发起压测任务,这个任务对接到控制平面。如:由控制平面下发切 20% 的流量到某下游服务,对它进行压测,实时产生的指标上报给监控平台,容量平台对监控平台的指标进行实时评估。
百度内部业务接入情况:
百度 App、信息流、百度地图、智能小程序、好看视频等产品线
接入实例十万级
每天处理请求数千亿次
业务接入收益:
大幅提升核心链路的可用性和系统整体容灾、防雪崩能力
大大降低治理迭代成本、服务治理迭代周期从数月缩短到天级别
解锁服务可观测,自动止损,容量探测等高级场景能力
最后,乔元才总结了通过接入 Mesh 服务网格得到的一些启示:
服务网格不是微服务治理的银弹
完全无入侵的,支持所有协议,所有框架和所有治理策略的 Mesh 方案是不存在的
大规模工业化落地的平滑、稳定可控接入方案,涉及到大量对已有服务治理组件的兼容升级和改造
服务网格确实实现了业务逻辑和服务治理架构的解耦,解锁了很多新能力
服务网格结合可观测、故障止损、混沌工程,容量管理等场景化,才能发挥出最大价值
百度智能云已开放包括服务网格在内的多项微服务产品,欢迎试用:https://cloud.baidu.com/product/cnap.html
本文授权转载自“百度云原生”,原文链接:
今日好文推荐Docker员工自述:我们为什么“输”给了Kubernetes?Amazon Elasticsearch Service正式更名,云厂商和开源社区间必有一战?日调用量超三十万亿,腾讯开源百万级服务发现和治理中心北极星网络安全风云15年:没有天才,也没有了江湖 | 顶尖技术团队访谈录 活动推荐汇集全网最深度技术内容,聚齐各领域最优秀创作者InfoQ 引航计划正式启动,下一个引导技术领域共建发展的 Pioneer 就是你!扫描下方二维码获取更多活动信息!
点个在看少个 bug 👇