吴连火,腾讯游戏专家开发工程师,负责欢乐游戏大规模分布式服务器架构。有十余年微服务架构经验,擅长分布式系统领域,有丰富的高性能高可用实践经验,目前正带领团队完成云原生技术栈的全面转型。
欢乐游戏这边对 Istio 服务网格的引进,自 2019 开始,从调研到规模化落地,至今也已近三年。本文对实践过程做了一些思考总结,期望能给对网格感兴趣的同学们以参考。
在正文开始之前,先明确一下本文所说的服务网格(service mesh)概念 —— 基于 sidecar 通信代理,网状拓扑的后端架构级解决方案。目前业界最流行的开源解决方案为 Istio。
服务网格的架构思想,是解耦,以及加一层。通过将基础的治理能力从进程中解耦出去,以 sidecar 的形式提供,以达到更大规模的复用,一旦标准化,将会是行业级的复用!其实作为微服务领域炙手可热的解决方案,网格所做的解耦分拆进程这件事情本身就很 “微服务”,因为微服务其实也是做进程拆分,解耦并独立部署,以方便服务的复用。
总体上,我们做的是一个大技术栈体系的演进,体现了较好的技术价值,提升了研发效能。所以对于我们而言,现在再回望,网格化是否值得实践?答案依旧是肯定的。
但假如抛开技术栈演进这个大背景,单独看网格本身的话,那么坦率地讲,我们对网格能力的使用是较为初步的:
考虑到实际开销情况,我们并没有拦截 inbound 流量,所以如果有依赖这点的功能特性,目前也无法实践。
从笔者个人的观察来讲,istio 网格最具吸引力的,实际上就两点:
至于熔断、限流、均衡、重试、镜像、注入,以及 tracing 监控之类的能力,严格来讲不能算到网格头上,用 sdk 也是一样可以实现的。在团队语言统一的时候,只用维护一种语言版本的 sdk,此时采用治理 sdk 方案也是可行的,也就是所谓的微服务框架方案。采用 sdk 方式下的版本维护问题,以及后期进一步演进网格的问题,这些都不难解决,这里不再发散。
对于我们自己来讲,因为恰好有引进 golang 以及 gRPC,所以现在再看,选择 istio 作为网格方案也算合适。
接入网格,要考虑天时地利人和。即,需要满足一些基本条件:
此外,对于这类大的技术优化,还有必要先统一思想:
在早期的构思阶段,需要明确几个大的关键问题:
对于第一点,不同团队要看自己的实际情况,这里不做展开。
对于第二点,k8s 在业界的大规模应用非常多,所以还算是可靠的,而且它 level triggered 的设计,使其具备较好的健壮性。相对未知的是 Istio,团队一开始对 Istio 做了一些压测,也考虑了回退无 mesh 的情形,结论是可以尝试。Istio 本质上就是一个复杂大型软件,所以其本身主要使人望而生畏的点,是其复杂的配置,版本之间的兼容性担忧,以及偏黑盒可控性不好这几点。现在想来,其实我们团队的步子迈得还是比较大的。幸运的是,后面的落地过程表明,Istio 本身稳定性也还行,不至于三天两头出问题。
对于第三点,我们针对性地做了引入间接层的设计,使用私有协议与 gRPC 互转的网关确保了服务平滑迁移上云,在服务内部引入 grpc 适配层确保了研发人员的开发模式基本不变。
系统整体架构如下图所示,可以清晰地看到上文所说的间接层:
图示:gRPC 适配与网格内外通信代理
对于评需求、定方案、写代码等差异不大的点,这里不做展开。下面主要罗列一些在云原生的技术栈体系下,与我们以前相比,有显著差异的一些研发体验。
图示:基于不同号码部署不同的专属 deployment
讨论性能之前,这里先说一下我们的实践方式:关掉 tracing,关掉 inbound 拦截(远端流量过来的时候,并不会走 sidecar)。
图示:pod1 上的业务容器调用 pod2 上的服务,仅拦截 outbound
在上述背景下,结合我们的线上真实案例情况,分享一下读者可能会比较感兴趣的性能数据:
对于内存开销的问题,社区有相对明确的解决方案,采用 sidecar crd 来限定载入业务所需访问目标服务的 xds 信息,即可大幅减少内存占用。业务进程需要访问哪些目标服务,可以通过手动维护、静态注册或代码生成之类的办法明确,我们后面也会做相关的优化。
接下来我们用相对大的篇幅讨论一下 cpu 开销的问题,先看一个大扇出业务的性能 top 示例:
图示:大扇出业务进程与 envoy 性能对比示意
看到上图中的数据,读者可能会有这样的疑问:为什么仅支持 gRPC 的转发,envoy 就需要如此高的 cpu 开销(图中 71.3%,远超业务进程的 43.7%)呢?关于这点,我们在分析火焰图之后,也没有发现显著异常的地方,它所做的主要工作,也就是在做协议的编解码与路由转发而已,无明显异常热点。
现在网上大量介绍 envoy 的资料,基本都会说它性能比较好,难道...真相其实是 envoy 其实做的不够高效么?针对这个问题,笔者这里也无法给出一个明确的答案,envoy 内部确实大量使用了各种 C++ 的抽象,调用层级比较多,但这未必是问题的关键所在,因为:
关于最后这一点,我们观测了业务主进程中的 grpc thread,它也需要做 http2 的解析和编解码,但它的 cpu 开销显然低得多。
图示:业务进程中的 grpc 线程 %cpu * 2 后依然比 envoy 小很多
将业务进程中的 grpc 线程(红框部分)%cpu 乘 2 后再与 envoy(蓝框部分)做对比,是因为 envoy 对 outbound 拦截的 workload 相对业务进程而言确实近似翻倍,例如就编解码而言,对于一次 req、rsp,业务进程就是 req 的编码和 rsp 的解码,但是对于 envoy,则是 req 的解码 + 编码,rsp 的解码 + 编码。
图示:envoy vs 业务进程的编解码开销
从上面的示例来看,grpc 自己做 http2 parse + 编解码 + 收发包的性能,要远好于使用 libnghttp2 的 envoy,但 envoy 显然不可能直接采用 grpc 里面的相关代码。要想更好地回答关于 envoy 做 grpc 通信代理性能的疑问,恐怕还需要做更加细致的分析论证以及测试(欢迎感兴趣或有经验的读者来交流)。
总之对于 gRPC 大扇出业务 sidecar cpu 损耗过大的这个问题,我们暂时也没想到好的优化方案。当然上面那个案例其实相对极端,因为是大扇出 + 主业务进程为 C++ 的情况,如果是小扇出则 sidecar 不会耗多少 cpu,如果是 golang 业务进程则 sidecar 占 pod 整体 cpu 开销的比例不会这么夸张(当然这也反过来说明 golang 性能和 C++ 差距还是蛮大的...)。
对于我们自身来讲,网格的综合性能并没有严重到无法接受的地步:
如前文所述,envoy 的性能问题,在大扇出业务场景下确实难以忽视。
如果真的无法接受相应的性能开销,那么可能私有协议或私有网格会是可选的替代方案。
对于欢乐自己的团队而言,后面会持续做更深度的实践。例如 envoy filter 开发、k8s crd,以及 istio 的更多能力的实践(上文也提到了,我们目前仅使用了一小部分网格能力,期望以后能使用熔断、限流等能力来提升业务的可用性)。
ebpf 可能未来会与容器网络、网格有更好的融合,可以提升网络相关性能表现,或许还会带来其他一些可能。
proxyless mesh 可以看做基于前文讨论性能问题的一个延伸,和前面提及的私有网格有些类似。这类方案也会有对应的生存空间,因为始终有些团队无法接受数据面 sidecar 所带来的性能开销:
proxyless mesh 实际上就是 sdk + 网状拓扑的方案,gRPC 现在也在持续完善对 xDS 的支持,所以也有可能借助 gRPC 的能力来实现。如果自行研发支持 xDS 的 sdk,那对于团队的投入还是有要求的,除非团队本身就是大厂的中间件类团队(网易轻舟、百度服务网格、阿里 dubbo,这一两年都有做 proxyless mesh 的实践)。
图示:proxyless gRPC mesh
对于编程语言统一的团队,例如全 golang,那么只用维护一套服务治理相关的 sdk(控制面逻辑也可以用 agent 承载),所以可能会倾向于做一套自己私有的解决方案。据笔者了解,B 站之前就是采用的这种方案,参考 eureka 实现名字服务自己做流量调度。
现在随着网格的流行(起码对应的理念已经广为人知了),私有方案也可以参考对标 xDS 的各种 feature。因为私有方案通常是自研的,所以理论上还能提供相对高效可控的实现,但是需要团队持续投入维护。
概念很好,故事很宏大,不过目前看来还为时过早。
让 istio 支持私有协议:
【https://github.com/aeraki-mesh/aeraki】
grpc 对 xDS 的支持:
【https://grpc.github.io/grpc/cpp/md_doc_grpc_xds_features.html】
proxyless grpc:
【https://istio.io/latest/blog/2021/proxyless-grpc/】
nghttp2 解析库:
【https://nghttp2.org/】
infoQ 基础软件创新大会微服务专场:
【https://www.infoq.cn/video/7RLecjvETz3Nt7HedviF】
xresloader 配置转换工具:
【https://github.com/xresloader/xresloader】
Dapr:
【https://dapr.io/】
互动赢好礼
精读文章,回答问题赢好礼
作者对欢乐游戏 Istio 云原生服务网格三年实践作出了思考和分享。
那么大家在接触 Istio 和服务网格中又有哪些思考或者有趣的故事呢?欢迎评论区留言分享!
5月18日下午5点,将选出回答最佳的5位读者,送怪企鹅暖手枕一个!
往期精选推荐