Как запустить собственные демонические процессы с Django?
в моем проекте Django я должен неоднократно выполнять некоторую обработку в фоновом режиме. Эта обработка требует доступа к материалам Django, поэтому я помещаю ее в команды Django и запускаю ее как cronjob. Прямо сейчас я понимаю, что мне нужно делать некоторые из них чаще (cronjob имеет ограничение вызывать команду не более чем каждые 1 минуту). Другая проблема заключается в том, что у меня недостаточно контроля, чтобы защитить выполнение одной и той же команды за один раз. Это происходит, когда одна обработка занимает больше одной минуты. Я думаю, что я должен управлять ими, как демоны, но я ищу чистый способ сделать это с Django. Вы когда-нибудь сталкивались с этой проблемой или знает какие-либо чистое решение для этого?
4 ответов
мы делаем много фоновой обработки для django с использованием сельдерея http://celeryproject.org/. Это требует некоторых усилий для настройки, и есть немного кривой обучения, но как только он работает, это просто потрясающе.
мы взяли более простой подход-напишите сценарий как обычный скрипт с бесконечным циклом, который повторяется через queryset, а затем используйте supervise
управлять им как демоном. В принципе, все это необходимо для запуска демона: -
$ sudo apt-get install daemontools daemontools-run
$ mkdir /etc/service/sendmsevad
$ echo -> /etc/service/sendmsevad/run
#!/bin/bash
exec /usr/local/bin/sendmsgd
$ sudo svc -d /etc/service/sendmsgd
$ sudo svc -u /etc/service/sendmsgd
$ sudo svstat /etc/service/sendmsgd
/etc/service/sendmsg: up (pid 10521) 479 seconds
подробнее об этом - как демонизировать произвольный скрипт в unix?
теперь /usr/local/bin/sendmsgd
может выглядеть так:-
def main(args=None):
while True:
process_messages()
time.sleep(10)
if __name__ == '__main__':
import signal
def signal_handler(signal, frame):
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
main(sys.argv)
у меня есть некоторые проблемы с пониманием документации на сайте сельдереи. Я нашел этот сайт. Что хорошо объяснило ситуацию. У меня есть вещи, работающие над системой centos 6.2 с django-1.5+Celery-3.0.17+sqlite3. Единственная проблема у меня было найти ошибки модуля настройки мне нужно изменить его на "имя_моего_проекта.настроить."
Шаг 1. Сделайте следующий скрипт в /etc/default / celeryd . Обратите внимание, что вам нужно будет изменить некоторые содержимое в зависимости в вашей системе.
# Name of nodes to start, here we have a single node
CELERYD_NODES="w1"
# Where to chdir at start.
CELERYD_CHDIR="/var/www/some_folder/Myproject/"
# Python interpreter from environment, if using virtualenv
ENV_PYTHON="/somewhere/.virtualenvs/MyProject/bin/python"
# How to call "manage.py celeryd_multi"
CELERYD_MULTI="$ENV_PYTHON $CELERYD_CHDIR/manage.py celeryd_multi"
# How to call "manage.py celeryctl"
CELERYCTL="$ENV_PYTHON $CELERYD_CHDIR/manage.py celeryctl"
# Extra arguments to celeryd
CELERYD_OPTS="--time-limit=300 --concurrency=8"
# Name of the celery config module, don't change this.
CELERY_CONFIG_MODULE="celeryconfig"
# %n will be replaced with the nodename.
CELERYD_LOG_FILE="/var/log/celery/%n.log"
CELERYD_PID_FILE="/var/run/celery/%n.pid"
# Workers should run as an unprivileged user.
CELERYD_USER="celery"
CELERYD_GROUP="celery"
# Set any other env vars here too!
PROJET_ENV="PRODUCTION"
# Name of the projects settings module.
# in this case is just settings and not the full path because it will change the dir to
# the project folder first.
export DJANGO_SETTINGS_MODULE="settings"
Шаг 2. Сделайте скрипт ниже в /etc/default / celeryd и измените его разрешения с помощью
chmod +x /etc/init.d/celeryd
этот не нужно изменять. источник
#!/bin/sh -e
# ============================================
# celeryd - Starts the Celery worker daemon.
# ============================================
#
# :Usage: /etc/init.d/celeryd {start|stop|force-reload|restart|try-restart|status}
# :Configuration file: /etc/default/celeryd
#
# See http://docs.celeryq.org/en/latest/cookbook/daemonizing.html#init-script-celeryd
### BEGIN INIT INFO
# Provides: celeryd
# Required-Start: $network $local_fs $remote_fs
# Required-Stop: $network $local_fs $remote_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: celery task worker daemon
### END INIT INFO
#set -e
DEFAULT_PID_FILE="/var/run/celeryd@%n.pid"
DEFAULT_LOG_FILE="/var/log/celeryd@%n.log"
DEFAULT_LOG_LEVEL="INFO"
DEFAULT_NODES="celery"
DEFAULT_CELERYD="-m celery.bin.celeryd_detach"
# /etc/init.d/celeryd: start and stop the celery task worker daemon.
CELERY_DEFAULTS=${CELERY_DEFAULTS:-"/etc/default/celeryd"}
test -f "$CELERY_DEFAULTS" && . "$CELERY_DEFAULTS"
if [ -f "/etc/default/celeryd" ]; then
. /etc/default/celeryd
fi
CELERYD_PID_FILE=${CELERYD_PID_FILE:-${CELERYD_PIDFILE:-$DEFAULT_PID_FILE}}
CELERYD_LOG_FILE=${CELERYD_LOG_FILE:-${CELERYD_LOGFILE:-$DEFAULT_LOG_FILE}}
CELERYD_LOG_LEVEL=${CELERYD_LOG_LEVEL:-${CELERYD_LOGLEVEL:-$DEFAULT_LOG_LEVEL}}
CELERYD_MULTI=${CELERYD_MULTI:-"celeryd-multi"}
CELERYD=${CELERYD:-$DEFAULT_CELERYD}
CELERYCTL=${CELERYCTL:="celeryctl"}
CELERYD_NODES=${CELERYD_NODES:-$DEFAULT_NODES}
export CELERY_LOADER
if [ -n "" ]; then
CELERYD_OPTS="$CELERYD_OPTS "
fi
CELERYD_LOG_DIR=`dirname $CELERYD_LOG_FILE`
CELERYD_PID_DIR=`dirname $CELERYD_PID_FILE`
if [ ! -d "$CELERYD_LOG_DIR" ]; then
mkdir -p $CELERYD_LOG_DIR
fi
if [ ! -d "$CELERYD_PID_DIR" ]; then
mkdir -p $CELERYD_PID_DIR
fi
# Extra start-stop-daemon options, like user/group.
if [ -n "$CELERYD_USER" ]; then
DAEMON_OPTS="$DAEMON_OPTS --uid=$CELERYD_USER"
chown "$CELERYD_USER" $CELERYD_LOG_DIR $CELERYD_PID_DIR
fi
if [ -n "$CELERYD_GROUP" ]; then
DAEMON_OPTS="$DAEMON_OPTS --gid=$CELERYD_GROUP"
chgrp "$CELERYD_GROUP" $CELERYD_LOG_DIR $CELERYD_PID_DIR
fi
if [ -n "$CELERYD_CHDIR" ]; then
DAEMON_OPTS="$DAEMON_OPTS --workdir=\"$CELERYD_CHDIR\""
fi
check_dev_null() {
if [ ! -c /dev/null ]; then
echo "/dev/null is not a character device!"
exit 1
fi
}
export PATH="${PATH:+$PATH:}/usr/sbin:/sbin"
stop_workers () {
$CELERYD_MULTI stop $CELERYD_NODES --pidfile="$CELERYD_PID_FILE"
}
start_workers () {
$CELERYD_MULTI start $CELERYD_NODES $DAEMON_OPTS \
--pidfile="$CELERYD_PID_FILE" \
--logfile="$CELERYD_LOG_FILE" \
--loglevel="$CELERYD_LOG_LEVEL" \
--cmd="$CELERYD" \
$CELERYD_OPTS
}
restart_workers () {
$CELERYD_MULTI restart $CELERYD_NODES $DAEMON_OPTS \
--pidfile="$CELERYD_PID_FILE" \
--logfile="$CELERYD_LOG_FILE" \
--loglevel="$CELERYD_LOG_LEVEL" \
--cmd="$CELERYD" \
$CELERYD_OPTS
}
case "" in
start)
check_dev_null
start_workers
;;
stop)
check_dev_null
stop_workers
;;
reload|force-reload)
echo "Use restart"
;;
status)
$CELERYCTL status $CELERYCTL_OPTS
;;
restart)
check_dev_null
restart_workers
;;
try-restart)
check_dev_null
restart_workers
;;
*)
echo "Usage: /etc/init.d/celeryd {start|stop|restart|try-restart|kill}"
exit 1
;;
esac
exit 0
Шаг 3. Используйте эти команды для запуска, остановки и др. сценарий.
# to start celeryd
/etc/init.d/celeryd start
# to stop
/etc/init.d/celeryd stop
# see the status
/etc/init.d/celeryd status
# print the log in the screen
cat /var/log/celery/w1.log
если у вас возникли проблемы, на сайте была куча комментариев и других рекомендаций. Надеюсь, он долго не отключится.
вы можете попробовать использовать контроллер жир, который может взять любой сценарий и daemonise его. Он также может многократно запускать скрипты с интервалами, заданными в секундах, или даже без интервалов, поэтому он предотвратит одновременное выполнение двух экземпляров.
Он полностью написан на C, поэтому он очень стабилен, предназначен для работы в течение нескольких месяцев или лет подряд - независимо от того, насколько ваши собственные скрипты могут рухнуть. Также очень легко встать и побежать.
Это также может сделать гораздо больше вещей, таких как параллельный запуск скрипта, даже настройка количества параллельных экземпляров в соответствии с объемом работы, но я думаю, что это не соответствует вашим требованиям.
на сайте есть много вариантов использования и подробная инструкция. Если вам понадобится дополнительная помощь, просто свяжитесь с нами или отправьте запрос в службу поддержки, и я свяжусь с вами, как только смогу.
веб-сайт: http://fat-controller.sourceforge.net/