开源微服务框架 Apache ServiceComb 的前身为华为云的 微服务引擎 CSE (Cloud Service Engine) 云服务, ServiceComb 的早期版本和多数第一批作微服务或分布式框架先贤同样,为了追求高性能,作过很是多如 改善编码效率 和改进通讯协议等尝试。然而,随着业务规模的递增,需求也逐渐呈现多样化,单方面经过传统手段追求高性能致使在面对多样化需求时遇到了各类挑战,遗留系统的通讯、接入各类不一样的终端、协议健壮性、防攻击等各类挑战迎面而来。html
Apache ServiceComb,愿景是帮助企业快速构建云原生应用,经过一系列解决方案帮助用户快速开发微服务应用的同时实现对这些微服务应用的高效运维管理,保持中立性以免厂商LockIn成为了关键任务。对于此, Apache ServiceComb 须要有友好的机制可以对接各微服务主流技术栈技术 或 开发框架。java
在系列挑战的驱动下, Aapche ServiceComb 设计团队逐步造成了 “全面开放,使用标准协议,架构易于拆分和扩展,对开发人员友好,能够与业界其余主流框架互通集成” 的共识, 本文将着重分享这些共识是如何体如今Apache ServiceComb 的设计中的。git
开放和标准应用到设计的不一样的层面。一方面是链接组织和开发人员,一方面是链接异构系统。组织和开发人员的复杂性来源于技能的多样性,你们使用不一样的开发语言,同一种开发语言存在多样的开发习惯;系统的多样性来源于系统之间的通讯协议,为了实现与异构系统的通讯,必须具有良好的适配不一样通讯协议的能力。github
每位技术人员都或多或少拥有本身的 Coding 习惯或爱好的技术, 使用我的熟练的方式从事技术工做每每更加高效和温馨。spring
开源微服务框架 Apache ServiceComb 的早期版本实现了 gRPC 协议,然而在项目演进过程当中咱们发现大量技术人员并不熟悉书写 IDL , 对 IDL 具体支持哪些特性也不清楚。 大多数状况下,用户每碰到一个场景就须要翻开协议规范看一遍, 而 IDL 缺乏配套的编辑或语法检查等工具也致使了开发效率的下降。shell
因而 Apache ServiceComb 设计团队开始思考是否有方法可以在确保保持用户开发习惯的前提下支持 gRPC 。数据库
设计团队结合本身的 Java 编程史,分析当下主流框架,并听取社区用户的反馈找到了一些共性:apache
Apache ServiceComb 很快在社区设计层面达成了一致,经过缺省支持以上共性来拥抱90%的开发者, 让大多数的 Java 开发者们可以快速开始工做。编程
除以上共识外,Apache ServiceComb 还额外作了进一步的优化,以保证不一样编程风格的兼容性,使用户或开发者倍感灵活及温馨。json
在下面的例子中,展现了 Provider和Consumer 代码的各类实现,在同一个微服务中,这些编程方式能够同时出现;同一段 Consumer 代码中能够访问各类不一样的编程风格的 Provider 实现。
RPC 方式的 Provider
@RpcSchema(schemaId="hello") public class HelloImpl implements Hello{ @Override public String sayHi(String name){ return"Hello"+name; } @Override public String sayHello(Person person){ return"Helloperson"+person.getName(); } }
JAX-RS 方式的 Provider
代码片断来自于 Apache ServiceComb JAX-RS sample
@RestSchema(schemaId="jaxrsHello") @Path("/jaxrshello") @Produces(MediaType.APPLICATION_JSON) public class JaxrsHelloImpl implements Hello{ @Path("/sayhi") @POST @Override public String sayHi(String name){ return"Hello"+name; } @Path("/sayhello") @POST @Override public String sayHello(Person person){ return"Helloperson"+person.getName(); } }
Spring MVC 方式的 Provider
代码片断来自于 Apache ServiceComb Spring MVC sample
@RestSchema(schemaId="springmvcHello") @RequestMapping(path="/springmvchello",produces=MediaType.APPLICATION_JSON) public class SpringmvcHelloImpl implements Hello{ @Override @RequestMapping(path="/sayhi",method=RequestMethod.POST) public String sayHi(@RequestParam(name="name")String name){ return"Hello"+name; } @Override @RequestMapping(path="/sayhello",method=RequestMethod.POST) public String sayHello(@RequestBody Person person){ return"Helloperson"+person.getName(); } }
RPC 方式访问上述三种服务的 Consumer
@RpcReference(microserviceName="hello",schemaId="hello") private Hello hello; System.out.println(hello.sayHi("JavaChassis"));
以上代码片断所有出自 Apache ServiceComb Samples,有兴趣者可阅读了解或贡献更多的智慧。
直至此处,或许开发者会产生疑问,既然 Consumer 能够经过一致的 API 方式访问不一样的Provider,为什么还须要额外的 JAX-RS 和 Spring MVC 标签?
缘由是,这里的设计依据是 Apache ServiceComb的 Consumer考虑的不只限于 类SDK 的 Consumer,还有浏览器等非 SDK 类的 Consumer,浏览器的 Conumer 识别的是 Http 形式的消息。 经过定义和使用这些标签, 咱们能够更加精细的指定浏览器如何访问后台接口。 相似于 Web Service 的 WSDL 描述语言, Apache ServiceComb 称之为服务契约。
服务的契约会在服务运行时经过代码定义自动生成,并注册到服务中心。契约也可在运行时用于独立的服务治理逻辑开发,生成 Consumer 代码。此外,也可做为 API 文档对外发布,供非 SDK 的 Consumer 参考。
微服务强调服务自治,对外体现的功能所有以松耦合的接口方式提供,而且只能以通讯的方式实现相互访问。此原则给团队协做带来了根本性的变革。
微服务的一个开发团队一般由5~6我的的全功能团队组成,端到端的完成 场景需求分析、架构功能设计、开发和运维,团队组织结构和业务系统的架构相匹配。团队创建后的核心问题就是团队之间如何进行高效的协做沟通,以决定不一样微服务之间的协做通讯。
Apache ServiceComb 经过确保让开发人员保持本身的固有编程习惯及设计上的松耦合灵活性,让微服务团队之间能够进行高效协做,以免在不一样的微服务团队讨论编程风格受限于历史旧帐而浪费宝贵的精力和时间。
在 RPC 的世界里,有 Corda IDL,WSDL,ProtoBuffer 等能够参考的优秀实践, REST 风格的接口让团队之间能够经过 HTTP 语义进行沟通,但却不能像 IDL 同样描述跨语言的数据格式。Open API 的出现很好地解决了这个问题。
Open API 首先是一个不断发展壮大中的开放的标准。Open API 能兼顾 RPC 、REST 等不一样的开发方式,而且吸取了大量的跨语言经验,可以在不一样的语言之间进行解析。
对于 Java 开发者,下面的代码片断是平常所打交道的:
User: type:object properties: age: type:integer
若是开发人员有丰富的跨语言开发经验,能够看出 Swagger 在解决跨语言编程方面API定义冲突的努力, 如 Swagger 经过 format 来定义数据类型的存储格式,以解决不一样的语言在数据类型表示上的差别:
User: type:object properties: age: type:integer format:int32
开源微服务框架 Apache SerivceComb 既遵循常规开发规范也特别关注开发效率。开发者能够先写接口定义后写代码, 也可直接经过本身熟悉的方式编写写代码, 两种方式都会生成 服务契约(Open API 描述文件),而且将内容注册到服务中心。使用者能够从服务中心下载相关的服务契约进行开发。 Apache ServiceComb 的各类治理结构也是基于契约的,可让开发者独立于业务实现对系统进行统一的管控治理。
开源微服务框架 Apache ServiceComb 早期版本提供了gRPC、REST、SOAP等多种协议,当前主要支持 REST 和Highway 高性能私有 RPC 两种协议。
gRPC 相对于 REST 的最显著优势就是性能,它采用长链接、高效的二进制序列化方式,提供多种语言支持, 提供了 IDL 语言约束开发者按照标准的方式工做, 一切看起来是那么的完美。
实际上,Apache ServiceComb 的第一轮重构,首选也是 gRPC 。历史第一次在华为云 微服务引擎 CSE 上线之后,面对了来自网关压力挑战。
网关做为业务接入端,必须高效的管理链接和保证公平,长链接容易致使拒绝服务。gRPC 程序开发完成后,开发人员没法利用系统提供的各类工具进行测试,网络包分析也变得困难,给生产环境上的开发联调形成了困难。随着业务规模的增加,gRPC 面临了诸如“其余三方系统如何与之直接通讯? 如何跨网关与它间接通讯?”等更严峻的挑战。
解决这些问题,将须要咱们扩展和改善老的协议和程序,提供 gRPC 客户端支持,开发者需自行提供一个额外的表示层用于业务接口的逻辑转换,形成大量的重复代码。同时因为 gRPC 依赖于接口定义,并根据定义生成代码,一套代码只能跑在 gRPC 协议上,若是用户但愿业务应用可使用如 REST等其余更加灵活的方式, 就需自行从新实现一套新的代码逻辑。据以上的血泪史, gRPC 最终被 Apache ServiceComb 设计团队定义为只能在中小型系统内部之间使用,并经过协议网关与外部系统进行通讯。并实现了 高性能私有协议 Highway 做为RPC首选默认协议。
REST 相较 gRPC ,最大的痛点是性能。
多数技术人员脑海里一个不成文的根深蒂固的观点:”二进制编码效率远高于文本协议,采用二进制编码的系统的性能远高于采用文本的 HTTP ”。该观点甚至会让多数决策止步于理论,多数人甚至不肯尝试去优化 REST。
可喜的是 开源微服务框架 Apache ServiceComb 迈出了重构 REST 底层通讯实现的第一步,基于 Netty 的异步框架来替换 Tomcat 实现,实践的效果大大超出预期,部分基准测试数据结果显示比 gRPC 还好, gRPC最终输在了HTTP2 协议上的额外报文。
优化后的 REST 和业界开源的其余基于二进制的 RPC 实现的性能基本持平。在一个简单的提供数据库查询的代码逻辑中,优化后的REST通讯框架处理时间,占比总处理时间远小于千分之一,这意味着再继续在框架层面进行大量优化也抵不上业务应用层面最简单的一个操做带来的消耗,Apache ServiceComb对 REST 的优化已经知足要求,最终也选择了 REST 做为首选和缺省协议(HTTP + json)。
咱们并无就此止步。
须要迁移到 华为云 微服务引擎 CSE 的业务日益增加,部分历史遗留系统也需进行对接。通讯协议对应不一样的开发者接口,往往增长通讯协议,则须要对业务代码进行大量的重复构建,形成大量无谓消耗。这是当时的华为云化转型以及当下不少云化转型企业或者云原生企业必将面临的痛点。
因而乎,通讯协议层被剥离了出来,和业务代码隔离,系统运行基于契约,开源微服务框架 Apache ServiceComb 实现通讯协议扩展机制。通讯协议扩展机制,帮助用户解决与 gRPC 框架、自定义二进制框架等许多遗留系统的对接通讯问题。
在 Apache ServiceComb 框架中,切换协议很是简单,不须要修改一行业务代码。多个协议共存也是容许的。
ServiceComb: rest: address:0.0.0.0:8084 highway: address:0.0.0.0:8094
扩展性是系统进一步发展的基石。开源微服务框架 Apache ServiceComb 创造性地将扩展性拓展到 Provider 和 Consumer,让开发者拥有一致的开发体验。
链接开发者和通讯协议层面已经让系统具有了很大的扩展性。微服务化给系统解耦、团队自治带来了很大的灵活性,加快了开发生产效率,但同时带来了服务管控的复杂性,在微服务领域,不得不考虑雪崩效应、调用跟踪、性能监控与分析等实际管控治理问题。
基于服务契约,开源微服务框架 Apache ServiceComb 提供了动态插拔扩展的处理链机制,而且为这些管控治理能力提供了默认实现,用户能够灵活插拔这些处理模块,或调整它们的顺序以应对不一样的处理场景,或自行实现以增长新的处理模块。Provider 和 Consumer 都会通过该处理链,这给客户端治理功能开发带来了极大的便利性。Apache ServiceComb 的运行结构以下:
图1 Apache ServiceComb 运行时架构
Apache ServiceComb 同时支持同步和异步两种编程接口,并在通讯实现上采用了纯异步方式,对于运行模型的扩展,也是基于异步回调接口的。该方式提供了比同步模式(好比 Filter)更加优雅灵活的扩展方式。
在Apache ServiceComb 结构中,几个核心的扩展机制均在 core 模块 进行定义:
Provider 编程模型的扩展,经过实现这个接口,能够适配不一样的 Provider编 程风格;默认支持 RPC、Spring MVC 和 JAX-RS 三种风格。
Consumer 编程模型的扩展,经过实现这个接口,能够适配不一样的 Consumer 编程风格;默认支持 RPC和RestTemplate 两种风格。RestTemplate 是 Spring MVC 提供的 REST 编程接口,能够在服务层解除接口依赖,只依赖数据模型。
处理链的接口,经过扩展该接口,能够在处理过程当中插入任意的逻辑。默认已经支持负载均衡、错误注入、流量控制和调用链跟踪等多个处理链。开发者能够针对 Consumer 和 Provider 定义不一样的处理链,而且为访问不一样的微服务定制不一样的处理链。
通讯协议扩展,默认支持REST over Vertx、Rest over Servlet、Highway协议。
Invocation
中立的对象。全部的运行模型都面向这个中立的对象进行编程,当定义好服务接口后,对服务的治理和服务业务逻辑的开发可并行进行。在编程模型和通讯模型里面,也面向这个对象进行编解码。
Apache ServiceComb Java-chassis 预留了对接外部系统的接口,以让开发者或用户能够灵活快速切换使用第三方提供的服务,这里所指的外部系统包括但不限于:服务注册发现的服务中心、配置管控和治理的配置中心、运行监控和运维的治理中心等。
下图展现了不一样的开发框架支持和运行的第三方系统状况,这些基础服务都给开发者预留了能够进行支持接入的接口。
图2 Apache ServiceComb 外部扩展接入
重要的扩展:
实现这个接口以对接不一样的注册服务。
ConfigCenterConfigurationSource
实现这个接口以对接不一样的配置服务。
此外,ServiceComb还提供了对接Zipkin、Servo等开源系统的功能,这些能够从github代码中查找到对应的例子。
一个完整的业务系统不是使用RPC框架就算完成了,它们还须要其余的计算资源。对于通常的业务系统都须要访问数据库,或者基于 J2EE 的设施进行工做。
开源微服务框架 Apache ServiceComb 能够以轻量级的方式运行,也可集成到其余系统框架。下面的示意图说明了 Apache ServiceComb 的一些工做环境。
图3 Apache ServiceComb 运行环境集成
因为 Apache ServiceComb 使用了Spring,所以自然继承了Spring的原有优点,可和不少通用的组件很好的集成,如 mybatis、JPA 等。各类集成方式,均可以从ServiceComb官网或者ServiceComb 示例库找到对应的例子。
开源微服务框架 Apache ServiceComb 的主体代码是由华为云微服务引擎捐赠给 Apache 软件基金会的,愿景是帮助企业快速构建云原生应用,经过一系列解决方案帮助用户快速开发微服务应用的同时实现对这些微服务应用的高效运维管理。本次设计团队将开放性设计部分细节点点滴滴分享出来也是为了可以对解放微服务开发者和用户能有所帮助。
当前愈来愈多的贡献者已加入到 社区行列,Apache ServiceComb 会和这些志愿者们一块儿一如既往坚持这个理念,争取给业界带来更多好的技术和分享。也指望有更多有志者一块儿行动。
参考文献
[1] 开源微服务框架 Apache ServiceComb 官网
http://servicecomb.incubator.apache.org/cn/
[2] 开源微服务框架 Apache ServiceComb 代码
https://github.com/apache/incubator-servicecomb-java-chassis
https://github.com/apache/incubator-servicecomb-service-center
https://github.com/apache/incubator-servicecomb-saga
[3] 华为云微服务引擎 CSE(Cloud Service Engine)
入口 https://www.huaweicloud.com/product/cse.html
资料 http://support.huaweicloud.com/cse_dld/index.html
[4] Apahce ServiceComb OSC 码云地址