阿里、蚂蚁、晟腾、中科加禾精彩分享 AI 基础设施洞见,现购票可享受 9 折优惠 |AICon 了解详情
写点什么

Istio 在百度百亿级流量⽣产环境的研发实践

  • 2021-09-27
  • 本文字数:5584 字

    阅读完需:约 18 分钟

Istio 在百度百亿级流量⽣产环境的研发实践

Service Mesh 从诞生至今短短数年,就以席卷之势成为了云原生时代的通信设施标准,被奉为“下一代微服务”。然而由于像 Istio 这样 Service Mesh 中的佼佼者,其在对异构基础环境支持、私有协议支持、复杂流量调度策略、产品化和易用性、性能和可靠性等方面还存在诸多限制和缺陷,Service Mesh 的落地一直以来都令人谈虎色变。


2021 年 QCon(北京)全球软件开发者大会上,百度 陈鹏 分享了结合 Service Mesh 在百度公司 Feed、手机百度、百度地图等百亿量级流量的核心生产环境大规模落地的真实案例,分享了关于上述 Service Mesh 落地的诸多痛点问题的深入思考和实践经验。


以下是演讲内容整理,以飨读者。


决定业务有没有必要上 Service Mesh,在什么程度上使用 Service Mesh,最重要的依据是业务现状。所以今天我会先分享百度服务治理的现状,再分享百度在落地 Istio 时遇到的问题,以及百度是如何解决的。


百度的 Service Mesh 经历了三个阶段:内部探索、跟进探索、拥抱开源


2013 年,百度研发了独立的 Sidecar 和 Proxy 代理一些流量,这是 Service Mesh 在百度的萌芽;2016 年,百度网盘大规模落地的 UFC 系统和现在 Service Mesh 的理念和架构功能已经非常相似了,也是用 Proxy 代理流量控制中心;2016 年的 9 月份,Service Mesh 的概念首次被提出后,百度立刻意识到了它会带来的变革。所以 2017 年,百度采用 Go 语言自研了一套 Service Mesh 系统—— BMesh 。


与此同时,社区发展迅速。2018 年的 7 月, Service Mesh 的明星产品可用于生产环境的 Istio 1.0 版本发布了。面临这个情况,百度最终决定拥抱开源。因此 2019 年,百度研发了基于社区的 Istio + Envoy 的解决方案,目前已经大规模落地了。

为什么要引入 Service Mesh?

Service Mesh 主要可以解决三种问题:


第一,多语言技术栈能力不统一。百度内部的语言生态非常复杂,内部应用最广泛的框架是基于 C++的 bRPC,还用了 Java 的 Spring Cloud 生态、PHP 的 RAL 框架、Go 的 GDP 等。同时使用了多个语言,但各个框架的使用方式、配置方式以及服务治理的能力天然是不统一的,这必然会损害用户体验和后端能力。


第二,服务治理周期长。分布式的能力总和业务进程耦合在一起,所以无论是技术库的维护升级,还是调整策略,服务治理的周期都非常长,成本也非常高。


第三,服务产品能力非常弱。大部分服务都是以配置文件为主,没有接入配置中心,可视化能力非常弱,没有平台化或产品化的功能,如配置变更版本追溯的能力,审查、审计的能力等,用户体验很差。


Service Mesh 进程隔离的特性,很好地解决了这些问题。很多公司都想落地 Service Mesh,但是落地的过程却很不顺利。我们以 Istio 为例,看看 Service Mesh 在生产环境落地面临的问题。

Istio 在生产环境落地面临的问题的百度解决方案

Istio 在生产环境落地面临很多问题首先,Istio 原生是为了弥补 Kuber-Proxy 流量调度上的缺陷而设计的,所以它在很多方面深度依赖 Kubernetes,而大多数公司还没有完全迁移到 Kubernetes 上,这必然影响 Istio 的落地;其次,Istio 只支持 HTTP 协议,但是很多公司使用的是内部私有协议,而且 Istio 支持的策略也很有限,因此 Istio 落地时,我们主要专门解决这些协议和策略的问题;最后,Istio 的稳定性、性能、产品能力也会影响业务方的使用规模。


那么这些问题,百度是如何解决的呢?我们先看第一个问题, Istio 对 Kubernetes 的深度依赖。

对 Kubernetes 的依赖问题

Istio 对 Kubernetes 依赖分为三部分,第一部分是 Sidecar 的注入和管理。


Kubernetes 的 PaaS 的可编程性和接口比较好,但是我们自己的 PaaS 或类似平台缺乏这样好的规范或接口,这样的话如何注入 Sidecar 呢?注入之后,如何大规模自动化管理 Sidecar 呢?面对这些问题,百度落地 Istio 时联合了内部的 PaaS 团队,进行了支持 Sidecar 模式的联动研发。


Istio 对 Kubernetes 依赖的第二部分,是 Istio 的各类配置依赖了 Kubernetes 各种组件,尤其是依赖了 API Server 和 etcd 做流量调度策略的存储。API Server 和 etcd 是可以进行独立部署的,所以百度保留了这部分组件。


最头疼的是第三个问题,Istio 依赖于 Kubernetes 的服务和流量模型,比如说服务调用基于虚拟的 ClusterIP,比如流量劫持使用了 Iptables 或 IPVS。


由于一些性能稳定性、可管控性等等的原因,百度的生产环境是无法使用 Iptables,内部的服务发现也没有用 Kubernetes 的方式,所以这个问题是最棘手的,决定了百度的流量到底能不能够让 Mesh 接管。面对这个问题,百度选择了研发新的流量劫持模式——基于 Naming 的流量劫持。

在传统的这种软硬件环境下如何做 Mesh 流量的接管

基于 Naming 的流量劫持

百度的流量劫持模式是基于百度微服务体系的私有 Naming 系统的。



图中左侧是 Consumer ,右侧是 Provide。正常 Consumer 调用 Provide 时,会去注册中心或本地的 Agent 查找下游的服务实例列表。


接入 Mesh 以后,第一步,我们会在 Mesh 的上层用户产品—— Console 上定义一个连接关系。图中定义的连接关系是 Consumer 会访问 Provide。借鉴 Kubernetes 的 ClusterIP 的概念,我们会给它分配一个本地回环地址。图中举例的本地的回环地址是 127.1.1.1,代表了访问的连接关系。


接着我们会把这个连接关系下发给 Consumer 侧的 Sidecar,即代理 Envoy。Envoy 会监听 127.1.1.1 的地址,服务会监听另外的端口。


第三步我们会联动 Envoy 和 Naming Agent。Envoy 会把自己的监听的地址注册到 Naming Agent 里伪装自己。此时业务的 Naming Lib 去访问 Naming Agent 拿下游,拿到的是本地 Envoy 的地址。 图中 Envoy 把自己注册成了 Provide ,地址是 127.1.1.1:8000,不是真实下游 Provider 的 10.1.1.2:3000。


第四步 Consumer 会发出请求,而第五步返回的是 127.1.1.1 的 8000 端口。此时的核心思想是 Envoy “欺骗” Naming Agent 自己是下游的实例,把流量导到自己。 Consumer 以为它请求的是真正的 Provide ,实际上是把流量发给了本地的 Envoy。Envoy 收到以后,会去真正的 Naming Agent 里做解析。


这样可以实现在 Sidecar 侧做服务发现。这样做是因为策略配置变更频率低,而服务端点的这种实例状态信息的变化频率高,控制面做服务发现压力很大。


另外第 7 步里 Envoy 去请求下游时,Inbound 的流量是可选的。图中既可以请求 Provide 真实监听的 3000 端口,也可以请求 Envoy 监听的 3001 端口。这样,出口流量必须经过 Envoy ,但是入口流量却不一定。


这是因为业务方会担心多过一次 Envoy ,会影响耗时和性能。而 Envoy 的能力,比如说负载均衡、超时、重试、熔断等都集中在上游,下游的功能很少,所以我们把下游做成了可选的模式。当然,如果你希望拥有 Envoy 全部功能,而且对性能不那么敏感的话,可以在 Consumer 和 Provide 侧都接入 Sidecar。


原生 Istio 会给任何 Sidecar 推送全集群所有服务的信息,比如 Consumer 可能只需访问一个服务 Provide,而 Istio 会给它所有服务的信息,这对 Consumer 自身的 Sidecar 资源开销和控制面推送的压力都很大。


而我们的方案定义了 Link 模型,这样可以做到精准下发,Consumer 只会收到 Provide 相关的配置,XDS 的推送量可以从 O(N)降到 O(1),Envoy 的内存占用也会大幅度减少。


面对故障,我们在 Envoy 和 Naming Agent 之间设置了一个非常敏感的 HeartBeat——心跳探活机制(上图中红色的部分)。一旦检测到 Sidecar 故障,我们会及时地去掉 Envoy 注册的伪装实例,Consumer 服务会在下一次解析周期里近乎实时地回退到直连模式。因此业务方不必担心 Envoy 是否挂了。


因为 Naming Lib 适用范围很广,所以通过修改 Naming Lib 做流量劫持的方案适用范围也很广。而且在没有使用容器网络的主机网络下,我们通过收集由 PaaS 动态分配的端口,也可以使用这套方案。

融合 Envoy 和 bRPC 的性能优化

在毫秒级别的请求、资源紧张、CPU 内存敏感的场景下,Envoy 无法满足业务方的需求。所以我们基于 bRPC 和 Envoy 各自具有独到的优势,做了深度二次开发。


bRPC 实现了一个非常高性能的用户态的线程,不完全等同于 Go 语言的协程,但是和用户态很相像,有高性能的 IOBuf 库,可以高效地做 Socket 处理。它还有优秀的 IO 机制,擅长处理长尾等等场景。


而 Envoy 的扩展机制非常灵活,在 L3、L4、L7 层都提供了很多 Filter 扩展机制;此外, Envoy 本身也实现了非常多丰富的策略,再加上它有 XDS 协议,可以进行动态地配置分发。


我们融合了这两套系统的优点。我们使用 bRPC 的内核组件重构了 Envoy。融合之后,平均延时和 CPU 开销⼤幅降低,效果如下图所示:



⽀持私有协议和⾼级策略

面对原生 Istio 不支持私有协议或一些高级策略的问题,百度也进行了相关优化。


因为 Istio 的扩展架构比较灵活,所以百度基于 Istio + Envoy 的扩展机制,全面支持了大多数私有协议,包括百度内部标准协议 Baidu STD、一些比较老的 Nshead、HTTP、Java 生态的 Dubbo 协议等。


Istio 每新增一种协议,都需要制定一种语法,描述该协议流量分发方式。百度把这些协议统一为了标准的协议框架,减少了很多的重复开发。真正在数据面做流量转发时,我们可以根据请求 HEAD 的特性做协议嗅探。


高级策略方面,百度在 Envoy 里做了加强版的 BackupRequest——DynamicBP。


BackupRequest 的核心是快速重试:在一个请求还没有回来时,就发出一个新的请求,优先使用先回来的请求结果。重试在很多场景下是高危的,而且在延时不太稳定的场景下,很难确定该在什么时候进行重试。


DynamicBP 会动态计算一段时间间隔的超时比例,借此设置重试时间。比如说对超过 99 分位值的长尾 Request ,才进行 BackupRequest。这能避免雪崩,更安全。


由于 Mesh 的控制面可以对网络行为进行动态地编程、修改配置、实施生效,服务治理效率会大幅提升。之前大规模的服务治理调整需要耗费半年时间,现在只需要几天,明显提升了故障容忍的可用性。


除此之外,百度实现了和测试、混沌相关的流量复制、流量镜像和一些其它高级负载均衡策略。这样业务方接入 Mesh 后,不仅能力不会变少,还获得了一些新的策略。线上实际效果如下图所示:



此外,Mesh 与框架语言无关的特点可以赋能其它的框架和语言。所有框架和语言可以共享在 Mesh 里实现的策略。比如下图中的框架原先不具备某种高级的能力,所以前面抖动比较厉害,接入 Mesh 以后复用在 Mesh 里移植的能力,稳定性大幅度提升。



如何解决 Istio 原⽣产品能⼒缺失

Istio 原生产品的能力本来就有缺失。比如 CRD 接口非常多,但是官方管理接口的 Kiali 基本上不可用;还有配置动态分发的安全问题,以前改配置有和 PaaS 结合的审计系统,接入 Mesh 后的监管问题。


面对这些问题,百度聚合了丰富的服务治理策略,可以让不了解 Mesh 的人,在良好的 UI 体验下完成服务治理。


一方面,百度集成了很多运维场景问题的解决方案,比如说跨机房切流,如何实时把流量切到其它机房,甚至按比例切流;再比如实时地关掉某一个链路的服务网格的开关;还有如何快速故障⽌损等等。


另一方面,如果 Mesh 上线后有任何问题,业务方可以一键回滚到对任何指定版本,及时地规避在线上遇到的问题。


当然,百度对任何一次服务变更都有详细的记录,会清晰地展示出操作者、操作时间、操作详情以及概述,便于审计或追查。


百度在 Mesh 上还做了很多平台化的工作。比如混沌平台可以和控制平面对接,负责调度任务,进行效果评估,而服务网格负责执行策略。图中 App1 调用 App2 边车 时,需要注入一个延时故障或一个百分比故障验证特定的 App2-3 实例。这时混沌平台可以通过监控平台收集反馈指标。



再比如线上运维。线上运维最头疼的就是容量压测,直接压测可能会把服务压垮,所以常常需要在大半夜流量低时去压测,运维人员也会非常辛苦。有了 Mesh 以后,可以利用 Mesh 精准的动态分流能力,让容量压测平台对接 Mesh。如下图所示,可以对下游某一个服务的实例,按百分比进行导流,让它接受比较大的流量。根据小部分实例的容量上限和实例的占比,就可以计算出服务在线上真实环境的容量水平。



百度智能云云原⽣微服务平台支持以上所有功能、协议扩展、性能优化,还支持公有云和私有化部署,感兴趣的同学可以去看一下。

百度 Service Mesh 落地经验总结

这里是一张百度 Service Mesh 的全景图,要想做 Service Mesh 落地,就要打通图中的所有环节。



当前百度使用 Mesh 的业务很多,包括手机百度/Feed、百度地图、小程序、好看视频等。切入 Mesh 的服务体量有几千个,实例数在 10 万左右,每天流量的 PV 是百亿级别。


通过接入 Mesh ,百度实现了跨语言统一的服务治理,提升了服务的可用性,微服务治理的周期从月级缩短到了分钟级。同时,服务变更的效率提升了 10 倍以上,再加上产品化、平台化等等的产品,运维人员的体验也明显提升了。


Istio 落地的核心要素总共有四个方面:务实、性能、稳定性和体验。这四个方面中最重要的是务实,也就是必须要适配公司的基础设施,实现公司生产环境里使用的策略或协议。这决定了能不能接 Mesh,后面三个方面不过是接入规模或体验的问题。


Istio 社区关注的是透明、安全性、可观察性、可扩展性等特性,百度关注的是 Istio 落地时的性能、流量治理策略、Sidecar 管理的可管控性、以及复杂网络或底层基础设施环境的支持。


未来,百度希望和社区继续融合,持续地跟进社区的新版本,引⼊社区⾼级扩展特性,同时百度也会向社区贡献性能优化和策略扩展相关的经验,和社区共建 Istio 生态。


嘉宾介绍


陈鹏,百度云原⽣技术专家,现负责百度 Service Mesh 的研发和落地,对服务网格以及云原生有深入研究。见证了百度 Service Mesh 从无到有,从摸索到大规模落地演变过程。致力于推动 Service Mesh 在多种场景下的落地。


ArchSummit 全球架构师峰会,将于今年 12 月 3 日与 4 日在北京国际会议中心举办,为此我们邀请国内一线技术专家来分享,更有经纬中国带来投资人视角下的中国开源与基础软件机会与挑战,微服务、云原生、低代码、机器学习等众多热门专题已经上线,希望对你有启发~



2021-09-27 19:146305

评论

发布
暂无评论
发现更多内容

LeetCode题解:641. 设计循环双端队列,使用队列,JavaScript,详细注释

Lee Chen

大前端 LeetCode

数据提交

hasWhere

鸿蒙系统究竟是PPT秀还是有真材实料?鸿蒙HarmonyOS开发环境搭建与运行Demo

软测小生

华为 鸿蒙 HarmonyOS

阿里P8大牛力荐Java程序员进阶必读的书籍清单(附电子版)

Java架构之路

Java 程序员 面试 编程语言 书籍推荐

《转》Spring事务传播机制

hasWhere

java安全编码指南之:敏感类的拷贝

程序那些事

Java java安全编码 java安全 java安全编码指南

onblur调用alert导致的死循环

hasWhere

揭秘App的财富密码,剖析算法工程师价值来源

峰池

人工智能 互联网 推荐算法 互联网公司

CICD实战——服务自动构建与部署

TARS基金会

DevOps 后端 jenkins CI/CD TARS

Java进阶教程、大厂面试真题、项目实战,GitHub上这14个开源项目屌炸天了!

Java架构之路

Java 程序员 面试 编程语言 项目实战

写给新人算法工程师

峰池

互联网 新人 推荐算法 算法工程师

Redis 缓存性能实践及总结

vivo互联网技术

redis redis集群 redis监控

ARChatRoom功能介绍手册

anyRTC开发者

音视频 WebRTC 语音 RTC 安卓

实践案例丨利用小熊派开发板获取土壤湿度传感器的ADC值

华为云开发者联盟

物联网 IoT 传感

for-range造就循环永动机?快来看看go中for-range的那些事!

Gopher指北

后端 for Go 语言

一文了解Zookeeper

Java旅途

kafka zookeeper 分布式

栈与队列简介

Java旅途

数据结构 队列

《我在你床下》观后感

徐说科技

架构师训练营第 1 期 第 2 周作业

李循律

极客大学架构师训练营

《转》POI的XWPFParagraph.getRuns分段问题

hasWhere

公有云厂商哪家强?本月UCloud、百度云、阿里云位居三甲——2020年8月云主机性能评测排名

博睿数据

学习思路

hasWhere

基于数组的有界阻塞队列 —— ArrayBlockingQueue

程序员小航

Java 源码 队列 源码阅读 JUC

在多架构时代,英特尔扩展高性能计算边界

E科讯

解读华为云原生数据库设计原则,打破传统数据库上云瓶颈

华为云开发者联盟

数据库 数据

清华架构师整理分布式系统文档:从实现原理到系统实现,收藏吧

小Q

Java 程序员 架构 分布式 微服务

c++ 杂谈3

菜鸟小sailor 🐕

格式化报文输出

hasWhere

如何避免option请求

hasWhere

Http自定义请求头接收不正确

hasWhere

form表单提交get请求

hasWhere

Istio 在百度百亿级流量⽣产环境的研发实践_云原生_李慧文_InfoQ精选文章