2019 年底,作业帮技术栈比较多元且业务复杂度较高:使用最多的语言为 PHP 和 Golang,约占到总模块数量的 60% 左右;此外还有大量的系统使用 NodeJs、Java、C++、lua、python 编写等,即使是同样的技术栈,也会因为业务特点、团队特点,技术栈上呈现出较大差异;工具型产品侧重客户端,服务端技术偏保守。产业互联网业务,领域驱动,大量使用微服务架构,但由于没有统一的标准,各自团队也在自研服务治理体系的基础设施。
语言栈多元后,业务间的沟通协作就变得困难。跨语言的微服务框架难以落地统一的服务治理标准,致使业务服务治理参差不齐,大大限制了业务的快速迭代和稳定性。
同时作业帮的服务调用方式比较多样化,有 HTTP、gRPC、自研协议等,治理难度非常大,不同的 RPC 协议也会导致服务间通信困难。作业帮当时已有数千个服务,且服务间请求链路较长,一次请求的深度可能就超过一百多、甚至数百。
此时,已经完成容器化进程的作业帮开始着手调研服务治理技术,希望借助 Service Mesh 技术,来解决当时复杂的服务治理问题。
同年,为了适应云原生发展,作业帮进行了组织架构调整,将运维、安全、数据库、架构研发和部分通用中台等统一归纳到了基础架构团队。Service Mesh 的工作也落到了基础架构团队头上。
解决复杂治理问题最大的“拦路虎”是:业务既渴望使用新技术,但又担忧会带来高昂的使用成本,因此宁愿原地停留也不进行升级。那么,作业帮基础架构团队是如何解决这一问题的呢?这次,InfoQ 有幸采访了基础架构团队负责人董晓聪和架构研发团队负责人吕亚霖,为我们详细阐述了作业帮的实践思路和效果。
全自研 Mesh
“基础架构团队在进行服务治理时,既要保证稳定性,还要能够帮助业务提升效率。”董晓聪总结道。具体来说,团队的核心目标就是让 Service Mesh 接管服务治理里大量的非功能逻辑,实现服务的流量控制、可观测性和安全韧性,并且通过能力下沉,让业务透明、无感地接入。
但面对当前市面上各种开源产品,基础架构团队在前期充分调研后,认为这些产品都不太能满足作业帮的需求,因此选择了一条全自研的路。
数据面,更看重性能
数据面上,作业帮更倾向追求极致的性能,而对扩展性的需求并不迫切。这是由于作业帮内部的链路较长(上百 span),对业务来说哪怕是单次请求毫秒级的损失,整体上都会带来较大的影响。
对于主流产品 Envoy,作业帮基础架构团队不太认同它的插件模式。“插件机制引入主要是为了降低开发难度,虽然能有效降低研发成本,但是性能较差,同时提供的隔离也不彻底。”作业帮架构研发团队负责人吕亚霖说道。
因此,基础架构团队用 C++ 自己实现数据面,初期按需求紧迫程度支持了三类协议:第一类是 RPC 数据面,负责服务通信;第二类是对象存储数据面,负责对象存储资源的鉴权管理、流控、分发及性能提升;第三类是加解密数据面,负责提供安全和数据加密的能力。这三种数据面的协议差异性很大,分别对应了 RPC 通信协议、文件读写流协议、加解密协议,且对性能要求极为苛刻。
整体上,基础架构团队主要针对 RPC 协议,采用了 Mesh-proxy 代理方式。对于入流量,直接通过 UDS 转发给了 Server,Server 需要支持 UDS 监听;对于出流量,则与 Istio 类似,用 iptable 拦截,不过团队另用 eBPF 做了优化。
吕亚霖表示,iptable 出流量拦截过程复杂,带来了不少的性能损失,因此团队使用 eBPF 优化内核网络劫持,在 Sock Map 进行映射、省掉中间环节,就可以极大提升劫持性能。eBPF 优化的前提是系统内核是 5.X 版本以上,作业帮使用的是 5.10 版本,主要是 5.10 版本解决了 CO-RE 有利于后期的升级维护,而 Istio 为了适应大部分客户内核低版本情况并没有支持。
根据作业帮此前的测试,以 Envoy 官方数据为例,在 QPS 为 1000 下,Envoy 在模式的 v2-stats-wasm_both 下 P90 响应时间是 2.25 毫秒,相比于 baseline 测试结果,添加了 Envoy 边车之后 P90 时延增加了 1.3 毫秒,且随着并发加大逐步恶化。作业帮自研数据面实测添加了 mesh 边车之后 P90 时延增长比这个数据降低了 0.38 毫秒,随着并发加大比较稳定。当 QPS 从 1000 加到 10000 时,平均响应时间减少 0.4 毫秒。另外在 CPU 耗损上,在 QPS 为 1000 的情况下,Envoy 耗损 0.54 核,作业帮的数据面损耗 0.09 核。这项测试也验证了作业帮数据面的可用性。
事实上,从立项到数据面研发完成,基础架构团队只用了两个月左右的时间。“我们是把问题进行了拆解和聚焦,使用了云原生 Kubernetes 的基座,初期只对 RPC 类流量做了 mesh 劫持。同时聚焦数据面性能本身。”作业帮基础架构负责人董晓聪说道。
控制面,纳入统一管控平台
控制面上,作业帮本身有完整的运维管控体系,即包含服务注册发现相关,还有服务感知的一系列能力。所以作业帮并没有单独做一个 Service Mesh 的控制面,而是基于已有体系扩展,直接实现进行流量管控、通信协议、安全等。
对于作业帮来说,管控面是 DevOps 理念的落地,能更好的贴合自身研发流程和组织管理,比如:统一鉴权、工单体系、审计体系等。
对于 Service Mesh 的控制面,作业帮并没有引入类 Istio 在 Service Mesh 的实现服务注册发现,而是使用原生的 Kubernetes 的注册发现。作业帮基础架构团队认为,在大型的复杂工程中,架构设计的核心目标是复杂度降维,而将服务注册发现引入到 Service Mesh 却是在将复杂度升维,Kubernetes 的服务发现是 node 级别,而 Istio 的服务发现是 pod 级别,服务发现数据是数量级的提升。而对于升维带来的更强计算力和内存需求等问题也没有给出很好的解决方案。比如 Istio 的 xDS 使用全量下发策略,会把整个网格内所有服务发现数据同步给 proxy 边车,这会带来一系列的问题。
另外根据团队观察,很多公司在接入的时候,精力被耗在了 xDS 对接上,从原有协议向 xDS 转换过程中也充斥着各种各样的问题。
基于以上考虑,作业帮并没有使用 xDS 来提供发现机制,而是沿用了 Kubernetes 里注册发现方式,通过 eBPF 来优化 service,也具备路由决策等能力。在基础架构团队看来,这种方式更加轻量级,也与 Kubernetes 社区的结合更为紧密。
另外在安全性方面,团队进行了认证授权、网络拦截等;观测性上,全量埋下了分布式追踪,支持日志的统一观测和监控等。
在作业帮基础架构团队看来,用不用某个协议只是看其能否满足实际需求或者是否认可它的模式。用 xDS 的好处是会有统一标准,但 xDS 能否成为事实标准,还有待时间的检验。
吕亚霖表示,目前将 xDS 当作标准还有一些风险。“xDS 成为标准的前提是升维带来的复杂度被其他方面拆解掉,但它现在的降维手段并不是一个通用方案,我们在看到新方案出来之前是不会跟进的。”不过团队也会继续观望,关键还是要看其能否在大型企业的大规模复杂场景下落地。
超预期的推广速度
研发完成后,基础架构团队开始了“边放量、边灰度、边优化”的循环。对作业帮来说,基础架构团队涵盖了不同方向的小组,团队内就可以完成闭环测试,然后再向业务推广。
实际上,Mesh 在作业帮内部的推广速度远超基础架构团队的预期。据悉,目前作业帮 Mesh 覆盖率已经超过 80%,涵盖了 C++、Python、PHP、Go、Java 等语言栈。董晓聪表示背后的核心原因有多个,一是流量管控和观测,真正帮助到了业务,二是 Mesh 是相对无感接入,三是 Mesh 落地提升了研发效率。
流量管控和观测方面:主要实现了流量管控、安全(认证授权)、可观测性(日志统计、全量分布式追踪)。流量管控上实现了很多业务期待的功能,比如自适应限流。很多情况下业务需要熔断限流,但是不太可能每个服务都进行压测配置限流阈值,同时业内的自适应限流算法与流量以及自身资源相关,也无法实现因下游服务容量问题时主动限流。作业帮将机器学习应用于该领域,实现了智能的流控,当通用模型不适合某些特定流量场景时,也提供基于过去半年的数据,学习和训练特有模型。
接入相对无感:业务几乎不需要改造,只需要兼容 listen uds,其他由基础架构直接升级,然后进行放量观察即可。改造成本极低。
研发效率方面:在原来的微服务开发模式下,模块非常多,业务进行联调和测试的效率非常低。比如联调要经过 CI/CD、发布到测试环境、验证等一系列复杂的过程,而微服务里改动一个需求可能就要改动几十个模块。一个研发每次改动就要重复一遍上述过程。而 Service Mesh 在研发阶段的作用就是使研发可以直接在本地启动服务,并且这个本地服务可以无缝的和远程的 Kubernetes 测试集群中的各个其它服务实现互相调用,免去了复杂的 CI/CD 流程。
“一个业务线里面有一两个服务用了发现效率提升非常明显后,会形成很好的口碑效应,之后该业务其他研发会主动找过来要求升级。”吕亚霖表示。据悉,作业帮内部研发主动升级的比例在 50% 左右。
不过在推广过程中,基础架构团队也踩过坑。一次灰度放量时,某业务线使用了不规范的 HTTP 协议,但 Mesh 拦截 RPC 流量是按标准协议处理的,所以就产生了冲突,该问题影响了服务间的通信。
“这也让我们认识到,多语言栈下的协议确实没有那么规范,而这种不规范更多是因为各个语言,在协议实现层面上的差异导致。”董晓聪说道,“同时也展现了 Service Mesh 这项技术的意义,即接管服务治理里大量的非功能逻辑,实现标准化。”
除了这次事故,其他方面都远远超过了团队的预期,甚至由于需求变多,团队不得不投入更多的人力。
同时这次 Mesh 落地实践也让基础架构团队深刻体验到了内核研发能力的重要性。
“服务的各种小问题会特别容易摧毁业务线对你的信任。问题多了,哪怕是他业务的问题也会怀疑是 Service Mesh 的问题。”吕亚霖表说道,“这些问题都要及时解决,但在这个过程中,团队发现最后这些问题大部分需要在内核层面定位和配合解决。比如业务反馈平响多了几毫秒或者毛刺率变高,都需要在内核底层进行追踪定位,需要基础架构团队有一套分析定位内核的工具,同时内核追踪需要和业务的分布式追踪关联,才能快速定位解决问题。
总体来看,作业帮 Service Mesh 的落地收益比还是很不错的。作业帮基础架构团队只投入了两个专职人力,进行 Service Mesh 的研发和迭代。推广上持续了一年。通过 Mesh 的协议升级,带来了性能和稳定性的提升,比如 PHP、python 很多都是 HTTP1.0 的短链,团队通过 mesh 层进行协议协商升级,在业务无感的情况下将 HTTP 升级到了 2.0,减少网络建连、提升了网络传输速率。同时 Service Mesh 的落地带来了治理能力的大幅提升,全量的分布式追踪、完善的监控报警,以及在协议实现上的标准和统一。
结束语
虽然如此,吕亚霖提醒道,业务体量不大的时候跟风上 Service Mesh 并不会带来太多收益,甚至可能使整体产品的迭代变慢。多语言栈、链路比较长、业务要求比较高的情况更适合接入 Mesh。
“真正落地的时候你就会知道适不适合了,真正引入 Mesh 后发现推广不下去,本质上就说明了不适合。一项技术非常匹配时,推广便是一件水到渠成的事情。”吕亚霖说道。
另外,企业真的要接入 Mesh,也没有必要自研。自研对企业的研发能力要求会比较高。首先,Mesh 自研对 C++ 工程师的研发能力要求很高,但如今很多公司大多是 Java 工程师做基础架构。其次,根据作业帮基础架构团队的经验,团队要有内核研发和定位的能力,对于一些小公司来说可能并不具备这样的条件。
对于当前自研的选择,吕亚霖表示,这是有很多前提条件的。“比如 97% 的容器化、整体内核升到了 5.10、多语言栈、业务链条复杂、对时延敏感等,我们会觉得自研会更有优势。一旦这些前提不在了,自研就不见得比选择现有产品更好。”
嘉宾介绍:
董晓聪,作业帮基础架构负责人
吕亚霖,作业帮基础架构 - 架构研发团队负责人
评论 2 条评论