Domanda

Un'applicazione web sto sviluppando necessità di svolgere compiti che sono troppo lunghi per essere eseguito durante il ciclo http richiesta / risposta. In genere, l'utente effettuerà la richiesta, il server avrà questa richiesta e, tra le altre cose, eseguire alcuni script per generare dati (ad esempio, il rendering di immagini con Povray).

Naturalmente, queste attività possono richiedere molto tempo, in modo che il server non dovrebbe appendere per gli script per completare l'esecuzione prima di inviare la risposta al client. Ho quindi bisogno di eseguire l'esecuzione degli script asincrono, e dare al cliente un "la risorsa è qui, ma non è pronto" e, probabilmente, dire che un endpoint ajax per interrogare, in modo che possa recuperare e visualizzare la risorsa quando è pronto.

Ora, la mia domanda non è relativo alla progettazione (anche se mi piacerebbe molto godere di alcun suggerimento su questo proposito pure). La mia domanda è: non un sistema per risolvere questo problema esiste già, quindi non reinventare la ruota quadrata? Se dovessi, vorrei utilizzare un gestore code processo di presentare l'attività e mettere un endpoint HTTP a sparare fuori lo stato, qualcosa come "in sospeso", "interrotta", "completato" al client Ajax, ma se qualcosa di simile già esiste appositamente per questo compito, io per lo più goderne.

Sto lavorando in Python + Django.

Modifica :. Si prega di notare che il problema principale qui non è come il server e il client devono negoziare e scambiare informazioni sullo stato del compito

Il problema è come il server gestisce la presentazione e l'accodamento dei compiti molto lunghi. In altre parole, ho bisogno di un sistema di meglio che avere il mio server presentare gli script su LSF . Non che non avrebbe funzionato, ma penso che sia un po 'troppo ...

Modifica 2 : ho aggiunto una taglia per vedere se riesco a ottenere qualche altra risposta. Ho controllato pyprocessing, ma non riesco a eseguire la presentazione di un lavoro e ricollegare alla coda in una fase successiva.

È stato utile?

Soluzione

Si dovrebbe evitare di reinventare la ruota qui.

Gearman . Ha le biblioteche in molte lingue (tra cui Python) ed è abbastanza popolare. Non so se qualcuno ha qualche fuori dalla scatola modi per collegare facilmente fino a Django Gearman e le chiamate Ajax, ma non dovrebbe essere complicato fare per farlo parte da soli.

L'idea di base è che si corre il server di lavoro Gearman (o più server di posti di lavoro), hanno la coda di richiesta web un lavoro (come 'resize_photo') con alcuni argomenti (come '{photo_id 1234}'). Si coda questo come attività in background. È possibile ottenere una maniglia posteriore. La tua richiesta Ajax è quindi andando a sondaggio su tale valore maniglia finché non è contrassegnato come completo.

Poi ci sono un lavoratore (o probabilmente molti) che è un processo python separata collegare fino a questo server di lavoro e si registra per i lavori 'resize_photo', fa il lavoro e quindi lo contrassegna come completata.

Ho trovato anche questo post sul blog che fa un buon lavoro riassumendo è l'utilizzo.

Altri suggerimenti

È possibile provare due approachs:

  • chiamata webserver ogni n intervallo e informare un id lavoro; server di processi e restituire alcune informazioni su esecuzione corrente di tale compito
  • Per implementare una pagina di corsa lunga, l'invio di dati ogni n intervallo; per il cliente, che la richiesta HTTP sarà "sempre" essere "loading" e ha bisogno di raccogliere nuove informazioni ogni volta che un nuovo pezzo di dati ricevuto.

A proposito seconda opzione, è possibile saperne di più leggendo su Comet ; Utilizzando ASP.NET, si può fare qualcosa simile mediante l'attuazione di sistema. Web.IHttpAsyncHandler interfaccia.

Non so di un sistema che lo fa, ma sarebbe abbastanza facile da implementare il proprio sistema:

  • creare una tabella di database con jobid, jobparameters, jobresult
    • jobresult è una stringa che conterrà una salamoia del risultato
    • jobparameters è una lista in salamoia di argomenti di input
  • quando il server inizia a lavorare su un lavoro, crea una nuova riga nella tabella, e spwans un nuovo processo per la gestione che, per inciso, che il processo di jobid
  • il processo gestore compito aggiorna il jobresult nella tabella quando ha finito
  • una pagina web (XMLRPC o qualsiasi altra cosa che si sta utilizzando) contiene un metodo 'getResult (jobid)' che controllerà il tavolo per un jobresult
    • se trova una conseguenza, restituisce il risultato, ed elimina la riga dalla tabella
    • altrimenti restituisce una lista vuota, o nessuno, o il vostro valore di ritorno preferito per segnalare che il lavoro non è ancora finito

Ci sono alcuni edge-casi di prendersi cura di così un quadro esistente sarebbe chiaramente meglio come dici tu.

In un primo momento, è necessario un po 'di servizio separato "lavoratore", che sarà avviato a parte all'accensione e comunicata con http-gestori delle richieste tramite alcuni IPC locale come UNIX-socket (veloce) o un database (semplice).

Durante la manipolazione richiesta cgi chiedere da statale lavoratore o altri dati e riprodurre al cliente.

È possibile segnalare che una risorsa è in fase di "lavorato" rispondendo con un codice 202 HTTP: il lato client dovrà riprovare più tardi per ottenere la risorsa completata. A seconda dei casi, potrebbe essere necessario emettere una "richiesta di id" al fine di corrispondere una richiesta con una risposta.

In alternativa, si potrebbe avere uno sguardo a librerie COMET esistenti che potrebbero riempire le vostre esigenze più "out of the box". Non sono sicuro se ci sono che corrispondono al disegno corrente Django però.

Probabilmente non è una grande risposta per la soluzione di pitone / django si sta lavorando, ma usiamo Microsoft Message Queue per le cose proprio come questo. Funziona fondamentalmente come questo

  1. Sito aggiorna una riga di database da qualche parte con un "trattamento" status
  2. sito web invia un messaggio al MSMQ (questa è una chiamata non bloccante quindi ritorna il controllo al sito subito)
  3. servizio di Windows (potrebbe essere qualsiasi programma realmente) è "guardando" il MSMQ e ottiene il messaggio
  4. servizio di Windows aggiorna il database di fila con uno stato "Finito".

Questa è l'essenza di esso comunque. E 'stato abbastanza affidabile per noi e davvero semplice da scalare e gestire.

-al

Un'altra buona opzione per Python e Django è sedano .

E se si pensa che sedano è troppo pesante per le vostre esigenze allora si potrebbe desiderare di guardare semplice distribuito TaskQueue service .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top