本发明涉及分布式任务调度的方法,具体的讲是基于延时队列的分布式任务轮询的方法。



背景技术:

微服务架构是一项在云中部署应用和服务的新技术,微服务的架构模式在互联网分布式技术领域已经逐步占据主流地位。在将应用模块拆分成微服务后,每个微服务在做高可用 (High Availability)部署时,必须是无状态的,这样才能方便扩展。而调度作业程序除了是无状态的以外,在做高可用分布式部署的时候,还要解决在执行某个作业时,多份程序同时从一个数据库中抽取某个状态的数据时,数据重复的问题。常用的任务调度机制不再适用于分布式场景,如何优雅、低开销的实现分布式场景下的任务轮询,直接决定了一个分布式系统将来的可扩展性。

在现有的一些微服务任务轮询技术中,常采用将数据库数据分组的方式来解决不再重复读取数据的问题。但在一些只需要轮询业务结果状态的任务中,使用数据库分组轮询技术就显的比较笨重。例如:在一个支付系统的场景中,支付的结果状态存在三种,交易处理中、交易已完成、交易失败,任何一个交易请求都可能返回交易处理中,而且返回结果的时间是不可预估的,我们需要将支付的最终结果推送给上游系统,常用的解决方案是设计一个定时轮询的作业来查询最终的支付结果,并返回给上游。在分布式场景下,每一个分布式调度作业,都需要先根据ID取模等于某个数字,且状态是处理中的条件来读取数据,比如调度作业 A读取数据的取模规则为模数等于1,调度作业B的取模规则为模数等于2,这样就避免了重复读取同一份数据的问题。

这个方案可行,但存在很大的局限性。首先,程序本身不够灵活,在程序开发时需要先开发一套针对调度的配置规则,在程序部署时,运维人员必须要了解并修改一个任务的调度配置规则才可以部署,这将不利于自动化部署,且增加了额外的学习成本。第二,定时作业由于读取数据时,采用了一个固定的周期来执行,任务粒度过粗,没有根据每一个任务的创建时间来订制调度周期,缺乏一定的公平性的,后来的请求有可能在最近的一个调度周期内被执行,在业务高峰期,交易处理往往会有一定程度的延迟,在这个周期内查询刚发生的交易结果,往往是徒劳无功的,反而增加了下游系统的压力。第三,分布式调度作业需要独立部署,这将占用额外的硬件资源。



技术实现要素:

针对上述问题,本发明提供了一种基于延时队列的分布式任务轮询的方法,使每个任务的执行间隔相等,任务的处理时机相对公平,并且在不采用数据分组方式的情况下,解决数据重复读取的问题,减少分布式调度程序的复杂度。

本发明基于延时队列的分布式任务轮询的方法,包括:

A.根据消息队列的消息过期与死信投递机制,建立业务延时队列;

B.在微服务中建立用于接收任务轮询请求的任务轮询队列;

C.将需要轮询的业务数据转换为队列消息,并将其投入到所述的业务延时队列中,在指定的延迟时间结束后,将所述需要轮询的业务数据自动投入到所述的任务轮询队列中;

D.由系统处理任务轮询队列中的业务数据,并根据处理结果判断业务数据是否退出任务轮询队列。

通过消息队列的方式能够实现每个任务的执行间隔相等的公平机制,减少系统无谓的符载压力,同时也能够减少分布式调度程序的复杂度。

进一步的,通过设置业务延时队列的延时间隔参数,调整不同需求下进行任务轮询的间隔时间。使其可以适应各种不同的应用环境和需求。

进一步的,所述的业务延时队列为通过RabbitMQ协议建立的MQ队列。RabbitMQ是一种实现了高级消息队列协议(AMQP)的开源消息代理软件,亦称面向消息的中间件。

进一步的,步骤D中系统通过业务数据的主键从数据库中读取对应的业务主体数据进行处理。

在此基础上,步骤D中,系统处理所述的业务数据后,如果处理结果不满足业务的就绪条件,则将业务数据再次转换为队列消息,重新将其投入到所述的业务延时队列中进行延时,延时结束后再将该业务数据自动投入到任务轮询队列中,重复执行步骤D;

如果处理结果满足业务的就绪条件,系统则更新数据库,并将业务数据退出任务轮询队列,终止对该业务数据的循环逻辑。

本发明基于延时队列的分布式任务轮询的方法的有益效果包括有:

1.规避了现有的数据库轮询机制的各种不足,采用延时队列的方式实现了轮询机制,使每个任务的执行间隔相等,任务的处理时机相对公平。

2.规避了现有的通过数据分组方式的各种不足,并且解决了数据重复读取的问题,减少了分布式调度程序的复杂度。

3.扩容时更加简单,无需修改任何配置,只需额外启动一个程序节点即可,配合docker容器技术可随时扩展到任意多个程序节点,完成业务高峰期的计算需求,高效、简单的实现了系统的弹性伸缩。

4.无需再进行额外的调度程序部署,大幅度节约了硬件资源。

以下结合实施例的具体实施方式,对本发明的上述内容再作进一步的详细说明。但不应将此理解为本发明上述主题的范围仅限于以下的实例。在不脱离本发明上述技术思想情况下,根据本领域普通技术知识和惯用手段做出的各种替换或变更,均应包括在本发明的范围内。

附图说明

图1为本发明基于延时队列的分布式任务轮询的方法的流程图。

具体实施方式

如图1所示本发明基于延时队列的分布式任务轮询的方法,包括:

A.根据RabbitMQ协议的消息过期与死信投递机制,建立MQ队列类型的业务延时队列,并设置业务延时队列的延时间隔参数,调整不同需求下进行任务轮询的间隔时间。使其可以适应各种不同的应用环境和需求。

业务延时队列配置如下:

Name:business_queue_delay

Arguments:x-dead-letter-exchange=xxx exchange

x-dead-letter-routing-key=business_queue_delay

B.在微服务中建立用于接收任务轮询请求的任务轮询队列;

C.将需要轮询的业务数据转换为MQ队列消息,并将其投入到所述的业务延时队列中,在指定的延迟时间结束后,将所述需要轮询的业务数据自动投入到所述的任务轮询队列中;

D.当需要轮询的MQ队列消息到达时,由系统通过任务轮询队列中业务数据的主键从数据库中读取对应的业务主体数据进行处理。并根据处理结果判断业务数据是否退出任务轮询队列。系统处理所述的业务数据后,如果处理结果不满足业务的就绪条件,则将业务数据再次转换为MQ队列消息,重新将其投入到所述的业务延时队列中进行延时,延时结束后再将该业务数据自动投入到任务轮询队列中,重复执行步骤D;

如果处理结果满足业务的就绪条件,系统则更新数据库,并将业务数据退出任务轮询队列,终止对该业务数据的循环逻辑。

由此,通过RabbitMQ延时队列的方式实现了任务的轮询机制,并且每一个业务的执行周期都是相等的,均为队列的延时间隔,具有公平性,而且RabbitMQ延时队列支持分布式场景,在弹性扩容时,无需修改任何配置,具有良好的可扩展性。

实施例:

以支付场景为例:

场景描述:支付系统在进行支付交易的时候,会返回支付处理中的交易结果,针对这种结果,需要调用方通过支付系统提供的交易结果查询接口来定时的查询最终支付结果。

通过本发明基于延时队列的分布式任务轮询的方法实现上述支付场景的应用:

A.根据RabbitMQ协议的消息过期与死信投递机制,建立MQ队列类型的支付延时队列,并设置支付延时队列的延时间隔参数。

MQ队列类型的支付队列配置如下:

Exchange:direct-exchange

Name:PAYMENT_PAY_QUEUE

B.在微服务中建立用于接收支付轮询请求的支付轮询队列;

支付结果确认轮询队列配置如下:

Exchange:direct-exchange

Name:PAYMENT_PAY_CONFIRM_QUEUE

C.将需要轮询的支付数据转换为MQ队列消息,并将其投入到支付延时队列中,在指定的延迟时间结束后,将需要轮询的支付数据自动投入到支付轮询队列中;

支付结果确认轮询的延迟队列配置如下:

Exchange:direct-exchange

Name:PAYMENT_PAY_CONFIRM_QUEUE_DELAY

Arguments:x-dead-letter-exchange=direct-exchange

x-dead-letter-routing-key=PAYMENT_PAY_CONFIRM_QUEUE

D.当需要轮询的MQ队列消息到达时,由系统通过支付轮询队列中支付数据的主键从数据库中读取对应的支付主体数据进行处理。并根据处理结果判断支付数据是否退出任务轮询队列。系统处理支付数据后,如果处理结果不满足支付完成的条件,则将支付数据再次转换为MQ队列消息,重新将其投入到支付延时队列中进行延时,延时结束后再将该支付数据自动投入到支付轮询队列中,重复执行步骤D;

如果处理结果满足支付完成的条件,系统则更新数据库,并将支付数据退出支付轮询队列,终止对该支付数据的循环逻辑。

支付结果通知队列配置如下:

Exchange:direct-exchange

Name:PAYMENT_PAY_RESULT_QUEUE

主要代码如下: