去哪儿网 Service Mesh 落地实践:100%容器化打底,业务友好是接入关键
自 2011 年引入 Dubbo 框架至今,去哪儿网的微服务架构已经有了十多年的历史。时至今日,去哪儿网架构已经形成了 Dubbo、HTTP 协议为主,多语言共存的格局。
根据去哪儿网基础架构部高级技术总监朱仕智分享的数据,现在去哪儿网 Dubbo 服务接口有 18,000 多个、HTTP 域名超过 3500 个,内部大约有 Java、Golang、Node 和 Python 等 5 种语言的技术栈,其中以 Java 和 Node 为主。此外,去哪儿网在线运行的应用大约 3000 多个、MQ 应用主题超 13,000 个。
随着业务的不断发展,多语言、多协议给基础架构团队带来了不小的治理问题。
首先,多语言的复杂性主要在于 SDK 的重复实现,每个治理逻辑需要开发不同的语言版本,此后还要一直对其进行维护,这是一份冗余且负担很重的工作。
在多协议治理上,一方面,去哪儿网内部有 Cactus 平台对 Dubbo 进行治理,治理功能相对完善。另一方面,去哪儿网对 HTTP 的治理主要通过 OpenRestry,治理能力相对薄弱,一些必需的治理需求零散分布在多个平台,对开发同学很不友好。
Dubbo 和 HTTP 治理能力不统一导致了重复造轮子情况,增加了业务的开发和维护成本。
此外,业务和中间件强耦合,但业务部门与基础架构部门对升级更新的意愿并不同步。基础架构部门不断升级更新来完善中间件,但业务研发在不影响使用情况下并不希望频繁更新。所以每次发布新版本后,基础架构团队要花很长的时间进行推广,致使整个迭代周期变长。
而 Service Mesh 将服务治理能力下沉到了 sidecar,SDK 只需要负责编解码、与 sidecar 通信,通用逻辑基本不用修改,只要对 sidecar 修改就可以应用到所有语言和框架,于是在去年,去哪儿网开始组织团队引入 Service Mesh 来解决自身多语言、多框架的治理难题。
在去哪儿网资深开发工程师李佳龙看来,容器化下比较适合引入 Service Mesh。
大概从 2014 年起,去哪儿网便开始使用 Docker、Mesos、Kubernetes(以下简称 K8s)等来解决测试环境构建困难的问题,也逐渐尝试基于容器部署 ES、MySQL 等中间件服务。到了 2021 年底,去哪儿网全面实现容器化,业务服务基本完成上云。从效果数据来看,容器化虚拟比例从 1:17 提升到 1:30,资源利用率提升 76%,宿主运维时间由天变成了分钟级,环境稳定性差、交付慢、可扩展性差和服务器成本高等问题都得到了有效解决。
经过多年积累,去哪儿网已经为引入 Service Mesh 打下了坚实的基础。引入 Service Mesh,本质上也是去哪儿网步入云原生实践新阶段——多方向探索的体现之一。
在去年加入去哪儿网后,李佳龙主要负责 Service Mesh 的落地工作。团队基于去哪儿网的现状,明确了对新服务治理体系的期望:多语言、多协议统一治理、治理能力增强,同时可以将治理能力下沉,实现基础组件开发周期和业务开发周期解耦。
整个实践过程主要分为三个阶段:调研、开发和推广。调研阶段的主要任务是技术选型。去哪儿网团队用了两周左右的时间,调研了其他企业的落地情况。
自 2011 年引入 Dubbo 框架至今,去哪儿网的微服务架构已经有了十多年的历史。
如何找到适合自己的产品呢?首先,由于业界已经有成熟的产品,因此去哪儿网没有选择重复造轮子,而是基于业内已有开源软件进行选型。其次,去哪儿网团队还从产品是否成熟、社区活跃度、性能是否满足公司需求,以及开发和维护难度等方面进行了考察。
最终,去哪儿网选择了蚂蚁开源的 MOSN 作为数据面。MOSN 经过了阿里双十一几十万容器生产级别验证,产品自身已经成熟。另外,MOSN 社区比较活跃,迭代也较快,更新周期基本维持在了两个月左右。
语言也是重要的考虑因素。由于在 C++ 技术栈方面人才储备有限,团队放弃了流行的 Envoy。MOSN 的开发语言是 Go,在性能、开发、维护难度和灵活性上有优势,虽然不是去哪儿网使用的主要语言,但开发人员入门和上手都比较快。MOSN 既可以替代 Envoy,也可以集成 Envoy 在网络层高性能的优势,并将其作为自己的网络插件使用。
控制面上,去哪儿网选择了 Istio,并根据自身需要对其进行了二次开发。Istio 使用 XDS 协议与数据面进行交互,是很多企业的首选,去哪儿网选择紧跟社区的脚步。但原生的 Istio 有个问题,就是和 K8s 耦合非常严重:主要体现在 K8s 既是注册中心又是配置中心,以及 sidecar 注入、启动配置和网络模型等。这导致去哪儿网团队面临着以下问题:
K8s 存储是以应用为维度,但 Dubbo 是以 Service 为维度,维度不统一问题怎么解决?
去哪儿网内部容器要和 KVM 共存,如何解决兼容问题?
公司内部已有比较成熟的注册中心和配置中心,一刀切必然会引入很多适配和运维成本问题。如果遇到定制化需求,是否会影响 K8s 集群的稳定?
去哪儿网希望 K8s 更多的用于服务编排,因此在最初商定方案时,选择解耦 K8s,采用内部使用多年的注册中心和配置中心。于一些启动配置,则依赖去哪儿网内部的配置中心(QConfig),同时团队自研了 McpServer 模块替代 K8s 来对接 Istio。
整体架构
接入 Mesh 后,业务主要关心的就是性能、治理能力和问题排查。因此在做好技术选型后,去哪儿网团队便开始设计实践方案,并花了数月的时间进行研发。
目前,业界将流量从 SDK 拦截到 sidecar 的方式主要有两种:iptables 拦截和流量转发。但由于 iptables 的可运维性和可观察性较差,配置较多时还会出现性能下降的问题,因此很多公司选择了流量转发的方式,去哪儿网也是如此。
去哪儿网主要使用了两种流量转发方式:一是升级 SDK,在 SDK 中直接将请求转发到本机 sidecar;二是域名拦截,例如使用 dnsMasa 将 xx.qunar.com 的请求转发到本机 sidecar。
李佳龙提醒道,引入 Service Mesh 后,流量安全值得特别关注,因为之前两个服务的调用变成了四个服务间的调用,大大增加了不稳定性。对此,去哪儿网主要采取了四方面的措施来保证流量的安全:
SDK 自动调用降级。当业务进程与 sidecar 连接断开 (基于健康检查) 时,调用降级为直连调用。
sidecar 节点故障剔除。sidecar 会对 upstream 的节点列表进行健康检查,一旦发现连接异常就快速剔除。
用户可以在新的统一治理平台 Captain 上一键切入 / 切出 Mesh 模式。
柔性可用。为保证可用性,当控制面出现问题时,sidecar 会使用缓存数据;当注册中心或配置中心出现异常,MCPServer 以及 Istio 也可以使用缓存数据。
对于 sidecar 的配置、部署、升级、回滚和灰度等,去哪儿网团队将其整合到了运维面上。
以 sidecar 的升级为例,Sidecar 的升级可以分为两个场景:原地升级和服务部署时升级。前者不需要重新部署服务,但需要确保升级对用户透明、流量无损。
Sidecar 的注入和升级
对于原地升级,由于 sidecar 容器和业务容器是同属一个 pod 的两个独立容器,基础架构团队将 MosnAgent 作为 sidecar 容器的 1 号进程,用于管理 sidecar 的生命周期,例如启停、健康状态检查和升级等。新版本发布时,会将 sidecar 镜像推送到镜像仓库,同时将二进制包推送到对象存储。
基础架构团队通过 sidecar 管理平台,可以对 sidecar 容器发送升级指令,MosnAgent 会拉取对应版本的 mosn 包,之后启动新版本 mosn,并通过 fd 迁移机制,完成无损升级流程。
而部署时升级,发布平台会请求 sidecar 管理平台来获取 sidecar 配置,包括是否注入、sidecar 版本、环境变量、配额信息等,然后生成服务的 yaml 配置。注意在部署时,有可能遇到 sidecar 容器、业务容器的启用顺序问题。如果 sidecar 容器未启动成功或者配置未拉取成功、但业务容器已经 ready,那么请求就会失败。基础架构团队设置成 sidecar 先于业务容器启动,并通过配置 K8s 的 postStart 钩子函数,来保证正确的启动顺序。
需要注意的是,Istio 下发配置时,也可能发生顺序异常问题。去哪儿网团队通过 Istio merkeltree 来跟踪资源下发进度,通过暴露接口来查询每个资源是否全量下发到 sidecar。
另外,运维面还负责对接内部系统,如内部配置中心、全链路监控系统、报警系统、镜像仓库及对象存储等。
在性能优化方面,首先由于业务容器与 sidecar 容器同属一个 pod,基础架构团队选择了使用 unix domain socket 进行通信,以此规避网络栈、优化性能。
其次,团队对 Dubbo 协议进行了优化。sidecar 接收到请求后的第一步是获取路由信息,用以服务寻址。按照 Dubbo 原来的设计,路由信息 (service/method/group 等) 存放在 body 中,但为了避免不必要的 body 反序列化,团队扩展了内部 Dubbo 协议,将路由信息放置到了扩展 header 中。
再者,团队选择按需加载 xDS 数据方式。Sidecar 启动时会请求控制面拉取 xds 数据,但是原生的 Istio 会拉取当前集群中所有服务数据,导致 sidecar 资源占用过多以及推送风暴,大大制约了 Service Mesh 的集群规模,这也是很多公司落地 Service Mesh 要解决的问题。去哪儿网的解决方式是配合内部 Spring Cloud Qunar 框架,在编译器采集订阅关系,并扩展 xds 协议,来实现按需加载。
除了按需加载配置,基础架构团队也在优化推送性能,统一服务注册模型等。
针对之前治理功能分散、能力不统一的问题,基础架构团队将 Dubbo 和 HTTP 统一到了新的 Captain 平台。
“在设计时,Captain 要尽量做到服务治理与协议无关。”李佳龙说道。比如,之前 Dubbo 服务需要在项目中配置参数支持调权预热、HTTP 在发布平台配置支持引流预热或者自定义接口预热,引入 Service Mesh 后就可以很方便地支持 Dubbo/HTTP 调权、引流两种预热模式。
此外,Captain 增强了很多服务治理能力,例如多维度的限流策略,包括基于应用粒度限流和基于优先级限流。业务团队既可以根据应用的不同来设置不同的限流阈值,也可以根据不同的流量来源设置不同的优先级,优先处理有价值的请求。
如下图所示,当流量达到设定的阈值时会触发限流,这时流量会进入到多个优先级队列,可以按照优先级处理。
此外很多情况下,业务会将超时时间、限流阈值设置得比较大或比较小,这未能起到应尽的作用,基础架构团队根据监控数据和合理算法,会智能推荐超时、限流等参数。
目前,去哪儿网已经在基础平台、机票等部门开始推广和试行 Service Mesh。
“推广是最为关键、也是比较容易出现阻塞的地方。因为对于用户来说,让系统最稳定的做法就是不轻易做变动。”李佳龙说道。
那么,如何让业务更容易接受 Service Mesh 呢?去哪儿网团队先是在内部做了关于 Service Mesh 基本认识的分享,让业务了解接入 Mesh 后都能得到哪些收益。
然后对于新服务治理平台,基础架构团队也注意保留了很多业务的使用习惯。比如在实际使用中,超时时间等治理参数与路由的相关度较低,业务更习惯作为服务提供方配置某个接口的超时时间,或者作为服务调用方配置要调用服务的超时时间。但在 xDS 协议中,超时时间等治理参数配置在服务提供方,并且与路由绑定。因此,基础架构团队做了部分扩展,业务可以从服务提供方、调用方两个角度来进行配置,并以接口为维度,这些配置包括超时、重试、备份请求、负载均衡策略等。
便捷性对业务来说也是非常重要的,业务希望切到 Mesh 后能够方便地查询问题,日志,trace,监控报警等内部系统的打通也是推广的前提。
基础架构团队现在提供了两种 Mesh 接入方式:第一种是接入新的开发框架 Spring Cloud Qunar,业务需要做部分改动;第二种是无侵入地一键接入,业务不需要修改代码,这也是接受度较高的一种方式。
另外,去哪儿网提供了按照接口级别的接入方式,业务可以按照百分比来切入 Mesh,而不是一刀切地接入。基础架构团队的策略是让业务先从一个小的接口、小的流量来接入,业务接受了之后再扩大接入范围。
在李佳龙看来,便捷易用性问题一定程度上确实阻碍了 Service Mesh 的落地。
一方面,从业务角度看,使用者更加在意 Mesh 接入后是不是好用、操作是不是简单、切换起来是不是安全和方便、需求是不是能够满足、能不能保留之前的研发习惯等等。另一方面,从开发角度看,企业开发 Service Mesh 时通常有很多工作,比如进行二次开发并与内部系统打通,还有诸如 xDS 按需下发,sidecar 管理等目前没有统一标准的工作,这些都需要维护成本。公司基础设施之间有差异,这些都需要决策者考虑清楚。
Service Mesh 不是一个很新的概念,它的本质就是解耦,具体实现起来就是语言 SDK 负责编码以及与 sidecar 的通信,这部分比较固定,不包含治理功能。虽然还是多个实现,但是复杂度降低了一个量级,从而将更多的功能实现,抽离到独立的 sidecar 进程,只需要实现一次。“所以本质上,解决多语言多协议的复杂问题,是分离了变与不变,这也是去哪儿网进行软件架构时的常用方式。”李佳龙说道。
那么对于企业来说,是不是要容器化后才能够接入 Service Mesh 呢?李佳龙表示这不一定。
“只能说,Service Mesh 天然比较适合容器化的场景,比如 Istio 方案默认使用者已经具备 K8s 的基础设施了,但是我们仍然可以有多种方式支持虚机接入服务网格,只要解决掉 sidecar 注入、升级,流量拦截,服务注册发现等。而且我们设计之初去除了 K8s 的耦合,接入虚机也变得更方便。按照去哪儿的云原生的发展来看,容器化作为云原生架构的底座,在容器之上能更好的支持 Service Mesh、Serverless 等。”
就中小企业而言,李佳龙表示,中小企业首先考虑的更多是业务。业务越来越多、越来越复杂后,才可能会出现多语言、多框架的问题。只有确实出现这个问题时,才应该开始考虑是否引入 Service Mesh。此外还需要考虑自身的基础设施、团队技术储备等是否支持落地。Service Mesh 是利用低复杂的技术去解决高复杂度的问题,如果本身复杂度不高,引入 Service Mesh 这样的技术只会增加复杂度,得不偿失。
还有一个值得关注的方面就是性价比。引入 Service Mesh 的新增成本包括 sidecar 所占有的资源,比如每个 sidecar 占用的 CPU、内存、磁盘以及其他如 trace 存储、日志存储等存储资源。另外,像请求耗时增加、系统开发维护等会产生相应成本,因此去哪儿网目前对于各类日志是按需开启,只打印耗时高的 trace 信息。
”不过目前看,Service Mesh 确实带来了很多好处。”李佳龙说道,“首先便是统一了多语言、多框架的治理能力,提供丰富的治理功能。另外对业务开发透明,减少了业务的使用成本。与业务解耦后,我们的推广周期也大大缩短。”
“Service Mesh 应该会是未来的一个发展趋势。”李佳龙表示,“之后去哪儿网会在可观察性、性能优化、多语言支持上持续发力。”
李佳龙,2021 年加入去哪儿网基础架构部,担任资深开发工程师,近五年专注于云原生、基础架构等领域,负责去哪儿内部 Service Mesh 和新服务治理平台 Captain 的研发落地等工作。
凭借在开源圈的好人缘,能让谷歌云找回自己失去的 10 年吗?
微信扫码关注该文公众号作者