延迟任务调度系统—技术选型与设计(下篇) (3)

延迟任务调度系统—技术选型与设计(下篇)



服务加载

从DB读取服务配置

根据配置动态构造Consumer对象并添加到Spring容器中


提交任务

业务系统通过dubbo或http接口提交任务

判断任务过期时间是否在一个扫描周期内

如果是,

设置分片号(从当前节点所负责的分片随机获取)

添加到内存队列

任务保存到job_delay_task表

如果否,

设置分片号(根据分片总数和随机算法算出分片号)

任务保存到delay_task表

定时器

由一个线程管理

根据配置的扫描间隔设置定时器的执行周期

根据当前时间和扫描间隔算出该时段的过期时间X-Delay

从DB获取过期时间在X-Delay之前的所有任务,并放到DelayQueue

调度任务

由一个线程池管理

所有线程都阻塞在DelayQueue的方法take

take到任务,从DB中获取任务,判断是否存在

如果不在,什么也不做(任务已执行成功或已被删除)

如果存在,判断调用次数是否超过设置

如果不超

调用业务回调服务

从任务中取出调用的服务配置

从容器中获取对应的Consumer对象

异步调用业务回调服务

设置下次重试时间,记录调用日志job_delay_task_execlog

如果超过,将任务转移到job_delay_task_backlog


任务反馈

更新任务调用结果

优点

功能全面,高可用、易伸缩、可重试

缺点

略微复杂

需要将服务配置动态生成为Consumer对象

增加新的服务需要通知所有调度节点刷新

存在一定的耦合性(直接调用业务服务,协议耦合),如果接入系统是thrift协议呢?

需要处理任务的重试

调度系统直接回调业务服务,如果业务服务不可用可能会造成盲目重试,不能很好的控制流量(调度系统不知道业务服务的处理能力)

如果引入MQ,使用MQ来解耦服务调用的协议,保证任务的重试,并由消费方根据自己的处理能力控制流量会不会更好呢?

另一种方案(DB/DelayQueue/ZooKeeper/MQ)

整体架构

延迟任务调度系统—技术选型与设计(下篇)


数据库设计

延迟任务调度系统—技术选型与设计(下篇)



主要流程

延迟任务调度系统—技术选型与设计(下篇)



调度任务

由一个线程池管理

所有线程都阻塞在DelayQueue的take方法

take到任务,从DB中获取任务,判断是否存在

如果不在,什么也不做(任务已执行成功或已被删除)

如果存在,将任务转移到job_delay_task_execlog;往消息队列投递消息

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwxjwy.html