定时任务处理过程中的问题

时间:2021-12-15 07:50:43

前段时间做了业务系统定时任务的一个需求,其中遇到几个问题,有必要思考并沉淀下来,分享出来。

业务系统的定时任务:指的是针对业务系统,每隔指定的一段时间,就做一次任务。那么,这个通知由谁来发?

(1)可以由业务系统自己来指定,利用多线程,指定时间执行一次就OK。但是这样带来的问题是,随着定时任务的越来越多,线程也会越来越多,而且这些线程须一直运行着,无疑对业务系统是一种庞大的负担。同时就本质上来说,业务系统是专门来处理业务逻辑的,不应该加入这些开销。

(2)那么,更好的方法就是,建立一个调度系统。以一个公司长远发展的利益来看,有必要建立这样的调度中心来为所有业务系统的定时任务提供支撑。每当一个业务系统需要一个定时任务时,就可以去调度中心配置相关的参数与对应的订阅关系,使得调度中心定期地向业务系统发出消息,告知业务系统,这个时候该执行这个定时任务了。(至于调度原理,可以参考Quartz的实现,定时任务的框架都与此大同小异)。

现在来说说我在开发过程中遇到的问题(其实也是必须考虑的问题):

1、如果调度中心往业务系统发送了消息,要求现在执行一个定时任务。但此时业务系统却挂掉了,如何应对这种情况?

答:分析得通俗点,其实一个好的业务系统要做每日定时任务,一年内出这类问题的频率应该不会上10次(如果更多甚至难以接受,只能是业务系统本身的设计和实现有问题,直接重构代码吧)。当这样的问题出现的时候,其实可以通过消息代发等形式告知系统开发人员,进行问题排查,然后手动地重新执行一次就OK了,不必大动干戈。

2、调度中心往业务系统发送消息的时候,往往需要得到业务系统的反馈,也就是这个任务执行的结果成功与否。这样的机制固然更可靠,但如果一个消息发过去之后,调度中心迟迟没有等来业务系统的结果(可能是由于这个任务执行的时间比较长,或者中途出了什么原因卡顿了一下,并不是因为业务系统down机),而调度中心却认为,这个消息可能没有传送到业务系统,就又发了一次消息过去试图重试。那可能就会出问题了。如何解决这类问题呢?

答:对于这种情况,需要使用线程池,在业务系统端启用异步线程执行任务处理,然后直接return返回给调度中心结果,告诉调度中心已经完成消息处理,避免超时重试(因为已经有了问题1的机制,完全不用担心这样操作会导致今天的定时任务没有执行)。

3、如果调度中心出了问题,在一天内向业务系统发了100次消息,那么又要如何处理这种情况?

答:这个就涉及到业务系统集群的调度方式了。当一条消息从调度中心过来时,会分发给业务系统集群的所有机器,换句话说,每台机器都会收到这样的消息,难道每台机器都执行一次吗?不是。业务系统集群需要一张DB表来管控。一个消息过来,最早接收到这个消息的集群中机器,将会得到DB管控表的写入权限,将这条消息写入。当另一台机器又试图写入这条消息时,它查询到DB表中已经存在这条消息,便将这条消息废弃掉,然后不做任何处理了。这样就保证了,不论调度中心一天之内来多少条消息,我也不会重复地去处理这个请求。实现了多个节点的应用在某一时刻对任务只进行一次调度。

定时任务处理过程中的问题