4月26日,在2018云栖大会南京峰会上,阿里巴巴研究员林昊正式发布了第四届阿里中间件性能挑战赛。挑战赛以开源项目为背景,核心技术为Dubbo和RocketMQ,目的是通过大赛向技术爱好者们传达开源精神。
林昊表示,“对于开发人员来讲,很多工作都使用了开源的东西,开源对整个世界也产生了非常大的影响。对阿里来讲也同样,阿里巴巴也同样使用了开源的软件,在这个过程中,我们结合阿里的场景,对整个开源的产品进行了很多改进,也不断回馈到社区。”
从2017年起,阿里巴巴开源的步伐正在加速。
2017年9月,RocketMQ在Apache毕业,成为了Apache顶级项目(TLP)。10月份,OpenMessaging发布,分布式消息中间件、流处理领域的应用开发标准,目前已正式入驻Linux基金会,这也是国内首个在全球范围内发起的分布式消息领域国际标准。11月,社区突然热闹起来,Dubbo快速更新,引发了非常广泛的关注。今年,Dubbo进入了Apache,目前正在孵化期。
Apache基金会联合创始人Jim Jagielski表示,Apache顶级项目RocketMQ是一个极其强大且具有变革性的软件项目,众多公司都是它的深度用户。Dubbo目前正在Apache软件基金会内孵化,具有巨大的潜力。
中间件性能挑战赛至今已经是第四届,这是首次把赛题设置在开源背景上,让更多技术开发者参与其中。
下面,我们针对本次赛题做个详细的深度解析。
了解 Dubbo 的朋友们都知道,Dubbo不仅仅是一款高性能的 RPC 通讯框架,更是一套完整的微服务解决方案——服务注册与发现、负载均衡、服务治理等,这些都是我们耳熟能详的能力。但是 Dubbo 也有着天然的不足,初赛的题目便由此而来。
一、初衷
Dubbo 一直致力于为 Java 应用提供高效、稳定和可用于生产环境的 RPC 通讯能力,但比起 gRPC 和 Spring Cloud,Dubbo 的跨语言能力是一大弱点。在不使用 RESTful 接口的情况下,用户很难将 Dubbo 与其它语言实现的系统对接起来。因此本次比赛将打破语言的藩篱,参赛团队可以尽情选取你最中意的技术,主流的也好,非主流的也罢——We don't care——让 Dubbo 在多语言的方向上迈出第一步。
提到 Dubbo 就不能不说微服务,而言及微服务就一定有 Service Mesh 的一席之地。
传统的微服务向我们展现了服务化的未来蓝图,也提供了诸多方法论和最佳实践指导我们完成架构的变革。但是显然实施过微服务的朋友们都一定清楚,这是一个异常复杂且充满了不确定性的改造过程——将单体系统剥离、引入服务化组件(如果 Dubbo 不是你的第一选择,你更有理由关注本次比赛了)、将内部调用转化为远程调用、解决因为调用远程化和分布化而带来的各种次生问题(网络问题、安全问题、状态管理问题、一致性问题等等)。在拥有复杂系统的组织内部,这样的改造不亚于梦魇。想想看要把各种不标准的 Java 应用、PHP 应用、Python 应用等全部打通且服务化,不是你在做梦,就是客户在做梦。
可这样的梦境就是我们要面对的现实,而Service Mesh 无疑是梦境架构师递给你的一根救命稻草。简言之,Service Mesh 另辟蹊径,在不深入服务内部的情况下,以 Agent 的形式与服务共生,并由 Agent 提供一切微服务所需要的能力。正如其名称所揭示的那样,Service Mesh 就如同一张网格,将各种服务网罗在其下。这次初赛的题目就是希望参赛选手编写一个高性能的 Agent 实现,让 Dubbo 融入 Service Mesh 这张大网。
二、场景
在本次比赛中,并不需要实现一套完整的Service Mesh 框架,因此我们对场景进行了限定。得益于 Docker 提供的容器化能力,让我们可以很方便地模拟出想要的场景。如图所示,整个场景由 5 个 Docker 实例组成(蓝色的方框),分别运行了 etcd、Consumer、Provider 服务(绿色的方框)和 Agent 代理(红色的圆圈)。
Provider 是服务提供者,Consumer是服务消费者,Consumer 消费 Provider 提供的服务。Agent 是 Consumer 和 Provider 服务的代理,每个 Consumer 或 Provider 都会伴随一个共生的 Agent。etcd 是注册表服务,用来记录服务注册信息。从图中可以看出,Consumer 与 Provider 之间的通讯并不是直接进行的,而是经过了 Agent 的中转。这看似多余的一环,却在 Service Mesh 的架构中扮演着举足轻重的角色。
首先,Agent 需要实现负载均衡的能力。在图中,蓝色方框的大小代表了容器的性能。我们可以发现,一个 Consumer 实例的性能是三个 Provider 实例性能的总和,而且三个 Provider 的性能又是以 1:2:3 的比例分配的。假如整个系统性能是 60,则 Consumer 占 30,Provider(small) 占 5,Provider(medium) 占 10,Provider(large) 占 15。因此任何一个 Provider 服务的性能都比 Consumer 要小,Agent 必须做到负载均衡才能保证任意一个 Provider 服务不会被压垮。
第二,Agent 需要实现服务注册与发现的能力。服务注册与发现是微服务的核心能力,Consumer Agent 具体要访问哪一个 Provider Agent 不是在配置文件中写死的,而是动态发现的。简单来说,当Agent 启动的时候,需要将自己的信息写入 etcd 注册表,在服务调用发生的时候,再从 etcd 中读取相关的注册信息,这个过程就是最简单的服务注册与发现。
第三,Agent 需要实现协议转换的能力。Service Mesh 的一大特色就是可以实现不同语言、不同框架、不同协议间服务的互联互通,靠的就是其协议转换的能力。在比赛设定的场景中,Consumer 使用 HTTP 协议,而 Provider 使用 Dubbo 协议,在没有 Agent 帮助的情况下,他们之间是无法通信的。
作为 Service Mesh Agent, 其实还有很多可以实现的功能,如流量控制、服务降级或熔断、安全认证等等,但以上三点是本次比赛必须做到的能力,其他能力不做要求。另外我们还要考虑 Agent 的通用性,一个不具有通用性的 Agent 是没有商业价值的。除此之外 Agent 占用的系统资源应该尽量小,而且不和共生的服务争抢资源,否则“皮之不存,毛将焉附”。如果服务失去了响应,那么 Agent 的性能再好也没有存在的意义了。
三、跑分
跑分环境是由一台 4 核 8G 的施压机和一台 8 核 16G 的被压机组成。所有 5 个 Docker 实例均运行在被压机上。每个项目的每一次跑分会独占一台被压机。流程大致如下:
准备跑分环境,创建并锁定工作区根据提交的地址,从镜像仓库中拉取镜像
验证 Provider、Consumer 及启动脚本文件的签名,以妨被篡改
启动 etcd 实例,并验证服务可用性
启动三个 Provider 实例,并验证服务可用性
启动 Consumer 实例,并验证服务可用性
使用最高并发数对系统进行预热
分若干次不同的压力水平,对系统进行压力测试,并记录 QPS 值
取最优的 QPS 作为最终的跑分结果,并上报给天池系统
按顺序依次停止 Consumer 实例、三个 Provider 实例和 etcd 实例
清理 Docker 实例及镜像
收集日志并上传到 OSS
解锁工作区,清理环境
因为本届比赛不限语言、不限技术,因此需要一种手段对选手的运行环境进行隔离。借助 Docker 镜像,参赛选手可以随意安装运行时环境、添加组件库、并定制 Agent 的启动脚本。
但需要注意的是,因为 Provider 和 Consumer 服务与 Agent 是共生的,因此他们都是被打到同一个 Docker 镜像中的。我们在赛题设计的时候已经对代码进行了充分的隔离,以保证选手只需要关注赛题允许修改的部分——与 Agent 有关的内容。但不管怎样,由于构建 Docker 镜像的主动权在大家手里,就势必会有篡改 Provider 和 Consumer 及其启动脚本的可能性存在。所以,本着公平的原则,在跑分流程中增加了对相关文件验证签名的过程,如果签名不通过,将失去本次评测机会。
四、优化
因为优化过程是本次比赛关注的重点,因此不能做过多的展开,仅仅提供几个参考的方向。
使用协程。协程可以理解为轻量级的线程,可以节约因为线程切换而造成的性能损失。使用异步通讯。Agent 与 Agent 之间的通讯机制完全由选手自行控制,采用非阻塞的异步通讯机制可以有效提高系统性能。
使用缓存。合理缓存响应结果,当相同的请求再次到来的时候,调用链可以不必经过系统中的每一个节点,从而尽快返回。
以上分别从赛题初衷、应用场景、跑分环境与过程以及少许优化方向的角度,对本届比赛的题目进行了简单的剖析,希望对即将参加比赛的亲们能有所帮助。在此预祝各位参赛选手能取得优异的成绩,进军复赛和总决赛。
阿里中间件性能挑战赛由阿里巴巴集团发起,自2015年开始已经成功举办了三届。我们的初衷是为热爱技术的年轻人提供一个挑战世界级技术问题的舞台,希望选手在追求性能极致的同时,能深刻体会技术人的匠心精神,用技术为全社会创造更大价值。
原文发布时间为:2018-04-27
本文作者:等你来的