作者:董艺荃|携程服务框架负责人
携程微服务产品的倒退历程
携程微服务产品起步于 2013 年。最后,公司基于开源我的项目 ServiceStack 进行二次开发,推出 .Net 平台下的微服务框架 CServiceStack。
2014 年,公司推出 Java 平台下同 CServiceStack 齐全互通的自研微服务框架 Baiji 和第一代服务注册核心。该服务注册核心后续经验屡次重构,目前应用的已是第四代产品。
2017 年,公司正式引进开源产品 Dubbo,推出整合携程治理能力的 CDubbo 框架。该框架最后基于 Dubbo 2.5.4 版本进行二次开发,经验屡次版本升级后,目前应用 Dubbo 2.7.7 版本。
2020 年,公司正式开始摸索落地 Service Mesh 我的项目。目前,相干产品曾经在生产环节正式落地,正在进行接入推广工作。
携程微服务产品状况简单,次要在于以下四点。
第一,线上同时运行着三种微服务框架产品。
第二,同时采纳 HTTP 和 Dubbo 两种通信协议。
第三,采纳齐全自研的基础设施,包含注册核心和配置核心。
第四,现存 8000 多个线上服务,实例数超过 10 万个。
随着研发的深刻,咱们团队次要遇到了以下三点问题。
第一,保护多个性能相似的中间件产品工作量较大,保障产品之间性能对齐须要破费大量的精力。
第二,因为产品以 SDK 公共依赖包的模式集成在业务利用内,进行版本升级须要业务方配合,推动降级比拟艰难,版本长尾问题重大。
第三,因为团队工作精力和技术栈的限度,只有少数几个语言平台上存在 SDK 反对,不利于小众语言用户应用微服务产品。
携程的云原生微服务架构设计
因为线上集群已初具规模,如何平滑适度和迁徙框架成为关键问题。彻底摈弃现有基础设施,一步到位实现全面云原生,不仅施行难度较大,我的项目周期也比拟长。
因而,我的项目决定采纳“小步快走”的形式。首先保障代码齐全向后兼容,其次保障整体架构反对业务利用迁徙,晋升接入容错率。
我的项目进行架构设计时,遇到了三个要害的问题。
数据权威问题:常见的 Service Mesh 实际以 K8S 为准则,将所有的数据保留在 K8S 内,但平台现有数据大部分保留在自研的注册核心和配置核心内。
有计划提出采纳两条推送路的形式,云内数据保留在 K8S 内,云外数据保留在现有注册中心里,通过内部工具或组件实现双向同步。但双向同步复杂度较高,既要保证数据的准确性和实时性,也要保障同步不成环。
因而,出于架构简便性思考,我的项目最终抉择放弃注册核心数据权威位置不变,通过内部组件将数据写入 K8S。
边界划分问题:目前的我的项目部署体系是一个 Region 内蕴含多个 Zone,一个 Zone 内又蕴含多个 K8S 集群,集群之间网络互通。但因为故障隔离的须要,数据最好放弃在 Zone 内收敛,使实例信息不须要进行跨 Zone 同步。
Zone 内收敛存在的问题是当调用方发动跨 Zone 调用时,须要通过网关进行直达。这种调用形式和现有的调用链路存在差别,会进步计算复杂度。
因而,我的项目最终抉择放弃现有工作模式不变,使得调用方可能获取 Region 内所有的 Zone 服务实例,保持数据在 Region 内通明。
技术选型问题:过来,我的项目研发产品大部分采纳自研模式,通过整个团队成员合作实现开发工作,而依靠开源社区可能更容易地产出优良产品。
因而,我的项目最终抉择基于开源产品进行二次开发。
目前所应用的 Service Mesh 架构设计,也被称为“渐进性”架构,次要有三个方面的特点。
开源方面:抉择 Istio 和 Envoy 作为 Service Mesh 的基础设施。
实例和配置同步方面:由新开发的 SOA Operator 负责将存储在注册核心和配置核心中的数据写入 K8S。
同时,该程序也会把 K8S 集群内服务提供方的数据写入注册核心,使得 K8S 集群外用户也可能失常读取服务数据。并且,该服务不须要 SDK 反对,由 SOA Operator 间接实现注册和发现,任何语言都能够不便地接入微服务产品体系。
应用方面:K8S 集群外的利用依然应用过来的交互方式,通过 SDK 和注册核心进行通信。
K8S 集群内的利用,如果应用 SDK,检测到 Sidecar 存在之后,SDK 会主动地敞开服务治理性能,应用非凡的 host 进行申请。如果不存在 SDK 反对,接入 Mesh 能够间接应用 HTTP Client,持续应用非凡的 host 发动申请。
HTTP 协定在 Service Mesh 架构上运行良好,但 Dubbo 协定在 Sidecar 网关上存些一些问题。
其一,元数据的地位:HTTP 协定中元数据位于报文最前端,而 Dubbo 协定中元数据位于报文末端,因而须要先解析报文能力定位到元数据地位。
其二,序列化问题:解析报文须要对报文进行反序列化解决,目前 Envoy 反对 Dubbo 默认序列化协定。但这种形式会产生额定开销,而且 Dubbo 服务应用的序列化器简单,甚至还有一些团队为进一步升高报文大小,应用了压缩算法,网关解析难度大。
Dubbo 3 推出了 Triple,这是一种应用基于 HTTP/2 的 gRPC 并通过申请标头实现元数据信息传递的通信协议,也是 Dubbo 3 中举荐应用的服务通信协议。
Triple 协定实用于 Envoy 框架,且能轻松接入 Service Mesh。Dubbo 版本升级也并不简单。
因为 gRPC 的 PB 序列化格局,Triple 协定无奈间接应用。只管 Triple 协定对 PB 兼容性较好,但 PB 要求先写契约再生成代码,而 Dubbo 要求先写代码,不存在契约,数据模型也是与 PB 对象齐全不同的 POJO 格局。
为了连贯 POJO 和 PB 对象,Triple 协定设计了 Wrapper。将原 POJO 对象序列化解决失去二级数据后,传入到 Wrapper 用 PB 进行序列化。
然而,这种形式不仅会导致内存占用变大,而且会引发更多的 GC。屡次 GC 和反复序列化将会增大 CPU 负载。
为解决 Triple 协定带来的问题,我的项目给 gRPC 增加了自定义序列化器。这样不仅能够实现流式的序列化,也能够为用户提供和原生 Dubbo 一样的应用体验。
其余语言想要调用这种 gRPC 服务,只须要具备这种自定义序列化器即可,默认的自定义序列化器 JSON 能够被大部分语言解析。
治理方面,Service Mesh 应用 Istio 和 Envoy 作为基础设施,通过 Istio 读取 K8S 中 CRD 数据,并生成配置推送给 Envoy。
因而,保留在自研服务治理零碎里内的实例数据、配置数据必须全副转化成 CRD 格局,同步到 K8S 以供 Istio 解决。
Operator 作为翻译机蕴含了大量模型转换逻辑,可能将配置模型翻译成 CRD 模型。针对一些简单的性能,我的项目通过 Envoyfilter 或者 Envoy 的二次开发,增加自定义的 Envoyfilter 进行实现。
目前,所有的罕用性能都已实现对齐,整体性能覆盖率超 90%。数千个线上利用实现接入,进入后续接入推广工作。
云原生微服务产品的将来发展趋势
Service Mesh 提供的都是通用能力,如分组、路由、流量管制、负载平衡等。这些性能自身没有语义,一线的业务研发和运维人员了解起来存在肯定艰难。
而且,该产品性能与现存治理零碎的性能存在差别。为了给一线人员提供更好的微服务治理体验,须要将理论运维需要和底层控制数据分割起来。
目前,社区内 Dubbo Mesh 的研发工作也在踊跃进行,其做法跟携程云原生微服务治理框架相似。通过独自的管制面将配置数据写到 K8S 里,将实例数据通过 MCP 进行同步。
另外,新的开源产品 OpenSergo 也在研发中。据官网介绍,该我的项目力求打造一套通用的面向云原生的微服务治理规范,并且提供一系列的 API 和 SDK 实际。
目前,多家大型互联网企业和开源社区正在独特推动该项目标进行,心愿可能实现从服务治理到云原生基础设施的全链路生态笼罩。