UWSGI таймер и cron-декораторы, выполняющие дублирующиеся задания

Я пытался заставить работать спулер uwsgi python в течение достаточно долгого времени. У меня есть установка, в которой я запускаю приложение django с двумя рабочими процессами. Я попытался настроить спулер cron (и спулер таймера) для запуска задачи каждые десять минут, но независимо от того, какую конфигурацию настроек я пробовал, всегда кажется, что сигнал регистрируется несколько раз, а задача запускается несколько раз.

Вот как я запускаю uwsgi:

#!/bin/bash
sudo uwsgi --emperor /etc/uwsgi/vassals --uid http --gid http --enable-threads --pidfile=/tmp/uwsgi.pid --daemonize=/var/log/uwsgi/uwsgi.log

Это мой uwsgi vassal config в /etc/uwsgi/vassals/django.ini:

[uwsgi]

chdir           = /home/user/django
module          = django.wsgi

master          = true
processes       = 2
socket          = /tmp/uwsgi-django.sock
vacuum          = true
pidfile         = /tmp/uwsgi-django.pid
daemonize      = /home/user/django/log.log
env = DJANGO_SETTINGS_MODULE=django.settings
#lazy-apps = false
#lazy = false
spooler = %(chdir)/tasks
#spooler-processes = 1
#import = django-app/spooler.py
#spooler-import = django-app/spooler.py
shared-import = django-app/spooler.py

(Я изменил некоторые пути по причинам конфиденциальности). Строки, которые закомментированы, представляют собой различные попытки сделать так, чтобы он не дублировал мои сигналы, но каждый раз, когда кажется, что он регистрирует сигнал дважды, а иногда даже трижды (предположительно, как в рабочих, так и в процессе одного спулера).

[uwsgi-signal] signum 0 registered (wid: 0 modifier1: 0 target: default, any worker)
[uwsgi-signal] signum 1 registered (wid: 1 modifier1: 0 target: default, any worker)
[uwsgi-signal] signum 1 registered (wid: 2 modifier1: 0 target: default, any worker)

Кто-нибудь знает, почему это происходит, и как правильно это предотвратить?

Это файл spooler.py:

@cron(-10, -1, -1, -1, -1)
def periodicUpdate(signal):
    print "Running cron job..."
    _getStats()

также пытался

@timer(600)
def periodicUpdate(signal):
    print "Running cron job..."
    _getStats()

Я также попытался добавить target='spooler' таймеру / cron-decorator, но это не показалось многим никакой разницы.

2 ответа

Вы уверены, что у вас нет других сигналов, зарегистрированных в django.wsgi, settings.py или других файлах, связанных с django? --shared-import загружает вещи только один раз (в мастере).

Кстати, я не понимаю, что вы пытаетесь достичь. Это не то, как должен работать спулер, и даже если вы хотите использовать его в качестве цели обработчика сигналов, вы должны указать его при регистрации сигналов (с target='spooler' в декораторе)

Хотя это старый вопрос, я не мог найти ответ в другом месте. Я использовал это решение с Flask, но оно должно быть похоже на Django.

Во время инициализации (режим prefork) вам необходимо зарегистрировать сигнал.

      uwsgi.register_signal(26, "spooler", periodicUpdate)

Тогда таймер должен выглядеть так:

      @timer(600, target='spooler')
def periodicUpdate(signal):
    print "Running cron job..."
    _getStats()

Что касается комментариев:

Ошибка «только мастер и рабочие могут регистрировать обработчики сигналов» верна, потому что вы не зарегистрировали никакого сигнала.

Проблема с

«всякий раз, когда я загружаю одну из страниц в своем приложении django, она перерегистрирует ее»

вероятно, может произойти, потому что его рабочий процесс вызывает метод (periodicUpdate) один раз. Вот почему сигнал должен быть зарегистрирован до создания рабочих процессов.

Другие вопросы по тегам