【问题标题】:Why are django-q scheduled tasks delayed randomly?为什么django-q定时任务会随机延迟?
【发布时间】:2021-09-26 21:46:11
【问题描述】:

我发现 django-q 没有按时执行我安排的任务。可能会有几秒到近一分钟的延迟。

我这样安排一个任务:

from django.utils import timezone
from django_q.models import Schedule

def schedule_auction_deadlines(self):
    now = timezone.now()
    if self.deadline:
        name = "end_phase_%d" % self.id
        Schedule.objects.filter(name=name).delete()
        if now < self.deadline:
            Schedule.objects.create(name=name, func="myapp.views.end_phase", args=str(self.id), next_run=self.deadline, schedule_type=Schedule.ONCE)

这是我在 settings.py 文件中的配置:

Q_CLUSTER = {
    'name': 'myproj',
    'label': 'Django Q',
    'timeout': 30,
    'catch_up': True,
    'guard_cycle': 1,
    'redis': os.environ.get('REDIS_URL', 'redis://localhost:6379'),
}

从文档看来,guard_cycle 可能是相关的,但我已经将它设置为最低设置。

什么可能导致这些延迟?

【问题讨论】:

    标签: python django lag django-q


    【解决方案1】:

    我发现 django-q 没有按时执行我安排的任务。可能会有几秒到近一分钟的延迟。

    根据the docs,调度器每三十秒才检查一次,所以需要30-40秒也就不足为奇了。

    从文档看来,guard_cycle 可能是相关的,但我已经将它设置为最低设置。

    保护周期实际上默认为 0.5,因此您将其设置为高于默认值。但是调度程序间隔的实现有点奇怪,因为设置较低的保护时间实际上可以增加调度程序检查之间的时间量。

    重要代码在Sentinel.guard:

    def guard(self):
        logger.info(
            _(
                f"{current_process().name} guarding cluster {humanize(self.cluster_id.hex)}"
            )
        )
        self.start_event.set()
        Stat(self).save()
        logger.info(_(f"Q Cluster {humanize(self.cluster_id.hex)} running."))
        counter = 0
        cycle = Conf.GUARD_CYCLE  # guard loop sleep in seconds
        # Guard loop. Runs at least once
        while not self.stop_event.is_set() or not counter:
            # Check Workers
            [...]
            # Check Monitor
            [...]
            # Check Pusher
            [...]
            # Call scheduler once a minute (or so)
            counter += cycle
            if counter >= 30 and Conf.SCHEDULER:
                counter = 0
                scheduler(broker=self.broker)
            # Save current status
            Stat(self).save()
            sleep(cycle)
        self.stop()
    

    所以调度程序不会每次都通过循环调用。只在每次counter大于30时调用,counter每次按guard_cycle递增。如果将 guard_cycle 设置为 0.001,则守卫将仅通过循环每 30,000 次调用调度程序一次,这将花费超过 30 秒,因为守卫在检查集群的健康状况方面所做的所有其他工作。

    由于调度程序间隔是硬编码的,除了修改 Django Q 或自己调用调度程序之外,我看不出你能做什么。文档没有说明如何执行此操作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-03-18
      • 1970-01-01
      • 2011-11-26
      • 2013-04-26
      • 2020-12-18
      • 2020-08-18
      • 1970-01-01
      相关资源
      最近更新 更多