Могу ли я использовать код внутри Django как демон?

Я использую mod_wsgi для обслуживания сайта django через Apache. У меня также есть код Python, который работает как фоновый процесс (dameon?). Он продолжает опрос сервера и вставляет данные в одну из моделей Django. Это прекрасно работает, но могу ли я включить этот код в состав моего приложения Django и все же иметь возможность постоянно работать в фоновом режиме? Он не должен быть процессом как таковым, а искусством сайта Django, который постоянно работает. Если да, можете ли вы указать мне пример или какую-нибудь документацию, которая поможет мне выполнить это?

Спасибо.

Ответ 1

Вы можете либо настроить задание cron, которое выполняет определенную вами функцию, либо - более продвинутый и, возможно, рекомендуемый метод, интегрировать celery в вашем проекте (что довольно просто, на самом деле).

Ответ 2

Вы можете создать фоновый поток из WSGI script, когда он сначала импортируется.

import threading
import time

def do_stuff():
    time.sleep(60)
    ... do periodic job

_thread = threading.Thread(target=do_stuff)
_thread.setDaemon(True)
_thread.start()

Для этого нужно работать, хотя вам придется использовать только один процесс демона, иначе каждый процесс будет делать то же самое, что вам, вероятно, не нужно.

Если вы используете несколько процессов в группе процессов демона, альтернативой является создание специальной группы процессов демона, единственной целью которой является запуск этого фонового потока. Другими словами, процесс фактически не получает никаких запросов.

Вы можете сделать это, если:

WSGIDaemonProcess django-jobs processes=1 threads=1
WSGIImportScript /usr/local/django/mysite/apache/django.wsgi \
    process-group=django-jobs application-group=%{GLOBAL}

В директиве WSGIImportScript говорится о загрузке script и запускается при запуске в контексте группы процессов django-jobs.

Чтобы сохранить несколько сценариев, я указал на то, что будет вашим исходным WSGI script файлом, который вы использовали для WSGIScriptAlias. Мы не хотим, чтобы он запускался, когда он загружается этой директивой, но мы делаем:

import mod_wsgi

if mod_wsgi.process_group == 'django-jobs':
    _thread = threading.Thread(target=do_stuff)
    _thread.setDaemon(True)
    _thread.start()

Здесь он смотрит на имя группы процессов демона и запускается только при запуске в группе процессов специального демона, настроенной только для одного процесса.

В целом вы просто используете Apache в качестве великого менеджера процессов, хотя он уже известен как надежный. Это немного утомительно, так как этот процесс будет потреблять дополнительную память поверх тех, кто принимает и обрабатывает запросы, но в зависимости от сложности того, что вы делаете, все равно может быть полезно.

Один милый аспект этого заключается в том, что, поскольку он по-прежнему является полноценным приложением Django, вы можете сопоставить определенные URL-адреса только с этим процессом и таким образом предоставить удаленный API для управления или контроля фоновой задачи и того, что она делает.

WSGIDaemonProcess django-jobs processes=1 threads=1
WSGIImportScript /usr/local/django/mysite/apache/django.wsgi \
    process-group=django-jobs application-group=%{GLOBAL}

WSGIDaemonProcess django-site processes=4 threads=5
WSGIScriptAlias / /usr/local/django/mysite/apache/django.wsgi

WSGIProcessGroup django-site
WSGIApplicationGroup %{GLOBAL}

<Location /admin>
WSGIProcessGroup django-jobs
</Location>

Здесь все URL-адреса, кроме файлов под /admin, запускаются на "django-site", с /admin в "django-jobs".

В любом случае, это касается конкретного вопроса о его выполнении в процессе демонов Apache mod_wsgi по запросу.

Как указано, альтернативой является наличие командной строки script, которая устанавливает и загружает Django и выполняет работу и выполняет это из задания cron. Командная строка script означает случайное использование временной памяти, но стартовая стоимость для задания выше, так как нужно загружать все каждый раз.

Ответ 3

Я раньше использовал работу cron, но, говорю вам, через некоторое время вы переключитесь на сельдерей.

Сельдерей - это путь. Кроме того, вы можете выполнить длительный процесс async, чтобы ускорить время запроса/ответа.