2014-09-03 5 views
21

Sto costruendo un sito web che fornisce alcune informazioni ai visitatori. Queste informazioni vengono aggregate in background eseguendo il polling di un paio di API esterne ogni 5 secondi. Il modo in cui lo faccio adesso è che io uso i lavori APScheduler. Inizialmente ho preferito APScheduler perché rende l'intero sistema più facile da portare (dato che non ho bisogno di impostare i lavori cron sulla nuova macchina). Comincio le funzioni di polling come segue:Come eseguire attività ricorrenti nel framework 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) 

Questo funziona un pò, ma c'è qualche problema con esso:

  1. Per cominciare, questo significa che l'intervallo-posti di lavoro sono in esecuzione al di fuori del contesto Flask. Finora questo non è stato un grosso problema, ma quando si chiama un endpoint fallisce, voglio che il sistema mi invii un'email (dicendo "hey chiama API X non riuscita"). Poiché non viene eseguito all'interno del contesto Flask, tuttavia, si lamenta che non è possibile eseguire flask-mail (RuntimeError('working outside of application context')).
  2. In secondo luogo, mi chiedo come si comporterà quando non uso più il server di debug integrato di Flask, ma un server di produzione con diciamo 4 lavoratori. Inizierà ogni lavoro quattro volte?

Tutto sommato, sento che dovrebbe esserci un modo migliore per eseguire questi compiti ricorrenti, ma non so come. Qualcuno là fuori ha una soluzione interessante a questo problema? Tutti i suggerimenti sono ben accetti!

[EDIT] Ho appena letto su Celery con il suo schedules. Anche se non vedo davvero come Celery sia diverso da APScheduler e se sia in grado di risolvere i miei due punti, mi chiedo se qualcuno che legge questo pensi che dovrei investigare di più su Celery?

[CONCLUSION] Circa due anni dopo sto leggendo questo, e ho pensato di poterti far sapere ai ragazzi cosa ho finito. Ho capito che @BluePeppers aveva ragione nel dire che non dovevo essere legato così strettamente all'ecosistema di Flask. Quindi ho optato per i normali cron-job in esecuzione ogni minuto che sono impostati usando Ansible. Anche se questo lo rende un po 'più complesso (avevo bisogno di imparare Ansible e convertire un po' di codice in modo tale che eseguirlo ogni minuto sarebbe sufficiente) Penso che questo sia più robusto. Attualmente sto usando il fantastico pythonr-rq per l'accodamento dei lavori di sincronizzazione a (controllo delle API e invio di e-mail). Ho appena saputo di rq-scheduler. Non l'ho ancora provato, ma sembra proprio quello di cui avevo bisogno in primo luogo. Quindi forse questo è un consiglio per i futuri lettori di questa domanda.

Per il resto, auguro a tutti voi una bella giornata!

risposta

22

(1)

È possibile utilizzare il gestore app.app_context() contesto per impostare il contesto di applicazione. Immagino che l'uso sarebbe andato qualcosa come questo:

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) 

In alternativa, è possibile utilizzare un decoratore

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)

sì che lo farà ancora funzionare. La sola (significativa) differenza è che la tua applicazione non comunicherà direttamente con il mondo; passerà attraverso un proxy inverso o qualcosa via fastcgi/uwsgi/qualunque.L'unica preoccupazione è che se si hanno più istanze dell'app che iniziano, verranno creati più scheduler. Per gestirlo, suggerisco di spostare le attività di back-end dall'applicazione Flask e utilizzare uno strumento progettato per eseguire le attività regolarmente (ad esempio Celery). Il rovescio della medaglia di questo è che non sarete in grado di usare cose come Flask-Mail, ma imo, non è troppo bello essere così strettamente legati all'ecosistema di Flask; cosa stai ottenendo usando Flask-Mail su una libreria di posta standard, non Flask,?

Inoltre, suddividere l'applicazione rende molto più semplice scalare i singoli componenti in base alla capacità richiesta, rispetto all'utilizzo di un'applicazione Web monolitica.

+0

Grazie per la tua risposta elaborata. Un'ultima cosa; dal momento che APScheduler funziona perfettamente, quale pensi sarebbe il vantaggio di usare Celery su APScheduler? Quale sarebbe la tua scelta e perché? – kramer65

+0

Well Celery offre molto di più della semplice programmazione. Detto questo, non so molto di APScheduler, e leggendo i documenti ora, sembra perfettamente a posto. – BluePeppers

+0

Trovo questo post molto utile. Ma mi piacerebbe chiedere, sto usando un database SQL per la mia applicazione che di APScheduler o di Celery sarebbe più adatto per l'uso? Posso vedere redis in Celery. Vado invece su APScheduler? – clementiano

Problemi correlati