2014-09-03 9 views
21

Buduję stronę internetową, która dostarcza informacji dla odwiedzających. Informacje te są agregowane w tle przez odpytywanie kilku zewnętrznych interfejsów API co 5 sekund. Sposób, w jaki teraz działam, polega na tym, że używam zadań APScheduler. Początkowo preferowałem APScheduler, ponieważ ułatwia on portowanie całego systemu (ponieważ nie muszę ustawiać zadań crona na nowej maszynie). Zacznę funkcji wyborczych następująco:Jak uruchomić cykliczne zadanie w frameworku Python Flask?

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) 

to trochę działa, ale istnieją pewne problemy z nim:

  1. Na początek, oznacza to, że przedział zadania są uruchomione poza kontekstem kolby. Jak dotąd nie stanowiło to większego problemu, ale gdy wywołanie punktu końcowego kończy się niepowodzeniem, chcę, aby system wysłał do mnie e-mail (mówiąc "hej wywołanie API X nie powiodło się"). Ponieważ jednak nie działa w kontekście Flask, skarży się, że nie można wykonać flask-mail (RuntimeError('working outside of application context')).
  2. Po drugie, zastanawiam się, jak to się będzie zachowywać, kiedy nie używam już wbudowanego serwera debugującego Flask, ale serwer produkcyjny z powiedzmy 4 pracownikami. Czy zacznie wtedy cztery razy każdą pracę?

Podsumowując, uważam, że powinien istnieć lepszy sposób wykonywania powtarzających się zadań, ale nie jestem pewien, jak to zrobić. Czy ktoś ma interesujące rozwiązanie tego problemu? Wszystkie wskazówki są mile widziane!

[edycja] Właśnie czytałem o Celery z jego schedules. Chociaż tak naprawdę nie widzę, jak Seler różni się od APSchedulera i czy może w ten sposób rozwiązać moje dwa punkty, zastanawiam się, czy ktokolwiek to czyta myśli, że powinienem zbadać więcej w Selerach?

[WNIOSKI] Około dwa lata później czytam to i pomyślałem, że mogę wam powiedzieć, co mnie spotkało. Pomyślałem, że @BluePeppers miał rację mówiąc, że nie powinienem być tak blisko związany z ekosystemem Flask. Dlatego zdecydowałem się na regularne zadania cron uruchamiane co minutę, które są ustawiane za pomocą Ansible. Chociaż to sprawia, że ​​jest nieco bardziej złożona (muszę nauczyć się Ansible i przekonwertować kod, żeby wystarczyło go co minutę) Myślę, że jest to bardziej niezawodne. Obecnie używam niesamowitego pythonr-rq do kolejkowania zadań synchronizacji (sprawdzanie interfejsów API i wysyłanie wiadomości e-mail). Właśnie dowiedziałem się o rq-scheduler. Jeszcze tego nie testowałem, ale wydaje mi się, że robię dokładnie to, czego potrzebowałem. Być może jest to wskazówka dla przyszłych czytelników tego pytania.

Co do reszty, po prostu życzę wszystkim pięknego dnia!

Odpowiedz

22

(1)

Można użyć menedżera app.app_context() kontekstowego aby ustawić kontekst aplikacji. Wyobrażam Wykorzystanie pójdzie coś takiego:

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) 

Alternatywnie, można użyć dekorator

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)

Tak będzie nadal działać. Jedyną (znaczącą) różnicą jest to, że twoja aplikacja nie będzie komunikować się bezpośrednio ze światem; będzie przechodzić przez odwrotne proxy lub coś przez fastcgi/uwsgi/cokolwiek.Jedynym problemem jest to, że jeśli uruchomisz wiele instancji aplikacji, zostanie utworzonych wiele programów planujących. Aby sobie z tym poradzić, sugerowałbym przeniesienie zadań backendu z aplikacji Flask i użycie narzędzia zaprojektowanego do regularnego wykonywania zadań (np. Seler). Wadą tego jest to, że nie będziesz w stanie używać rzeczy takich jak Flask-Mail, ale imo, nie jest zbyt dobrze, aby być tak blisko związanym z ekosystemem Flask; co zyskujesz, używając Flask-Mail przez standardową bibliotekę pocztową?

Ponadto rozdzielenie aplikacji znacznie ułatwia skalowanie poszczególnych komponentów, ponieważ wymagana jest pojemność, w porównaniu do jednej monolitycznej aplikacji internetowej.

+0

Dziękuję za wyczerpującą odpowiedź. Ostatnia rzecz; ponieważ APScheduler działa doskonale, jak myślisz, co może być zaletą korzystania z Celery przez APScheduler? Jaki byłby twój wybór i dlaczego? – kramer65

+0

Well Celery oferuje znacznie więcej niż proste planowanie. Powiedziawszy to, nie wiem zbyt wiele o APScheduler, a czytanie dokumentów teraz wygląda doskonale. – BluePeppers

+0

Uważam ten wpis za bardzo przydatny. Ale chciałbym zapytać, używam bazy danych SQL dla mojej aplikacji, która z APScheduler lub Selera byłaby bardziej odpowiednia do użycia? Widzę czerwone w Selerach. Czy zamiast tego wybieram APScheduler? – clementiano

Powiązane problemy