定时任务的典型落地场景在各行业中都很普遍,比如支付系统中,支付过程中因为网络或者其他因素导致出现掉单、卡单的情况,账单变成了“单边账”,这种情况对于支付用户来说,毫无疑问是灾难级别的体验,明明自己付了钱,扣了款,但是订单状态却未发生变化。所以,每一笔订单的支付任务流程中都需要一个定时轮询的备选方案,一旦支付中发生问题,定时轮询服务就可以及时发现和更正订单状态。
又比如,之前的一篇以寡治众各个击破,超大文件分片上传之构建基于Vue.js3.0+Ant-desgin+Tornado6纯异步IO高效写入服务[1],在超大型文件分片传输任务过程中,一旦分片上传或者分片合并环节出了问题,就有可能导致超大型文件无法完整的传输到服务器中,从而浪费大量的系统带宽资源,所以每一个分片传输任务执行过程中也需要一个对应的定时轮询来“盯”着,防止过程中出现问题。
在实际业务场景中,定时服务基本都作为主应用的附属服务而存在,不同定时任务的调度时间可能不一样,所以如果能够配合主服务并发异步调用定时任务,则可以单应用能够支持上万,甚至十万以上的定时任务,并且不同任务能够有独立的调度时间,这里通过Tornado配合APScheduler和Celery,分别展示不同的异步定时任务调用逻辑。
APScheduler
APScheduler(advanceded python scheduler)是一款及其优秀的Python3定时任务框架,它不仅支持并发异步调用定时任务,还可以动态地对定时任务进行管理,同时也支持定时任务的持久化。
首先安装APScheduler以及Tornado6:
随后导入基于Tornado的异步APScheduler:
这里TornadoScheduler实例就具备了Tornado的事件循环特性,随后声明异步定时任务:
随后初始化定时任务对象:
这里启动后就添加一个定时任务,每隔三秒执行一次。
接着main入口启动服务:
系统返回:
随后创建Tornado控制器视图:
这里通过传参来动态的删减异步定时任务,对于完成轮询任务的定时任务,完全可以物理删除,从而节约系统资源,随后添加路由并且启动Tornado服务:
APScheduler定时任务持久化
所谓任务持久化,即任务存储在诸如文件或者数据库这样的持久化容器中,如果APScheduler定时任务服务进程中断,未执行的任务还会保留,当服务再次启动时,定时任务可以从数据库中读取出来再次被装载调用,这里以redis数据库为例子:
这里通过jobstores参数将redis装载到定时任务服务中,当创建任务时,数据库中会以hash的形式来存储任务明细:
而如果删除任务,redis数据库中的任务也会同步删除。
至此,APScheduler配合Tornado就完成了一个简单的并发异步定时任务服务。
Celery
celery是一款在Python定时任务领域“开风气之先”的框架,和APScheduler相比,celery略显臃肿了一点,同时,celery并不具备任何任务持久化的功能,也需要三方的容器进行支持。
首先安装5.0以上版本:
随后,初始化任务对象:
这里任务代理(broker)和任务结果(result_backend)也都存储在redis中。
紧接着声明异步任务方法:
这里通过asyncio库间接调用异步方法。
然后添加定时任务的配置:
随后启动worker服务:
接着启动beat服务:
异步定时任务会被装载执行,系统返回:
同时,在redis数据库中会以列表和字符串的形式存储任务明细和结果:
从调度层面上讲,celery和APScheduler并无太大的不同,但从使用成本上看,celery比APScheduler多维护一个服务,worker和beat双服务的形式无形中也增加了系统监控资源的开销。
动态维护异步定时任务
从任务管理层面上看,celery毫无疑问输的很彻底,因为原生celery压根就不支持动态地修改定时任务。但我们可以通过三方库的形式来曲线救国:
这里通过redis的定时任务服务来取代celery原生的beat服务。
建立redisbeat实例:
通过schduler.add方法就可以动态地添加定时任务,随后以redisbeat的形式启动celery服务:
此时经过改造的系统接受动态任务调用而执行:
相应地,也可以通过remove方法和任务id进行删除操作:
任务明细的存储形式上,也由列表升级成为了有序集合,提高了效率:
至此,celery配合tornado打造异步定时任务就完成了。
结语
APScheduler长于灵活机动并可以依附于Tornado事件循环体系中,Celery则娴于调度和分布式的支持并相对独立,二者不分轩轾,各擅胜场,适合不同的业务应用场景,当然,在异步定时任务执行异常时的处理策略也有很多方面需要完善,比如由于实例夯死导致的过时触发问题、任务追赶和任务堆积问题、工作流场景下任务异常后是整体重试还是断点续传重试等,都需要具体问题具体分析。
引用链接
以寡治众各个击破,超大文件分片上传之构建基于Vue.js3.0+Ant-desgin+Tornado6纯异步IO高效写入服务:https://v3u.cn/a_id_218
领取专属 10元无门槛券
私享最新 技术干货