于celery源码
schedule.is_due注释:
"""Return tuple of ``(is_due, next_time_to_check)``. Notes: - next time to check is in seconds. - ``(True, 20)``, means the task should be run now, and the next time to check is in 20 seconds. - ``(False, 12.3)``, means the task is not due, but that the scheduler should check again in 12.3 seconds. The next time to check is used to save energy/CPU cycles, it does not need to be accurate but will influence the precision of your schedule. You must also keep in mind the value of :setting:`beat_max_loop_interval`, that decides the maximum number of seconds the scheduler can sleep between re-checking the periodic task intervals. So if you have a task that changes schedule at run-time then your next_run_at check will decide how long it will take before a change to the schedule takes effect. The max loop interval takes precedence over the next check at value returned. .. admonition:: Scheduler max interval variance The default max loop interval may vary for different schedulers. For the default scheduler the value is 5 minutes, but for example the :pypi:`django-celery-beat` database scheduler the value is 5 seconds. """
说的是为了节约资源,扫描这个is_due有个间隔时间,一开始是5分钟(默认)或5秒(django-celery-beat),等扫描到周期任务时,这个周期任务的间隔时间又小于celery默认扫描时间时,将以最小值时间进行休息不扫描。
具体代码实现在
Service.start中,如下:
``` while not self._is_shutdown.is_set(): interval = self.scheduler.tick() if interval and interval > 0.0: debug('beat: Waking up %s.', humanize_seconds(interval, prefix='in ')) time.sleep(interval) if self.scheduler.should_sync(): self.scheduler._do_sync() ```
interval = self.scheduler.tick() 这句代码会调用到schedule.is_due,
time.sleep(interval) 这句代码将使扫描休息。interval是schedule.is_due返回的间隔时间和app.conf.beat_max_loop_interval比较后的最小值。
所以当周期任务被动态添加时,并不会马上触发,而是会等待beat_max_loop_interval或者其它任务的间隔时间。
(如果理解错误,欢迎指正。)