Отказ от ответственности. Я знаю, что на SO есть несколько похожих вопросов. Я думаю, что я читал большинство, если не все, но не нашел ответа на мой реальный вопрос (см. Ниже). Я также знаю, что использование сельдерея или других асинхронных систем очередей - лучший способ для достижения длительных задач - или, по крайней мере, использовать управляемый cron script. Там также mod_wsgi doc о процессах и потоках, но я не уверен, что все правильно.
Возникает вопрос:
Каковы конкретные риски/проблемы, связанные с использованием перечисленных там решений? Является ли любой из них жизнеспособным для длительных задач (хорошо, хотя сельдерей лучше подходит)? Мой вопрос действительно больше о понимании внутренних функций wsgi и python/django, чем поиске наилучшего общего решения. Проблемы с блокировкой потоков, небезопасный доступ к переменным, обработка зомби и т.д.
Скажем:
- мой "long_process" делает что-то действительно безопасное. даже если это терпит неудачу, мне все равно.
- python >= 2.6
- Я использую mod_wsgi с apache (что-нибудь изменится с uwsgi или gunicorn?) в режиме демона
mod_wsgi conf:
WSGIDaemonProcess NAME user=www-data group=www-data threads=25
WSGIScriptAlias / /path/to/wsgi.py
WSGIProcessGroup %{ENV:VHOST}
Я понял, что это варианты, доступные для запуска отдельных процессов (в широком смысле) для выполнения долговременной задачи при быстром ответе на пользователя:
os.fork
import os
if os.fork()==0:
long_process()
else:
return HttpResponse()
подпроцесс
import subprocess
p = subprocess.Popen([sys.executable, '/path/to/script.py'],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
(где script скорее всего будет командой manage.py)
темы
import threading
t = threading.Thread(target=long_process,
args=args,
kwargs=kwargs)
t.setDaemon(True)
t.start()
return HttpResponse()
NB.
В связи с глобальным блокировщиком Interpreter Lock в CPython только один поток может выполнять код Python сразу (хотя определенные библиотеки, ориентированные на производительность, могут преодолеть это ограничение). Если вы хотите, чтобы ваше приложение стало лучше использовать вычислительные ресурсы многоядерных машин, вам рекомендуется использовать многопроцессорность. Тем не менее, потоковая передача по-прежнему является подходящей моделью, если вы хотите одновременно запускать несколько задач с привязкой к I/O.
Основной поток быстро вернется (httpresponse). Будет ли порожденный длинный блок wsgi потока делать что-то еще для другого запроса?!
многопроцессорная
from multiprocessing import Process
p = Process(target=_bulk_action,args=(action,objs))
p.start()
return HttpResponse()
Это должно решить проблему с потоком concurrency, не так ли?
Итак, это те варианты, о которых я мог думать. Что будет работать, а что нет, и почему?