分析apscheduler的定时调度器源码

前言:

跟大家在群里聊了关于apscheduler的一些话题,大家尤其对他的时间管理感兴趣, 趁现在有空,花点时间做个分享。  其实在以前是写过apscheduler的源代码分析文章,写得太泛了,这次主要着重于定时器的相关逻辑。  python下的定时任务框架有那么几个选择,像sched,celery,apscheduler都可以做,相对来说功能和扩展最好的当属apscheduler了。   话说,我曾经还给apscheduler提交过一个crontab 格式的扩展,最后没merge,原因不明….  

该文章写的有些乱,欢迎来喷 ! 另外文章后续不断更新中,请到原文地址查看更新.   http://xiaorui.cc/?p=4228

首先从一个测试说起,代码如下:

执行的结果确实是我们想看到的,很理想  !  

那么我们应该去思考下,Apscheduler是如何管理这些定时器的 ?  我曾经写过各种各样的定时器, 用redis zset实现定时器,用gevent实现过, 用小堆实现过, 用epoll timerfd也实现过…  有兴趣的朋友可以看看我的github和博文. 

追了一下代码发现 apscheduler 默认是没有采用这些方法, 而使用了一个更加简单的方法. 


在这里我们知道他会wait这个事件,超时的时间为所有定时器中最小的那个。。。   举个例子现在是1秒, 有三个任务分别是10秒、15秒、20秒后执行? 那么我们就再等待 10 – 1 秒。

那么这里会有一个效率的问题 !  当job列表任务很多的时候,难道每次都O(N)的时间复杂度计算下次event等待时间? 

当然不可能这么粗暴  !     

Apscheduler 使用jobstore为memery模式时候,会构建一个列表来用存放任务,当我们 add_job 添加一个新任务的时候,这个列表按时间排序存放,可以理解为有序列表,查找存放的点当然是二分查找算法了, 他的时间复杂度是 O(logN) .   这样实现的效果跟我前面说的小堆是一样的.   


如果 apscheduler的定时任务已经跑起来了, 这时候你新加了一个定时周期任务?  但是你这边还在wait?  不要担心,当你调用add_job时, _real_add_job会帮你唤醒的.  当被唤醒了后,Apscheduler又继续寻找到期任务及等待时间。 

Apscheduler扩展了很多的jobstore存储方案,那么我们挑几个看看他们的实现方法. 

file: jobstores/redis.py

当然mysql也是依赖时间戳的概念,也是需要有排序的。

就先这样吧,.  到此为止我们差不多得知apscheduler的scheduler和job的设计,下次有时间再来分析下apscheduler的其他组件源码。

END.


对Golang感兴趣的朋友可以加群: 278517979 !!!
另外如果大家觉得文章对你有些作用! 如果想赏钱,可以用微信扫描下面的二维码, 感谢!
另外再次标注博客原地址  xiaorui.cc

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">