APScheduler выполняется несколько раз для количества рабочих gunicorn
У меня есть проект django со встроенным в него APScheduler. Сейчас я перешел к производственной среде, поэтому связал его с gunicorn и nginx в процессе работы. Gunicorn имеет 3 рабочих. Проблема в том, что gunicorn инициирует APScheduler для каждого рабочего и запускает запланированное задание 3 раза вместо того, чтобы запустить его только один раз.
Я видел подобные вопросы здесь, похоже, это распространенная проблема. Даже оригинальная документация APScheduler признает эту проблему и не говорит о способе ее устранения.
Я видел в других темах, что люди рекомендовали ставить --preconfig в настройках. Но я читал, что --preconfig инициирует работу с текущим кодом и не перезагружает его, если в коде произошли изменения. (См. "Когда не стоит перезагружать" в ссылке ниже)
https://www.joelsleppy.com/blog/gunicorn-application-preloading/
Я также видел, что кто-то рекомендовал привязать TCP сокет для APScheduler. Я не понял до конца, но в основном он пытался привязать сокет каждый раз, когда инициируется APScheduler, затем второй и третий рабочий попадает на этот привязанный сокет и выбрасывает ошибку сокета. Вроде того
try:
"bind socket somehow"
except socketerror:
print("socket already exists")"
else:
"run apscheduler module"
конфигурация. Кто-нибудь знает, как это сделать или знает, будет ли это действительно работать?
Другой обходной путь, о котором я подумал, это просто удалить APScheduler и сделать это с помощью функции cron на сервере. Я использую Digital Ocean, поэтому я могу просто удалить APScheduler и запустить вместо него функцию cron, которая будет запускать модуль. Однако я не хочу идти таким путем, потому что это нарушит "единство" всего проекта и сделает его зависимым от сервера. Есть ли у кого-нибудь еще идеи?
Модуль расписания:
from apscheduler.schedulers.background import BackgroundScheduler
from RENDER.views import dailypuzzlefunc
def start():
scheduler=BackgroundScheduler()
scheduler.add_job(dailypuzzlefunc,'cron', day="*",max_instances=2,id='dailyscheduler')
scheduler.start()
В приложении:
from django.apps import AppConfig
class DailypuzzleConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "DAILYPUZZLE"
def ready(self):
from SCHEDULER import dailypuzzleschedule
dailypuzzleschedule.start()
web:
python manage.py collectstatic --no-input;
gunicorn MasjidApp.wsgi --timeout 15 --preload
use --preload.
Для меня это работает хорошо.