阿里云「飞天发布时刻」2024来啦!新产品、新特性、新能力、新方案,等你来探~ 了解详情
写点什么

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:146311

评论

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

近年来面试阿里总结出360道面试题,【Java岗】(JVM

Java 程序员 后端

这篇Kafka笔记真是写的太好了!不收藏都对不起我的眼睛

Java 程序员 后端

遇到Java内存溢出(OOM)时,这样排查

Java 程序员 后端

重走JAVA之路(五):面试又被问线程池原理?教你如何反击(1)

Java 程序员 后端

拥有一台服务器后,我竟然这么酷?

老表

Python Linux web开发 云服务器 跟老表学云服务器

超进化!阿里腾讯大佬联合撰写亿级网关、分布式、微服务等太香了!(1)

Java 程序员 后端

还在担心面试遇到SpringBoot,莫慌,我送你套神级pdf文档

Java 程序员 后端

Vue进阶(幺捌叁):IE9兼容性问题-数据初始化问题

No Silver Bullet

Vue 11月日更

重走JAVA之路(五):面试又被问线程池原理?教你如何反击

Java 程序员 后端

跨年巨作!13万字!腾讯高工纯手写“JDK源码笔记”直接带你飙向实战

Java 程序员 后端

【LeetCode】环形链表 II Java题解

Albert

算法 LeetCode 11月日更

这400道面试题,决定了你去BAT还是TMD

Java 程序员 后端

超进化!阿里腾讯大佬联合撰写亿级网关、分布式、微服务等太香了!

Java 程序员 后端

软考(软件设计师)考点总结 -- 数据库技术

Java 程序员 后端

还没搞懂Java中的路径?看完这篇文章你就全懂了

Java 程序员 后端

送给你一份程序员大佬整理的 HTTP 基础知识大图

Java 程序员 后端

通过AOP和自定义注解实现请求日志收集功能

Java 程序员 后端

逼着面试官问了我ArrayList和LinkedList的区别,他对我彻底服了

Java 程序员 后端

我终于知道,中国互联网是怎么弯道超车,干翻美国了!

博文视点Broadview

软件设计师复习(一)

Java 程序员 后端

远景能源java后台开发实习面试题

Java 程序员 后端

适合程序员表白的情话【保你脱单】

Java 程序员 后端

透过根源从而探究红黑树的本质,究竟二叉树是什么神仙鬼怪?

Java 程序员 后端

金三银四助力面试-手把手轻松读懂HashMap源码

Java 程序员 后端

超详细:常用的设计模式汇总

Java 程序员 后端

还在傻乎乎得背MyISAM与InnoDB 的区别?一篇文章让你理解的明明白白

Java 程序员 后端

还在用 Guava Cache?它才是 Java 本地缓存之王!

Java 程序员 后端

dart系列之:dart语言中的异常

程序那些事

flutter dart 程序那些事 11月日更

这六个 MySQL 死锁案例,能让你理解死锁的原因!

Java 程序员 后端

适合程序员表白的情话【保你脱单】(1)

Java 程序员 后端

【Flutter 专题】11 图解 ListView 的多种绑定方式

阿策小和尚

Flutter 小菜 0 基础学习 Flutter Android 小菜鸟 11月日更

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