Вы можете создать фоновый поток из сценария WSGI при его первом импорте.
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 говорит, что нужно загрузить этот скрипт и запустить его при запуске в контексте группы процессов 'django-jobs'.
Чтобы сохранить наличие нескольких сценариев, я указал на то, каким будет исходный файл сценария WSGI, который вы использовали для 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 в соответствии с запросом.
Как указывалось, альтернативой является наличие сценария командной строки, который устанавливает и загружает Django, выполняет работу и выполняет ее из задания cron. Сценарий командной строки означает временное временное использование памяти, но стоимость запуска для работы выше, так как нужно каждый раз загружать все.