Django cron运行多次,但不应运行多次

时间:2019-09-04 12:09:26

标签: python django cron

我在Django中设置了多个克朗。在每个CronJob中,我都设置了ALLOW_PARALLEL_RUNS = False。为了运行克朗,我使用了Linux crontab,如下所示:

*/1 * * * * /home/social/centralsystem/venv/bin/python3.6 /home/social/centralsystem/manage.py runcrons 

运行一段时间后(例如2个月后),我看到许多运行的同名客户在服务器上造成了很多负载。我的问题是造成这种情况的原因是什么?

我的cron类的一个示例是:

class UserTaskingCronJob(CronJobBase):
    ALLOW_PARALLEL_RUNS = False
    RUN_EVERY_MINS = 5

    schedule = Schedule(run_every_mins=RUN_EVERY_MINS)
    code = 'user_tasking'

    def do(self):
        args = {
            'telegram': {
                'need_recrawl_threshold': 60 * 2,
                'count': 100,
            },
            'newsAgency': {
                'need_recrawl_threshold': 10,
                'count': 100,
            },
            'twitter': {
                'need_recrawl_threshold': 60 * 4,
                'count': 500
            },
        }
        for social_network in ['telegram', 'newsAgency', 'twitter']:
            user_queuing(
                SOCIAL_USERS_MODEL[social_network],
                social_network,
                args[social_network]['need_recrawl_threshold'],
                args[social_network]['count'],
            )

5 个答案:

答案 0 :(得分:2)

您的cronjob每分钟运行一次。

有关说明,请参见here

Cron分为:

minute hour day(month) month day(week)

斜线表示步长值。

在您的情况下,它将以1分钟为单位执行。即每分钟。

*/1 * * * *

答案 1 :(得分:1)

如果您有许多不同的任务在不同的时间段运行,则必须谨慎使用django-cron。 runcrons按顺序获取所有cron类,并按顺序运行它们。完成后,它也只会将cron(成功与否)记录到数据库中。我认为django-cron可以通过在开始时保存cron日志(并检查是否已经有正在运行的任务)来进行改进,但是如果运行多个作业而不是一个长时间的作业,那仍不能排除重叠。

您每分钟都在运行runcrons,因此在这些情况下,您会遇到麻烦:

  • 如果在其中一种运行期间,需要运行的一项任务花费的时间超过1分钟。
  • 如果在其中一种运行期间,所有需要运行的任务的总持续时间超过1分钟,则需要运行。

在两种情况下,某些任务都不会及时登录到数据库中,并且在它们运行时,下一个runcrons命令将再次启动它们。

为避免这种情况,请执行以下操作:

  • 确定运行时间超过1分钟的任务,并以不同的时间表运行它们,以确保任务在下一次运行之前完成。
  • 在crontab中,运行单独的runcrons命令,每个命令都包含一个cron类列表,以确保列表的总运行时间少于1分钟,例如
*/1 * * * * ./bin/python3.6 manage.py runcrons "my_app.crons.FirstCron" "my_app.crons.SecondCron"
*/1 * * * * ./bin/python3.6 manage.py runcrons "my_app.crons.ThirdCron"
*/10 * * * * ./bin/python3.6 manage.py runcrons "my_app.crons.LongCron"

答案 2 :(得分:0)

我建议您为每个社交网络创建一个锁定文件,并检查您的最后一个收集器是否完成。例如,在代码的开头添加/tmp/telegram.lock(如果存在,则停止该作业),然后在代码的末尾将其删除。每次您要开始新工作时,请检查是否存在旧锁。

答案 3 :(得分:0)

我发布了最终解决方案,以便其他任何人都可以使用它。

首先,您应该知道由于django-cron错误,您不应期望它会阻止单个cron的并行运行。因此,为了防止并行运行,您应该为每个分支都编写一个单独的Linux crontab

第二,您应该使用某种锁定方式来防止crontab多次运行单个cron。我建议使用flock

答案 4 :(得分:0)

Django cron默认情况下使用缓存来维护当前正在进行的作业的状态,因此除非指定为并行运行,否则它不会多次执行任务。

如果您在Django应用中设置了缓存,则无需担心,并在crontab中多次拆分命令

有关更多信息,您可以检查它here