云原生微服务治理技术朝无代理架构的演进之路
Posted 华为云开发者联盟
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了云原生微服务治理技术朝无代理架构的演进之路相关的知识,希望对你有一定的参考价值。
摘要:本文基于对微服务治理技术从SOA, 微服务框架,到云原生架构的历史发展总结,提出了一种新的基于Javaagent技术的新一代无代理架构的服务治理技术,并介绍了其相关的代表性开源项目Sermant。
本文分享自华为云社区《云原生微服务治理技术朝无代理架构的演进之路》,作者: 杨奕|华为云技术规划专家。
微服务治理技术发展趋势
对于云原生的归纳,业界从来没有停止过演进。但是总体来讲,微服务和容器化基本上是两个永恒不变的话题。今天这篇文章重点来谈谈微服务架构的演进。
微服务这个词,比较公认的官方正式介绍来自 Martin Fowler 在2014年发布的 Microservices 一书。但是实际上,其解决的服务解耦的问题,最早可以追述到SOA (Service-Oriented Architecture,面向服务的架构)。下面这种图 (参考链接 ) 比较好的诠释了服务的演进历程。从最早的SOA,到本世纪10年代的微服务,到最后的云原生微服务架构的Servicemesh,核心都是为了解决在企业的复杂业务场景下,让各服务以解耦方式各自独立快速迭代。
图例1:服务架构的演进历程:SOA -> 微服务框架 -> 云原生
总体来讲,微服务的迭代发展到目前为止,分为三个阶段。
- SOA:该阶段针对政企场景的烟囱式架构,通过集中式中心网关方式,解决异构应用之间的快速集成问题。该阶段,服务治理功能集中在中心网关上,性能和可靠性上也都有较大问题。
- 微服务框架:主要针对大规模高并发场景,通过去中心网关、做厚客户端的方式,使得企业内部应用可快速解耦和横向扩容,以满足业务快速发展需求。该阶段,服务治理功能一般通过SDK,部署在业务程序上,辅以注册中心和配置中心进行服务管理。虽然性能和可靠性得到解决,但是服务治理逻辑和业务逻辑存在一定程度耦合,在应用生命周期迭代上存在一定问题。
- 云原生 Service Mesh:将更多的服务治理能力沉淀到云平台上,应用只关注业务逻辑,服务治理和应用彻底解耦,应用快速迭代得到解放。该阶段,服务治理功能以代理边车方式沉淀到容器内,应用时在运行时挂载边车即可,具体的服务治理控制逻辑由云平台(如图中 Kubernetes/Service Mesh)承接。
在以上架构图中,SOA不是本文重点。关于SOA到微服务的演进,感兴趣可以参考文章 《 SOA 和微服务的区别》 一文。本文以下章节重点介绍其他的 微服务框架 和 云原生 Service Mesh 这两个阶段的微服务治理架构特点。
微服务框架 架构
如前文所述,微服务的的名词比较正式被普及可归公于 Martin Fowler 在2014年撰写的 Microservices 一书。但是实际上,国内的微服务起源反而更早。比较出名的是是阿里早期的HSF和Dubbo。正如“ Dubbo 和 HSF 在阿里巴巴的实践:携手走向下一代云原生微服务 ”一文中所述,阿里最早在2008年就开始了微服务方面的实际尝试,虽然可能在当时,其团队并未真正意识到自己开发的其实是下一代微服务架构。
”Dubbo项目诞生于2008年,起初只在一个阿里内部的系统使用;2011年,阿里B2B决定将整个项目开源,仅用了一年时间就收获了来自不同行业的大批用户;2014年,由于内部团队调整,Dubbo暂停更新;2017年9月,Dubbo 3重启开源,在2019年5月由Apache孵化毕业,成为第二个由阿里巴巴捐献至Apache毕业的项目。“
文摘1:Dubbo阿里内部的演进历史
在海外,虽然RPC框架类组件尘出不穷,但是真正将服务治理纳入一体,而且几乎成为事实标准的,当属 Spring Cloud 。虽然项目是2016年才开始正式发布,但论流行程度,不光在世界范围论堪称一哥,在中国国内,风头也几乎盖过Dubbo。
图例2:Dubbo 和 SpringCloud 在国内的搜索热度。蓝色是Dubbo,红色是SpringCloud
Dubbo和SpringCloud的具体发展历程,这里不多做介绍,大家可以翻翻其他相关介绍。这里重点突出一个两套框架的一个共同特点,无论是Dubbo,以及后来的SpringCloud,都不光是一套RPC框架。其除了方便研发直接基于RPC模式开发微服务架构的业务以外,自身还有很多扩展点,方便服务治理开发人员以独立Jar包方式进行服务治理功能的单独开发。比如:Dubbo比较耳熟能详的是自身的基于SPI扩展点机制来实现服务治理;而SpringCloud则是通过SpringBoot机制,通过开发者开发starter包来实现服务治理。两者基本都能做到服务治理功能对业务代码解耦。例如SpringCloud,对于引入新的服务治理功能,很多时候对于开发者来说只需要引入一个starter的pom依赖。不过这也引入一个问题,任何服务治理的功能升级,虽然对于业务代码来说只是更新配置文件,但是毕竟还是动了业务代码,这也给服务治理功能的升级带来潜在阻力。随着业务规模增长,该问题也会被指数级放大。
基于以上问题,需要指出一个极其重要的但是容易被忽略大家忽略的事实,就是微服务治理能否在一个大厂内能否大规模铺开使用,很重要的因素是服务治理能否和业务在软件开发和发布上解耦。阿里之所以微服务内部推广和演进比较顺利,笔者认为很大原因是阿里内部采用的微服务框架HSF很早集成了Pandora 容器这项技术。这个不起眼的技术,其实起了一个至关重要的作用:服务治理功能和业务功能在代码上彻底解耦,治理功能的jar包可以在不改变业务代码情况下单独发布;且在此基础上实现了治理功能和业务功能类隔离,防止类冲突。
图例3:据阿里巴巴微服务实践一文介绍,通过Pandora,业务和中间件逻辑发布得到完全解耦。
阿里内部的Pandora容器技术,虽然在外曝光度不高。但是在阿里的服务治理领域起到了至关重要的作用。正是因为有了Pandora,阿里的业务开发人员才能做到 "治理功能万千重,我自岿然不动"。阿里历史上每年双11前几个月,在业务近乎无感情况下,微服务框架批量搞几次大版本升级,也基本就能满足每年大促的服务治理需求。
而其他如采用SpringCloud技术栈的大厂,在没有类似Pandora容器的隔离技术情况下,随着业务规模增长,服务治理能力的演进将越来越痛苦。每发布一个重要版本或重要补丁,服务治理团队就需要思考如何去说服上千个业务方进行SDK升级,就成了一件让人非常头疼的事。因此,服务治理功能如何和业务功能在架构上如何解耦,就成了后来微服务治理一个刚需。这也是后续Istio等边车服务治理方案兴起的一大原因。
云原生 Proxy (边车代理) 服务治理 架构
在CloudNative时代的服务治理架构中,Service-mesh因为其对应用的无侵入性,成为了云原生服务治理的一个经典流派。而在Service-mesh流派中,Istio又是其中一个代表作。Istio的兴起,其实核心是因为解决了两个问题。
- 多语言架构下的服务治理功能统一。无论是java、go、c++等语言,只要通讯协议一致,理论上都可以通过边车进程来进行服务治理。
- 通过代理进程方式,实现治理功能对业务代码的非侵入,架构上和业务充分解耦。
图例4:Istio社区中火了5年的书店demo程序,集 python、ruby、node.js、java 等各类开发语言
关于Istio的功能和架构介绍,网上文章多如牛毛,本文就不赘诉了。但是这里核心讲下Istio在实践中遇到的几个问题。
- 非侵入的兼容性。本来非侵入是istio的主打优势,但是社区版的istio有个核心问题,就是是基于gRPC协议构建的。这就使得istio在国内落地时,面对国内dubbo治理框架是个事实标准之一的情况,显得有点水土不服。这在大多数云厂商的istio商业版中对Dubbo的各种“蹩脚”支持可见一斑。虽然dubbo社区也在主动朝3.0开始演进,兼容gRPC协议,但是其成熟度仍尚存很长距离。
- 服务治理,功能也很丰富,但是有缺陷。在长长的xDS协议的功能列表中,从服务注册发现,到限流降级,到馄饨工程,可谓玲珑满面。但是基于Proxy边车的服务治理方案中,一大硬伤是Proxy边车进程毕竟是个和业务无关的进程,本身无法侵入到业务进程,因此任何需要在业务进程透传标识的场景全部都不支持。典型比如分布式链路Tracing ID的透传,还比如一些全链路灰度发布的路由标的透传,等。以上两个问题,都可参考 Proxyless Service Mesh 在百度的实践与思考 一文中有详细阐述。
图例5:百度在 Proxy Service Mesh 实践中因为边车无法侵入进程,所遇到的问题
- 架构上,由于采用了单独进程,无论是性能和运维上,和SDK流派相比还是有差距。一方面,在各种基准性能测试中,额外的响应时间稳定增加1.7ms以上,参见istio Performance and Scalability 。另外一方面,在落地时,sidecar conatiner的规格设置也是个令人头疼的问题:vcpu和内存设得小了,性能不够;设得大了,浪费资源;按应用各自性能特点设置,又造成额外管理成本。
图例6:Istio社区中最新发布的性能测试。测试现实,增加边车,性能损耗至少增加1.5ms
基于以上各种原因,原生的istio的落地实践中,都多少处于叫好不叫座的尴尬境界。接下来就Proxy边车治理方案的问题,说说为啥最近Proxyless边车治理方案开始逐渐异军突起。
云原生 Proxyless (无代理) 服务治理 架构
Proxyless服务治理,原本出处是 gRPC Proxyless Service Mesh . 原文本意是基于gRPC,结合xDS协议,做了一个服务治理框架。gRPC Proxyless Service Mesh的提出,笔者认为,本质上是因为proxy治理架构的各种各样的问题,导致istio团队重新思考适基于现成的xDS协议,把服务治理的大部分功能重新做到了框架内部。从架构上看起来gRPC Proxyless Service Mesh更像是走了一次微服务框架流派的历史倒车,把业务和治理框架耦合在了一起。
图例7:左边是 gRPC Proxyless Service Mesh 最新发表的架构图,右侧是 Dubbo 几乎10年前的架构图,是不是何其相似
那么有没有一种 Proxyless 边车方案,既能具备边车方案的各种解耦优点,又能一定程度上克服Proxy带来的问题呢?答案是 Javaagent。
Javaagent的字节码增强技术很早就有。真正发挥商业价值的地方其实是在2015年前后的所谓APM元年,其被大量使用在APM领域。但是这个javaagent这个技术在服务治理领域火起来的,也是最近两年的事。这里面主要发生两件值得一提的事:
- Apache Skywalking 这个开源APM工具,作为国内Apache的顶级项目,把javaagent技术在国内好好普及了一把。最终结果是各个互联网中小厂商基本上java进程上都挂了一个skywalking javaagent的同时,该技术都普遍接受。 (笔者见过不少政企和互联网厂商,甚至挂了一个skywalking javaagent的同时,又挂了一个基于skywalking修改的javaagent,其使用场景涵盖各种服务治理场景。)
- 基于对javaagent技术的接受基础上,以Java技术栈为主的各类互联网大厂和云厂商开始内外大量使用Javaagent技术做服务治理和相关商业化产品。总体上讲,之前业界对javaagent做服务治理基本上都持观望态度。现在基本上也不质疑了,大家现在思考的问题都变成了怎么把javaagent在服务治理领域如何发挥到极致。
为啥javaagent技术这么火?这是因为其相比传统SDK和Servicemesh技术:
- 非侵入架构:这点和Sidecar架构类似,治理能力开箱即用,业务方代码务虚改造,上车成本极低。而且相比传统边车技术,没有额外进程,运行态和开发态的差异进一步降低。
- 治理功能和业务代码升级解耦:相比SDK升级动辄需要去各业务方推广,非侵入这块这块能力确实比SDK实际体验好太多。试想一下,治理功能快速迭代的同时,业务方只需晚上滚动重启一下即可获得新的治理功能,这对服务治理团队和业务团队都是一种生产力的解放。
- 相比传统边车方案,性能更好,资源消耗更低 :毕竟传统边车方案动辄2ms以上的延时增加,以及额外的进程资源开销,对业务都是不小的负担。而javaagent这块由于采用和SDK雷同的AOP服务治理方式,性能几乎和SDK持平。
- 治理场景多样:实践证明,在场景上,Javaagent > SDK > 边车架构。Javaagent的场景比边车方案多,这个好理解,毕竟Javaagent可以注入到用户进程中,完成很多流量标透传的场景,这块是边车架构无法做到的。但是Javaagent为何场景比SDK方案还要多?这是因为一般如Dubbo, SpringCloud等治理方案,其默认需要对应的RPC函数提供相应的函数埋点。但是很多服务治理场景,如流量录制回放,对应的一些远程调用,如Redis调用,本身并不提供函数埋点,因此通过SDK来拦截流量进行录制和回访就无从谈起。而基于Javaagent的字节码增强技术则没有这个限制。
图例8:(原创首发)Javaagent对其他服务治理对比的优势
当然,Javaagent的服务治理技术也并非银弹。
- Javaagent最大的问题是服务治理场景只能用于Java。如果您所在公司,主流开发预言是非Java类,那么还是放弃吧。但是如果您所在公司,主流开发语言是java, 但是有很多长尾应用语言是其他语种怎么办?这里开发者可以考虑 传统边车 + javaagent 方案,javaagent负责主流的Java语言微服务的服务治理,而传统边车方案负责其他多语言的服务治理。至于两者的服务治理打通,业界也有很多方案,如Javaagent同时对接基本的xDS协议,也可以完成两者服务的打通。
- 这里也稍微提个不大不小的问题,就是当多个javaagent对同一个类进行增强的时候,有时候会产生增强冲突的异常。其实这块很多场景是因为各类javaagent开发不规范的原因,是完全可以避免的。相关详细的问题就不展开了,大家如果敢兴趣的话,可以去看下相关文章 记一次多个 JavaAgent 同时使用的 类增强 冲突问题及分析 。这里就摘出要文章核心摘要:
"严格遵守字节码增强的使用要求和限制。无论是Byte Buddy、Javassist还是ASM,底层实现都离不开JDK1.5之后引入的Instrumentation接口。既然官方接口的设计理念是reTransformClasses()增强类时不能新增、删除或者重命名字段和方法,不能更改方法的签名,也不能更改类的继承关系,那作为JavaAgent的框架开发者,应该不要做出超越上述限制的设计,否则极易导致JavaAgent之间的兼容性问题出现。不仅仅是这个接口,JavaAgent框架的开发者也需要遵循所有的字节码增强的底层接口的设计理念,毕竟有规则才有秩序。"
文摘2:"记一次多个JavaAgent同时使用的类增强冲突问题及分析" 文中对避免Javaagent冲突的建议。
华为云的sermant开源项目
用javaagent做服务治理很想,但是实际上手怎么搞? 华为云在早期接触的很多客户场景中,发现很多架构团队都是拿已有的开源的 javaagent 相关的项目上手魔改做自己的服务治理能力。但是做着做着很快发现了几个问题。
- 我们目标的服务治理功能很多,但是一般开源项目如pinpoint, skywalking等增强的点就那么一个,比如如果在服务调用增强点上实施了链路追踪逻辑以后,再加其他比如限流降级功能,就需要在Plugin中写很多限流降级逻辑,这些代码逻辑会和已有的开源项目的原生治理逻辑纠缠不清。
- 很多服务治理功能本身逻辑可能比较重,有其自身的三方依赖依赖库。但是世面上已有的Javaagent,并不支持针对组件级别的类隔离机制。
- 服务治理场景有很多通用逻辑,除了方便快速的对特定函数接口做增强以外,还包括可替换的实时配置中心,基于RPC的Tag透传,通用的Metrics上报机制。能否把这些能力都沉淀出来,以SDK API方式暴露给开发者直接使用,这样可以极大提高服务治理的开发效率。
以上几个原因,促使我们思考是否应该做一个新的javaagent服务治理项目,来解决以上问题。这就是sermant项目由来。我们希望通过Sermant项目,
- 服务治理功能以插件形式装载到javaagent中,不同插件间可以做到对同一个业务函数增强点进行不同增强,且互不冲突。最终所有服务治理统一到一个javaagent中,降低资源损耗。。
- 服务治理插件之间同时需要做到类隔离,以降低不通版本的三方库依赖造成的类加载冲突风险。
- javaagent本身能提供一层厚度适中的framework能力,帮助插件快速开发服务治理能力。项目之初,我们提出至少三个目标需要尝试实现:
- 实时配置中心抽象。无论用ZooKeeper, Nacos, 还是Servicecomb,都不影响插件使用统一framework提供的实时配置的能力。以此做到实时配置连接收敛。
- payload数据透传能力。我们希望framework提供SDK,无论是tracing id透传,还是全链路灰度标透传,都能基于数据透传能力快速开发治理功能。
- 监控能力。按照规范开发的插件最后都能在后端平台上对所有的javaagent和其加载的plugin做统一监控。
图例9:Sermant 的框架、插件架构
路走对了,就不怕远。到今天,在公司内外生态伙伴的贡献下,Sermant名下已有各类服务治理插件已多达数十种,场景覆盖包括 服务注册发现改造、服务契约查询、服务血缘关系发现、服务双注册、配置治理、流量录制回放、限流降级、优雅上下线、全流量标签路由、同机房调用优先、故障注入、性能监控、等等。我们同时将规划更多的框架层能力,以辅助增强Sermant服务治理总体能力,进一步降低插件开发难度。这包括:插件动态插拔能力,应用无需重启应用,即可在线升级服务治理功能;插件增强顺序动态调配,对于同一个函数增强点,不同插件可以按需调整顺序,如性能监控插件在限流降级插件之前生效,以保证服务治理逻辑正确;等等。
如果您对以上细节感兴趣,我们诚挚欢迎你来社区使用Sermant。
图例10:Sermant的社区介绍
欢迎使用Sermant
Sermant社区当前快速成长中,当前开源代码仓地址:GitHub - huaweicloud/Sermant: Sermant, a proxyless service mesh solution based on Javaagent.
Sermant目前部分服务治理功能已在华为云产品中提供商业化服务,华为云用户可在 微服务引擎 CSE 中使用相关功能: 微服务引擎_CSE_微服务_应用管理与运维-华为云
政企客户亦可在最新的HCS产品中使用相关Sermant功能。该功能在ROMA-Factory已支持部分场景的PoC。
以上是关于云原生微服务治理技术朝无代理架构的演进之路的主要内容,如果未能解决你的问题,请参考以下文章