Ответы пользователя по тегу Celery
  • Резонно ли использовать один Celery для множества приложений?

    Assargin
    @Assargin
    Перед ответом смотрю наличие ✔ в ваших вопросах
    Celery - это штука, которая умеет выполнять некоторые, помеченные вами специальным декоратором функции, "где-то там", асинхронно, в N единиц параллельности, и т.д. Но ключевой момент в кодовой базе. Если вы можете выделить код заданий в отдельный проект, так, что эти функции-задания будут работать - смело прикручивайте к нему Celery, оборачивайте в контейнер - и вот у вас микросервис заданий.

    Однако лично я с таким не сталкивался, обычно кодовая база одна. В монолите на джанге ли, или в сервисе на фласке - задания писались мной так или иначе как часть одного или нескольких сервисов, и использовался код проекта: модели БД, либы.

    Вполне реален и нормален сценарий, когда вы монолит подробили, к примеру, на 5 микросервисов. Задания также растеклись по ним, оказавшись в 3 из 5 сервисов. Значит, к тем сервисам, в который есть задания, нужно рядом поднимать контейнера на тех же образах, уже в качестве воркеров заданий.
    Ответ написан
    Комментировать
  • Как организовать микро слипы в задаче celery?

    Assargin
    @Assargin
    Перед ответом смотрю наличие ✔ в ваших вопросах
    Явное указание ETA ради лимитирования - так себе механизм. Если воркер вдруг умрёт, то после перезапуска новому воркеру придут на выполнение сразу все "опоздавшие" задания, и чем дольше воркер лежал, тем больше будет пачка. Также, сложно регулировать проставление абсолютного значения ETA, если вдруг придётся делать это одновременно для нескольких потоков рассылок, чтобы они, выполняясь параллельно, не выбирали весь лимит.

    Ещё в Celery есть механизм rate limit на тип таска, правда, он работает только в пределах 1 воркера.

    Т.е. в тех нечастых случаях, когда на 1 очередь запускается более 1 воркера + для случаев, когда лимит с типом таска матчится не 1:1 (например, лимит на API общий, а методов в этом API может быть 100500, каждый дёргается с помощью отдельного типа таска) - есть реализация на основе token bucket.
    Ответ написан
    Комментировать
  • Что за магия в работе Celery с использованием Docker?

    Assargin
    @Assargin
    Перед ответом смотрю наличие ✔ в ваших вопросах
    Воу-воу, сам на днях буду переносить celery в docker.
    Но ваш вопрос немного не о том. Он скорее о понимании, как вообще работает celery.

    Неужели все содержимое такса каким-то образом передается через брокер и ему неважно, где располагается код? Или передается только имя+сигнатура.

    Только описание, какое задание надо выполнить, с какими входными параметрами. Никакого кода не передаётся.

    Возьмём Django + Celery.
    Типичный, описанный в документации и используемым самим celery для интеграции с django, шаблон использования таков: вы создаёте в django-приложениях файл tasks.py, в котором создаются функции, декорируемые @task. В этих функциях вы описываете логику этих заданий.

    В таком случае, веб-приложение и воркеры используют один и тот же код. И в контейнеры django_web и celery_worker надо упаковывать одно и то же. Просто запускаться это будет по разным сценариям: django_web будет обрабатывать http-запросы, celery_worker будет обрабатывать поступающие задания.
    Ответ написан
  • Как запускать Celery сразу с учетом виртуального окружения?

    Assargin
    @Assargin
    Перед ответом смотрю наличие ✔ в ваших вопросах
    Ну так, у вас в проекте, наверное, есть файл с зависимостями. requirements.txt, например. Где помимо прочих зависимостей, также должен быть прописан сельдерей нужной версии:
    ..
    celery==X.Y.Z 
    ..

    На проде одним из шагов вашего процесса релиза, наверное, является установка/обновление этих зависимостей:
    pip install -r /path/to/requirements.txt
    Следовательно, вы имеете в вашем venv'е установленный celery. Наверное.
    Ну и просто запускайте его оттуда, и всего делов. Тем же способом можно, просто путь до исполняемого файла будет указывать внутрь вашего виртуального окружения с проектом, типа:
    /path/to/virtualenv/bin/celery --params ....
    Ответ написан
    1 комментарий
  • Как сделать переодичные задачи с celery, выставляемые пользователем?

    Assargin
    @Assargin
    Перед ответом смотрю наличие ✔ в ваших вопросах
    В той же документации указывается на возможность написания своих классов шедулеров вместо дефолтного PersistentScheduler
    Там же пишут о django-celery-beat - удобном решении для админки, в котором можно редактировать расписание заданий.
    Ответ написан
    Комментировать
  • Демон в celery для django: какнастроить?

    Assargin
    @Assargin
    Перед ответом смотрю наличие ✔ в ваших вопросах
    Прежде всего хочу обратить внимание вот на это:
    Выбрал вариант с celeryd

    Если вы "выбирали" между celeryd или celerybeat, то тут выбор бессмысленен: celeryd - демон для выполнения заданий, celerybeat - следит за расписанием заданий, отправляя их в заданное время на выполнение. Так что, если у вас есть надобность выполнять задания по расписанию, настраивать надо оба демона.

    Теперь немного ответов на вопросы.

    CELERY_APP - что сюда вписывать?

    Это экземпляр класса celery.Celery, вот путь до него и надо прописать, в формате package[.subpackages].module:variable. Например, у меня есть файл project/celery.py, в котором создаётся экземпляр таким образом:
    from celery import Celery
    
    app = Celery('project')

    И я впишу в CELERY_APP значение project.celery:app
    У вас наверняка подобный код тоже есть в проекте, если вы делали по документации

    И как создать celery-пользователя? Погуглил, но не понял ответа.

    Я для всего проекта использую одного пользователя, того, под которым django выполняется (у меня webapp)

    И почему CELERYD_CHDIR="/opt/Myproject/"? Так и не понял, зачем нужен редирект куда-то (а я так понял, это адрес, куда переместиться во время работы). Зачем это нужно и помешает ли сохранять получаемые данные (сохранять изображения в папках) по относительным адресам в django-проекте?

    Эту опцию не использую, вместо неё у меня используется WorkingDirectory на уровне systemd, но смысл абсолютно тот же.
    Это не редирект, это просто указание рабочей папки, относительно которой будет запускаться ваш демон. При правильной настройке работа проекта в режиме celery-воркера ничем не должна отличаться от работы проекта в веб-режиме. На уровне кода никаких ветвлений на тему "если я демон - то делай так, а если нет - делай эдак" быть не должно (и я даже не знаю, как их вообще делать).

    CELERY_BIN="/usr/local/bin/celery"
    Прошел по пути, никакого celery там не увидел.

    Ну блин, куда вы установите celery, там его исполняемый файл и будет. Например, у меня все python-зависимости, куда входит и celery, установлены в virtual env'е, и путь до него такой: /home/webapp/Env/project-backend-3.5/bin/celery

    2. Что делать после настройки? В документации указано что-то про django-настройки и пояснено значение переменных, прилагается несколько кусков кода, но даже с переводчиком не могу понять их назначения.

    Что делать после того, как я сделаю оба файла celeryd пригодными для работы?

    После настройки - запускать, тестировать, отлаживать. Всё как обычно.

    CELERYD_SU_ARGS="-l"
    Что это? Зачем это?

    Не знаю, и видимо, не нужно. Там даже написано, что не рекомендуется.

    Вот мои конфиги (для systemd), делал на основе конфигов из официальной репы celery.

    Файл сервиса celeryd (/etc/systemd/system/celery.service):
    [Unit]
    Description=Celery Service
    After=network.target redis.target
    
    [Service]
    Type=forking
    User=webapp
    Group=webapp
    EnvironmentFile=-/etc/systemd/celery.conf
    WorkingDirectory=/home/webapp/project_dir/project/src
    PermissionsStartOnly=true
    ExecStartPre=-/bin/mkdir -p ${CELERYD_STATE_DIR}
    ExecStartPre=/bin/chown -R ${CELERYD_USER}:${CELERYD_GROUP} ${CELERYD_STATE_DIR}
    ExecStart=/bin/sh -c '${CELERY_BIN} multi start \
        ${CELERYD_NODES} \
        -A ${CELERY_APP} \
        --pidfile=${CELERYD_PID_FILE} \
        --logfile=${CELERYD_LOG_FILE} \
        --loglevel=${CELERYD_LOG_LEVEL} \
        ${CELERYD_OPTS}'
    ExecStop=/bin/sh -c '${CELERY_BIN} multi stopwait \
        ${CELERYD_NODES} \
        --pidfile=${CELERYD_PID_FILE}'
    ExecReload=/bin/sh -c '${CELERY_BIN} multi restart \
        ${CELERYD_NODES} \
        -A ${CELERY_APP} \
        --pidfile=${CELERYD_PID_FILE} \
        --logfile=${CELERYD_LOG_FILE} \
        --loglevel=${CELERYD_LOG_LEVEL} \
        ${CELERYD_OPTS}'
    
    [Install]
    WantedBy=multi-user.target


    Файл сервиса celerybeat (/etc/systemd/system/celerybeat.service):
    [Unit]
    Description=CeleryBeat Service
    After=network.target redis.target rabbitmq.target
    
    [Service]
    Type=simple
    User=webapp
    Group=webapp
    EnvironmentFile=-/etc/systemd/celery.conf
    WorkingDirectory=/home/webapp/project_dir/project/src
    PermissionsStartOnly=true
    ExecStartPre=-/bin/mkdir -p ${CELERYBEAT_STATE_DIR}
    ExecStartPre=/bin/chown -R ${CELERYD_USER}:${CELERYD_GROUP} ${CELERYBEAT_STATE_DIR}
    ExecStartPre=/bin/rm ${CELERYBEAT_SCHEDULE}
    ExecStart=/bin/bash -c '${CELERY_BIN} beat \
        -A ${CELERY_APP} \
        --workdir=${CELERYBEAT_WORKDIR} \
        --pidfile=${CELERYBEAT_PID_FILE} \
        --logfile=${CELERYBEAT_LOG_FILE} \
        --loglevel=${CELERYBEAT_LOG_LEVEL} \
        --schedule=${CELERYBEAT_SCHEDULE}'
    ExecStop=/bin/systemctl kill celerybeat.service
    
    [Install]
    WantedBy=multi-user.target


    Файл конфигурации сервисов celeryd и celerybeat (/etc/systemd/celery.conf):
    # See
    # http://docs.celeryproject.org/en/latest/tutorials/daemonizing.html#available-options
    
    # Common Celery Settings
    CELERY_BIN="/home/webapp/Env/project-backend-3.5/bin/celery"
    CELERYD_USER="webapp"
    CELERYD_GROUP="webapp"
    CELERY_APP="project.celery:app"
    
    # Common env settings
    DJANGO_SETTINGS_MODULE=settings.production
    LC_ALL=ru_RU.UTF-8
    LC_LANG="ru_RU.UTF-8"
    LANG=ru_RU.UTF-8
    
    # Worker settings
    CELERYD_NODES="w1 w2 w3 w4 w5 w6"
    CELERYD_OPTS="-Q:w1 default --autoscale:w1=8,4 \
    -Q:w2 queue2 --autoscale:w2=6,2   \
    -Q:w3 queue3 --autoscale:w3=8,2 \
    ....................
    -Q:w6 queue6 --autoscale:w6=6,2       "
    
    CELERYD_MULTI="multi"
    CELERYD_STATE_DIR="/var/run/celery"
    CELERYD_PID_FILE="/var/run/celery/%n.pid"
    CELERYD_LOG_FILE="/var/log/celery/%n.log"
    CELERYD_LOG_LEVEL="INFO"
    
    # Beat settings
    CELERYBEAT_STATE_DIR="/var/run/celerybeat"
    CELERYBEAT_PID_FILE="/var/run/celerybeat/beat.pid"
    CELERYBEAT_LOG_FILE="/var/log/celery/beat.log"
    CELERYBEAT_LOG_LEVEL="INFO"
    CELERYBEAT_SCHEDULE="/var/run/celerybeat/schedule"
    CELERYBEAT_WORKDIR="/home/webapp/project_dir/project/src"
    Ответ написан
    5 комментариев
  • Может ли Celery писать результат в бд на другом хосте?

    Assargin
    @Assargin
    Перед ответом смотрю наличие ✔ в ваших вопросах
    Сам недавно разворачивал Celery. Пока тоже всё крутится на одном сервере.
    1. Ваша БД, с которой работает django-проект, и celery result backend - вещи разные. Последнее - это, грубо говоря, хранилище для значений, которые вы можете вернуть из отложенного задания. А БД проекта - это БД проекта, хотя и может так же выполнять функцию result backend'а. Кстати, вы можете вообще не использовать result backend, если не вам не требуется что-то возвращать из заданий.
    2. Рабочие процессы вашего django-проекта и celery-воркеры - одно и то же, только запущенное через разные точки входа. Для веба - это, скорее всего, wsgi.py, для celery, к примеру, celery.py.
    3. Чтобы запустить воркеры на 2м сервере (вместо 1го или в дополнение к нему), вам нужно будет развернуть ваш проект на нем, и сделать всё то же самое, что и на 1м сервере, чтобы заработали celery-воркеры.
    4. помимо подключения в БД, вам также нужно будет озаботиться подключением к брокеру и result backend'у (если используете его). В самом простом случае, как мне видится, никаких IP не надо будет менять - зачем, если сервер БД у вас один, и находится на 1м сервере. Ну разве что вместо 127.0.0.1 нужно будет прописать нормальный адрес.
    Ответ написан
    Комментировать