重构XXL-JOB,使用响应式编程实现异步RPC提升调度吞吐量

原创 吴就业 132 0 2021-12-25

本文为博主原创文章,未经博主允许不得转载。

本文链接:https://wujiuye.com/article/2a126602392f4b9590a85bf808bb72a2

作者:吴就业
链接:https://wujiuye.com/article/2a126602392f4b9590a85bf808bb72a2
来源:吴就业的网络日记
本文为博主原创文章,未经博主允许不得转载。

本篇文章写于2021年12月25日,从公众号|掘金|CSDN手工同步过来(博客搬家),本篇为原创文章。

在xxl-job中,RPC即用于调度中心请求执行器执行job、kill job,也用于执行器请求调度中心主动注册、执行结果上报。

xxl-job实现的RPC类似Feign框架,是基于http这种七层协议实现的,而http协议是无状态的,因此一个连接不能同时被用于多个线程发送请求,只能等待一个请求响应后再放入连接池被其它线程使用。

对于执行器而言,由于只与调度中心交互,请求量也少,因此这种RPC实现不会对执行器性能有什么影响。

调度中心则不同,它需要同时与多个执行器交互,如果同一时刻需要下发几百个执行job的请求给执行器,使用这种阻塞的RPC,意味着需要开启几百个线程,使用几百个连接发送请求,而这几百个线程都需要阻塞等待响应,Job越多,需要的线程数就会越多,对调动中心的性能影响就越大。

xxl-job即便更新到最新的2.x版本,还是使用同步阻塞的RPC调用。

知道了为什么同步RPC会影响调度中心的性能,再来理解为什么异步RPC能解决这个问题的原因就容易很多。

响应式编程通过事件触发回调解决同步阻塞问题,要求整条链路上都无阻塞,即无I/O阻塞(数据库操作、网络请求响应等)。

我们重构后的新版本调度中心(xxl-job),我们使用了reactor-netty-http框架实现异步RPC,当然,我们需要解决的只是调度中心的性能问题,因此执行器是可以不用改动的、兼容旧版本的。

reactor-netty-http并非解决http这种协议的无状态问题,依然一个连接同时只能用于发送一个请求,需要等待响应后才能被用于发送其它请求。但reactor-netty-http不会创建一个线程去阻塞等待,而是通过事件轮询方式,去消费响应,释放连接回连接池。

在使用reactor-netty-http之后,我们只需要配置CPU核心数个工作线程处理向执行器发送RPC请求,reactor-netty-http在一个线程上完成请求发送后,就会继续处理其它请求发送,当轮询到某些连接收到客户端响应事件后,再处理这些响应,释放连接回连接池,调回doNext。

最终从效果上看,基于reactor-netty-http实现的RPC,类似于dubbo使用长连接实现的异步RPC。

使用响应式编程实现异步RPC提升调度吞吐量

reactor-netty-http可能会创建大量连接,但不会创建大量线程,可用使用netstat观察连接数的增长,使用jstack工具观察reactor-netty-http创建的线程数。

要解决调度的性能问题,除了异步RPC是不够的,异步RPC只能帮我们解决下发请求的阻塞问题。而且响应式编程要求整个链路上必须无阻塞。那么异步回调的事件消费也必须是异步的。

同时,我们将执行器节点信息、Job数据也完全存储在内存中,让触发->job查询->执行器查询->执行器节点查询->日记打印->调度下发整条链路都完全无阻塞。而数据的一致性,则通过分布式一致性算法保证,为了稳定以及开发简单,我们基于zookeeper实现。

#中间件

声明:公众号、CSDN、掘金的曾用名:“Java艺术”,因此您可能看到一些早期的文章的图片有“Java艺术”的水印。

文章推荐

基于扩展点,为dubbo支持跨业务调用

很多规模稍大点的公司,内部都会有多个业务部门,这些业务部门都有自己的业务产品。每个业务部门开发的产品部署的环境物理上也都是相对隔离的,但这些业务部门之间可能存在合作关系,业务关联,因此就有了跨业务RPC调用的需求。

kafka消息重复消费排查

业务使用我们基础部门封装的kafka组件,在一次版本迭代中,我们引入了offset缓存,正是这个缓存,在某种条件触发下,会导致出现消息重复消费现象。

Quartz分布式调度原理

在同一时刻需要触发的Job只有少量的情况下,我们看不到Quartz的性能缺陷,在Job数量明显增加情况下,我们就会发现,调度延迟会有明显增加。尽管横向扩展节点,调度延迟也不会降低,且整体调度性能没有明显好转,反而更糟糕。

重构支持多租户的XXL-JOB,如何实现多个逻辑集群的均衡选主

我们基于XXL-JOB的架构原理,重新架构设计了支持多租户横向扩展的分布式任务调度平台。本篇介绍如何实现多个逻辑集群(多个租户逻辑上是独立的集群)的均衡选主。

BFE原生路由转发功能分析

为什么加上“原生”,因为我们基于BFE开发已经魔改了。路由转发是BFE作为一个七层流量代理服务的核心功能,BFE设计了一套支持多租户、多机房的路由转发模型。

基于Kafka,延迟消息队列的设计

由于Kafka不支持延迟消息,而目前公司技术栈中消息中间件使用的是Kafka,业务方希望使用RocketMQ满足延迟消息场景,但如果仅仅只是需要延迟消息功能而引入多一套消息中间件,这会增加运维与维护成本。在此背景下,我们希望通过扩展Kafka客户端提供延迟消息的支持。