响应式编程实现异步RPC,提升xxl-job调度吞吐量
在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。
reactor-netty-http可能会创建大量连接,但不会创建大量线程,可用使用netstat观察连接数的增长,使用jstack工具观察reactor-netty-http创建的线程数。
要解决调度的性能问题,除了异步RPC是不够的,异步RPC只能帮我们解决下发请求的阻塞问题。而且响应式编程要求整个链路上必须无阻塞。那么异步回调的事件消费也必须是异步的。
同时,我们将执行器节点信息、Job数据也完全存储在内存中,让触发->job查询->执行器查询->执行器节点查询->日记打印->调度下发整条链路都完全无阻塞。而数据的一致性,则通过分布式一致性算法保证,为了稳定以及开发简单,我们基于zookeeper实现。
相关文章
- iOS 有哪些迷惑的设计规范?
- iOS系统即将迎来升级,新功能备受欢迎,安卓用户只能干看着
- iOS15新功能来袭,让人惊喜让人忧,你们期待吗?
- 安卓8GB运存都表示卡顿了,为何苹果手机才4GB却一点不着急
- 谷歌大脑创始成员辞职,他也和Jeff Dean闹掰了
- 交互优化方案的流程是什么样的?来看高手的总结!
- B端设计师怎样发挥设计价值?来看京东高手的总结!
- Android 12现在有了设备搜索API 可用于第三方启动程序
- 10 年版权案终了结:美最高法院裁定谷歌安卓系统未侵权甲骨文 Java
- 谷歌地图大更新!AR导航转室内,机场商场不再难逛
- 苹果iOS系统隐藏的6个实用功能,不会用真是太浪费了
- iOS 14.5不再默认为女性语音 英语Siri新增两种声音
- 支付宝收钱码提现免费服务再延长 3 年,且不设单笔上限和单日上限
- 手机内存怎么删?这三种方式都可以实现,根据需求选择即可
- 图数据挖掘:小世界网络模型和分散式搜索
- 知识图谱实体对齐3:无监督和自监督的方法
- 谷歌准备发布 Fuchsia 首个开发者预览版
- 老年消费者吐槽扫码点餐:字太小 操作难
- 手机行业:关于手机的冷知识,这些你知道吗?
- 数值优化:经典随机优化算法及其收敛性与复杂度分析