[重磅] 如何更好地实现服务调用和消息推送
发布日期:2021-05-07 12:35:29 浏览次数:21 分类:精选文章

本文共 1417 字,大约阅读时间需要 4 分钟。

第四届阿里中间件性能挑战赛是由阿里巴巴集团发起,阿里巴巴中间(Aliware)、阿里云天池联合举办的一场工程性品牌赛事。这场比赛旨在为热爱技术的年轻人提供一个挑战世界级技术问题的舞台,鼓励选手在追求性能极致的同时,体会技术人的匠心精神,为社会创造更大的价值。

本文是亚军选手“做作业”的解题思路,来自南京理工大学的95后开发者。

初赛部分

初赛的主要考察点是实现一个高性能的HTTP服务器和优秀的负载均衡算法。协议转换仅需对协议进行详细了解即可实现,属于基本技能考察。服务的注册和发现可以参考demo中的实现,属于常见处理逻辑。

为了在竞赛环境下取得较好的成绩,常用通用HTTP框架难以取得高分,因为consumer agent和consumer共享一个Docker运行环境。在512连接测试环境下,系统资源紧张,需要舍弃部分HTTP特性才能将consumer性能发挥到极致。因此,选择自行造轮子是一个比较合适的方案。Consumer Agent的总体结构如图1所示。

网络编程模型的选择

高并发网络模型首选epoll,因其在连接数增多时性能不会像select和poll一样明显下降,是由于内核对其进行了特殊优化。实际测试中发现,由于请求是在收到响应后才会继续发出,所以不仅要求高并发,还要求低延迟。延迟叠加会导致QPS下降。

常见的异步网络库如libuv、libevent等都是one loop per thread的设计,即一个线程一个事件循环。这种设计具有较高的吞吐量,但请求只能绑定到一个事件循环上,一旦请求不均匀,就会导致一核有难众核围观的情况,对于动态均衡线程负载不适合。

基于此原因,我决定自己造轮子,让多个线程处理一个epoll循环,让操作系统的线程调度均衡请求。所有连接均绑定到一个事件循环上,也便于处理。最终选择了多线程的et模式的epoll模型,整体框架代码如图2所示。

程序整体流程

Consumer端agent负责解析HTTP请求转换为Dubbo请求,以UDP形式发给Provider agent处理。Provider agent收到UDP后直接传给Provider Dubbo服务处理,将结果以UDP形式回传。Consumer agent处理后返回HTTP形式结果。

程序初始化时,Provider agent调用Etcd接口将自己的服务注册。Consumer agent调用Etcd接口获取到注册的Provider agent地址。由于采用UDP协议通信,不用提前建立连接。Provider agent端仅在第一个请求到达时建立到Provider的TCP连接,保证Provider已经启动完毕可以接受请求。

中间协议设计

考虑到高吞吐量和低延迟,采用了UDP协议。请求为单包单请求,数据格式为Dubbo请求格式,相应包为单包多相应,数据格式为Dubbo响应。Consumer agent端实现协议转换,Provider agent端实现UDP转TCP。

由于请求仅存在于一个包中,不需考虑乱序情况,直接将收到的数据包进行重组发到Dubbo的TCP连接上。提供最大的吞吐量和最低的延迟。具体处理操作如图3所示。

负载均衡算法

负载均衡采用计数方法实现,每次请求发送到和配置负载比例差距最大的Provider上。如果三台都超出200负载,则进行请求排队。当有请求返回时,优先调度排队请求。整体流程如图5所示。

上一篇:开发怼产品,天经地义?大惊小怪?
下一篇:我又花了28个小时分析了一下各省二类疫苗采购公示数据

发表评论

最新留言

第一次来,支持一个
[***.219.124.196]2025年05月06日 08时34分36秒