本文分享自**《华为云DTSE》第五期开源专刊**,作者:聂子雄 华为云高级工程师、李来 华为云高级工程师。
微服务是一种用于构建应用的架构方案,可使应用的各个部分既能独立工作,又能协同配合,微服务的治理模式在适应云原生的方向也逐步在演进中。本文以汽车行业DMS系统在微服务应用发布时面临的挑战为切入点,介绍了基于微服务SDK框架与JavaAgent技术的全链路灰度发布,整体方案能够有效提升微服务应用发布的效率。
1、微服务应用在发布时面临的挑战
微服务架构因其小而独立的特点受到广大开发者欢迎,我们生活中很多常见的应用也是基于微服务的架构。微服务架构强调应用拆分为一系列责任单一的小型服务单元,各个服务单元可进行独立部署,相互协作配合,这种架构模式极大的提高了IT团队的开发效率。
微服务应用在发布的时候一般会采用一种叫灰度发布的策略,它将新版本的软件逐步地推送给一小部分用户,以便在全面发布之前测试和验证新版本的稳定性和可靠性。这种发布策略可以减少潜在的风险和影响,因为只有一小部分用户受到影响,而其他用户仍然可以使用旧版本的软件。
常见的灰度发布一般只针对某个单点的服务进行实施,在很多情况下,这种方法可以大大提高应用发布的效率及稳定性。当然,单点灰度发布实际上也存在一些缺点,下面以汽车行业中的DMS系统为例进行分析:
DMS全称为汽车经销商管理系统(Dealer Management System),专门为汽车经销商和售后服务提供商设计的软件系统,帮助汽车经销商实现业务数字化、自动化和智能化,提高业务效率、降低成本、提升服务质量。很多厂商的DMS系统都做过微服务化改造,在提高了团队开发效率的同时,也遇到了一些业务发布场景的挑战:
-
经销商想在某一个门店A上线自己的新业务,作为业务试点门店,比如新品汽车销售,或者打折促销活动等。和新业务相关的流量只会流入试点门店B。
-
为了节约成本以及降低部署服务工作量,希望能够实现逻辑上的环境隔离。例如,测试环境有部分服务复用生产环境上的模块,开发测试人员只需要聚焦于需要测试的服务模块。
-
经销商的交易、商品服务有新的业务要上线,新上线的功能间有依赖和交互,要在上线前做一些测试工作。
-
计划让测试人员专门账号来进行现网测试。
-
引入少量比例的生产流量进行验证。
针对上述问题,一般的思路是通过灰度发布去解决,通过灰度发布,可以引入部分的测试流量到新业务模块,也能控制带有具体特征的流量只流入到对应的测试模块,其余流量保持原有方式不动。
但是经过仔细考虑,就会发现如果只做单点灰度发布,其实是无法完善地解决以上场景的痛点问题,主要体现在:
业务特征时常只在第一跳,也就是特征只在入口,传递过程中会丢失。
除了第一跳入口,后续微服务之间进行调用的时候也会把特征给丢失。
因此,仅仅依靠单点灰度发布的能力是不够的,还需要能够做到整条微服务调用链的可灰度,也就是全链路灰度的能力,这样就可以灵活解决类似DMS系统遇到的问题。
后续我们将以全链路灰度发布的场景来展示微服务SDK框架和JavaAgent如何相互结合,解决真实场景中的服务发布问题。
2、微服务治理方案的选择
在提出具体解决方案之前,我们可以先了解基于微服务SDK框架以及基于JavaAgent技术的治理模式。微服务SDK进行治理是常见的一种形态,我们常见的Spring Cloud、Dubbo都属于微服务SDK架构,这种方式通常可以较为方便的通过外部依赖的方式集成各种服务治理功能。JavaAgent则可以通过非侵入的方式引入微服务治理功能,下面将对这两种模式进行解析。
2.1 基于微服务SDK框架的微服务治理
2.1.1 原理和优势
服务治理是一个宽泛的概念,通常来说,保证微服务可靠运行的策略,都可以称为服务治理。这些策略涵盖开发态、运行态和运维态等微服务生命周期。可以从两个不同的角度进行描述服务治理:
-
从管理流程上,可以分为进行业务定义和设置治理规则两个步骤。系统架构师将请求流量根据特征打上标记,用于区分一个或者一组代表具体含义的业务,然后对这些业务设置治理规则。
-
从处理过程上,可以分为下发配置和应用治理规则两个步骤。可以通过配置文件、配置中心、环境变量等常见的配置管理手段下发配置。微服务SDK框架负责读取配置,解析治理规则,实现治理效果。
-
由于微服务应用是基于微服务SDK框架开发的,开发者可以明显可以感知微服务SDK框架的存在,此外SDK和应用实例是运行在同一个进程中,这些特点也给微服务的治理带来了一些好处,包括但不限于以下:
-
更轻量级:微服务SDK框架在运行时不需要起单独的进程,因此资源开销较小。
-
治理粒度更精细:微服务SDK可以直接对应用实例的某个方法直接进行管理,因此能够满足各种治理场景要求。
-
性能高,时延低:微服务实例之间的链路不存在代理,访问的时候是直接点对点的调用,因此时延低,并且微服务SDK框架可以提供高性能的RPC,保障数据的高效传输。
华为云也致力于为开发者提供全面开放,方便高效的微服务SDK框架,目前对外开源的稳定成熟框架主要有Spring Cloud Huawei和Java Chassis。
2.1.2 Spring Cloud Huawei框架
自从Netflix开源出最早的Spring Cloud微服务SDK框架,Spring Cloud在这个领域的发展非常迅速,目前Spring Cloud已经是业界广泛使用的微服务SDK框架之一。为了让开发者能够更加方便、高效地使用Spring Cloud开发可靠的微服务应用,基于Spring Cloud和华为云服务生态体系,华为云提供了Spring Cloud Huawei微服务SDK框架,为开发者提供了一站式的开发、部署、运维、监控、治理等全生命周期的服务。
使用Spring Cloud Huawei,开发者可以不用熟悉和了解Spring Cloud,只需要熟悉Spring和Spring Boot,就能够按照微服务架构模式开发应用。相对于Spring Cloud,Spring Cloud Huawei能够更好的支持快速微服务开发,提供开箱即用的微服务治理能力。
2.1.3 Java Chassis框架
Java Chassis框架是Apache ServiceComb项目下面向Java语言的微服务框架。ServiceComb项目最早源于华为微服务引擎(CSE),在2017年12月捐赠给Apache基金会,目前已经形成了庞大的微服务生态,而Java Chassis是其中重要一环,着重解决微服务面临的如下问题:
-
微服务通信性能
-
微服务运维和治理
-
遗留系统改造
-
配套DevOps
Java Chassis框架包含服务契约、编程模型、运行模型与通信模型四个部分,具备负载均衡、容错熔断、限流降级、调用链追踪等全面微服务治理能力。下面是总体的架构设计图:
为了支持软件工程实践, Java Chassis 的运行时架构是一个哑铃结构, 两端分别是"编程模型"和"通信模型",中间是"运行模型"。"编程模型"面向开发者写服务接口的习惯,"通信模型"面向微服务之间的高效编码和通信,"运行模型"基于"契约",提供一种服务无关的插拔机制,能够让开发者独立于业务实现开发治理功能,并且灵活的移除和增加功能,以及调整这些治理功能的处理顺序。"运行模型"的核心抽象接口是 Handler ,这个接口是一个异步的定义,Java Chassis 运行时模型采用纯异步的实现,让整个系统运行非常高效。
Java Chassis和Spring Cloud都实现了微服务架构模式,相比而言,Java Chassis 是一个更加紧凑的实现,开箱即用,而 Spring Cloud则是相对松散的实现,整合了大量的Netflix组件。
2.2 基于JavaAgent的非侵入微服务治理
JavaAgent是如何实现能服务治理能力的?其技术核心在于Java进程启动时,可以挂载JavaAgent来执行字节码的增强逻辑。JVM启动后,JavaAgent运行于Java应用之前,可以修改原应用的目标类和方法的字节码,做到非侵入地增强,原应用中被增强的类在JVM中实例化的对象都是已经被JavaAgent处理过的,因此在业务应用的代码执行时,我们的服务治理逻辑就能悄无声息地通过这种方法实现注入。
例如,我们可以增强服务发现过程,对这一过程中的某个关键函数进行拦截增强,插入一段路由筛选服务提供者实例的逻辑,根据服务实例的元数据和下发的路由规则选定对应的服务提供者,以此来完成灰度发布的功能。下图简化地介绍了字节码JavaAgent字节码增强的核心原理:
类似地,其他的服务治理能力的开发都可以通过这种方式,用户的Java业务应用无需修改,业务应用的开发者也无需理解其中的深层原理,只要把实现了服务治理功能的JavaAgent挂载上即可一键非侵入接入服务治理。
基于上述原理,华为云开源团队开发了无代理服务网格Sermant项目,目前已经在Github开源。Sermant专注于利用Java字节码增强技术为宿主应用程序提供服务治理功能,以解决大规模微服务场景中的服务治理问题。Sermant构建了非侵入、高性能、插件化核心框架,并在框架中提供了对接动态配置中心、事件上报、链路标记、心跳等服务治理通用能力。
当前开源仓库中提供的插件涵盖了服务注册、标签路由、流量控制、服务监控等常见的服务治理场景。Sermant的后端观测、动态配置中心、Agent等组件提供的一套完整的解决方案如下:
利用Sermant来进行微服务治理能够集合上文提到的各种服务架构的优势:
-
高性能:对比传统的服务治理边车,由于没有边车进程,因此有更高的性能和更低的资源损耗。
-
非侵入:对比微服务 SDK 架构架构,无需代码修改,升级云原生架构无需代码改造。
-
插件化架构:服务治理功能作为插件嵌入到JavaAgent内部,可动态部署,且内部充分类隔离,和业务代码无类冲突。
3、方案详解
结合以上两种治理模式的各自特点,便可设计出理想的全链路灰度发布方案。目前要实现全链路灰度,一般要考虑这些问题的处理:
-
在第一跳的地方(一般是网关),我们需要能选中各种类型的流量,把这部分流量染色,再路由到正确的目标。
-
除了第一跳,剩下调用链路中的各个微服务能够识别染色标,透传染色标,并路由到正确的目标。
-
能对异常情况进行妥善处理。
3.1 全链路灰度发布方案的具体流程
针对以上问题,我们有一套相对完善的全链路灰度发布方案,整体方案如下:
-
在前端部分,请求会统一携带流量标签参数发到网关上面。
-
网关会选中各种类型的流量,将这些流量根据需求分别染色,比如通过请求header进行标记染色。
-
网关会将染色后的流量转发到带有不同tag的后端微服务实例,tag可以由应用发布流水线注入到相应发布的微服务实例当中。
-
借助微服务实例上运行的SDK/JavaAgent,接收到应用网关流量的微服务实例会通过SDK/JavaAgent提供的标签路由能力将流量特征保留并转发到合适的下一跳微服务实例。
-
对于后续链路上的微服务实例,都可以通过微服务实例上面的SDK/Agent进行特征的传递。
3.2 SDK/JavaAgent如何助力全链路灰度发布?
由于在每个微服务实例都运行着SDK/JavaAgent,因此SDK/JavaAgent可以对每个实例进行细粒度的服务治理,包括限流,熔断,降级,标签路由等功能。在全链路灰度发布过程中,对于每条链路上的微服务实例,可以借助SDK/JavaAgent的标签路由能力实现流量特征的保留以及传递到下一跳微服务实例。进行标签路由的全流程如下:
3.3 SDK/JavaAgent如何搭配使用?
从上面的方案介绍可以知道无论是SDK还是JavaAgent的方式,其实都可以非常有效地助力全链路灰度发布方案的落地,那遇到具体业务场景对全链路灰度发布有诉求的时候,我们该如何去选择呢?
对于用户规划的新业务,用户一般会统一技术栈,因此直接使用微服务SDK框架自带的能力去实现全链路灰度发布会更加方便高效。
对于用户已有的业务,并且业务内部技术栈也不统一,这时候直接采用非侵入式的JavaAgent去做全链路灰度发布会极大程度地降低改造成本,因为业务代码本身不需要做变动,只需要在运行实例上挂载一个JavaAgent即可。当然目前的JavaAgent其实是基于Java 语言的,因此对于别的编程语言,还是得依靠微服务SDK框架来实现全链路灰度发布,但是考虑到目前Java属于使用量第一的编程语言,因此JavaAgent这种方式基本上还是能够覆盖绝大多数的场景。
总的来看,两种方式其实适用于不同的业务场景,它们之间可以相互补充,形成一整套完善的全链路灰度发布解决方案。
3.4 全链路灰度发布方案带来的优势
微服务应用通过全链路灰度发布的方式可以显著提高发布的效率以及稳定性,关键优势如下:
-
在开发测试过程中,客户可以根据需求在逻辑上划分出一套属于自己的服务链路,只需要关注自己设定的特征流量即可,这种模式可以为客户省去搭建系统中一些共用的模块时间以及节约环境资源。
-
在发布过程中,方便地将带有试点特征的流量引入到含有自己试点应用的链路环境当中。客户还可以根据需要把一部分生产流量引入到自己的新版本业务链路环境当中,完成新版本的验证。
4、总结
微服务治理架构的形态一直在演进,各种形态有其适用的场景和优缺点。对于企业用户和开发者来说,如何尽可能以较低的成本、较好的效率来解决微服务治理过程中的各个问题是永恒的目标。
以上我们主要对主流的微服务SDK架构和JavaAgent非侵入治理架构作了解析,对于Java应用场景来说,这两种治理模式可以在不影响性能的前提解决绝大多数场景的治理问题。
华为云在微服务治理方向的持续探索也孵化出了Spring Cloud Huawei、Java Chassis、Sermant等优秀的开源项目,并且将持续演进,丰富微服务治理领域的开源生态。
华为开发者空间,汇聚鸿蒙、昇腾、鲲鹏、GaussDB、欧拉等各项根技术的开发资源及工具,致力于为每位开发者提供一台云主机、一套开发工具及云上存储空间,让开发者基于华为根生态创新。点击链接,免费领取您的专属云主机