2014-09-03 3 views
21

Я создаю веб-сайт, который предоставляет некоторую информацию посетителям. Эта информация агрегируется в фоновом режиме путем опроса нескольких внешних API каждые 5 секунд. Теперь у меня это работает, так что я использую APScheduler рабочих мест. Сначала я предпочел APScheduler, потому что он упрощает работу всей системы (поскольку мне не нужно задавать задания cron на новой машине). Я начинаю функции опроса следующим образом:Как запустить повторяющуюся задачу в фреймворке Python?

from apscheduler.scheduler import Scheduler 

@app.before_first_request 
def initialize(): 
    apsched = Scheduler() 
    apsched.start() 

    apsched.add_interval_job(checkFirstAPI, seconds=5) 
    apsched.add_interval_job(checkSecondAPI, seconds=5) 
    apsched.add_interval_job(checkThirdAPI, seconds=5) 

Это своего рода работает, но есть некоторые проблемы с ним:

  1. Для начала, это означает, что интервал-рабочие работают вне контекста Колба. До сих пор это не было большой проблемой, но когда вы вызываете конечную точку, я хочу, чтобы система отправила мне электронное письмо (говоря «эй, вызвав API X не удалось»). Поскольку он не работает в контексте Flask, он жалуется, что flask-mail не может быть выполнен (RuntimeError('working outside of application context')).
  2. Во-вторых, мне интересно, как это будет вести себя, когда я больше не использую встроенный отладочный сервер Flask, а производственный сервер с разрешением 4 рабочих. Будет ли она начинать каждую работу четыре раза?

В целом я чувствую, что должен быть лучший способ запуска этих повторяющихся задач, но я не уверен, как это сделать. У кого-нибудь есть интересное решение этой проблемы? Все советы приветствуются!

[EDIT] Я только что читал о Celery с его schedules. Хотя я действительно не вижу, как сельдерей отличается от APScheduler и может ли он таким образом решить мои две точки, мне интересно, читает ли кто-нибудь, что я должен исследовать больше в сельдере?

[ЗАКЛЮЧЕНИЕ] Примерно через два года я читаю это, и я подумал, что могу дать вам понять, что у меня получилось. Я понял, что @BluePeppers прав, говоря, что я не должен так тесно привязываться к экосистеме Flask. Поэтому я выбрал регулярные задания cron, выполняемые каждую минуту, которые устанавливаются с использованием Ansible. Хотя это делает его немного сложнее (мне нужно было изучить Ansible и преобразовать какой-то код, чтобы его можно было запускать каждую минуту). Я думаю, что это более надежный. В настоящее время я использую awesome pythonr-rq для очередей заданий синхронизации (проверка API и отправка электронной почты). Я только что узнал о rq-scheduler. Я еще не тестировал его, но, похоже, именно то, что мне нужно, в первую очередь. Так что, возможно, это подсказка для будущих читателей этого вопроса.

Для отдыха я просто желаю вам прекрасного дня!

ответ

22

(1)

Вы можете использовать менеджер app.app_context() контекста, чтобы установить контекст приложения. Я полагаю, использование бы что-то вроде этого:

from apscheduler.scheduler import Scheduler 

def checkSecondApi(): 
    with app.app_context(): 
     # Do whatever you were doing to check the second API 

@app.before_first_request 
def initialize(): 
    apsched = Scheduler() 
    apsched.start() 

    apsched.add_interval_job(checkFirstAPI, seconds=5) 
    apsched.add_interval_job(checkSecondAPI, seconds=5) 
    apsched.add_interval_job(checkThirdAPI, seconds=5) 

В качестве альтернативы, вы можете использовать декоратор

def with_application_context(app): 
    def inner(func): 
     @functools.wraps(func) 
     def wrapper(*args, **kwargs): 
      with app.app_context(): 
       return func(*args, **kwargs) 
     return wrapper 
    return inner 

@with_application_context(app) 
def checkFirstAPI(): 
    # Check the first API as before 

(2)

Да он все равно будет работать. Единственная (значительная) разница заключается в том, что ваше приложение не будет напрямую общаться с миром; он будет проходить через обратный прокси-сервер или что-то через fastcgi/uwsgi/whatever.Единственное беспокойство заключается в том, что если у вас запущено несколько экземпляров приложения, будут созданы несколько планировщиков. Чтобы справиться с этим, я предлагаю вам переместить свои backend-задачи из приложения Flask и использовать инструмент, предназначенный для регулярного выполнения задач (например, Celery). Недостатком этого является то, что вы не сможете использовать такие вещи, как Flask-Mail, но imo, не слишком хорошо быть настолько тесно связанными с экосистемой Flask; что вы получаете, используя Flask-Mail над стандартной, не флягой, почтовой библиотекой?

Кроме того, разбивка приложения значительно упрощает масштабирование отдельных компонентов по мере необходимости, по сравнению с одним монолитным веб-приложением.

+0

Благодарим вас за подробный ответ. Одна последняя вещь; так как APScheduler работает отлично, как вы считаете, преимущество использования Celery над APScheduler? Что бы вы выбрали и почему? – kramer65

+0

Ну сельдерей предлагает вам гораздо больше, чем простое планирование. С учетом сказанного, я мало что знаю о APScheduler и читаю документы сейчас, это выглядит отлично. – BluePeppers

+0

Я считаю этот пост очень полезным. Но я хотел бы спросить, я использую базу данных SQL для своего приложения, которое из APScheduler или Celery было бы более подходящим для использования? Я вижу redis в Сельдерей. Вместо этого я иду на APScheduler? – clementiano

Смежные вопросы