Sto pianificando un servizio web per alcuni modelli computazionali. Una volta formati, i modelli sono in genere piuttosto leggeri, ma a volte è necessario eseguire un calcolo pesante per aggiornare i modelli su cui si basano i calcoli della luce. Inoltre, ci può essere (eventualmente) una quantità arbitraria di questi modelli.
In fase di produzione, questo servizio sarà ospitato in contenitori Docker identici e sarebbe utile poter distribuire più contenitori per poter servire più richieste contemporaneamente. Docker ha il supporto per il collegamento di più contenitori allo stesso volume (cartella esterna), in modo che le richieste di gestione dei contenitori possano essere collegate a una comune per ottenere risultati coerenti. Nessun problema lì.
Problema
L'aggiornamento di un modello richiede al massimo decine di minuti, quindi aspettare che finisca prima di rispondere a una richiesta non sembra giusto. E quando viene avviato un aggiornamento, se ci sono altri contenitori, non c'è modo di sapere quale sta facendo l'allenamento o anche se è stato fatto. Quindi altri contenitori potrebbero avviare lo stesso processo se la richiesta viene ripetuta, affamando efficacemente l'intero servizio.
Idea
Quindi il mio pensiero era questo: facciamo in modo che i contenitori elaborino le richieste più leggere e accolgano le pesanti richieste di aggiornamento, ma le pubblichino in una coda di qualche tipo. Quindi, dopo aver terminato, gli altri contenitori consumano da quella coda e aggiornano i modelli su disco.
I diversi tipi di contenitori devono avere un canale di comunicazione coerente e sincronizzato. Il mio primo pensiero era solo quello di scrivere la coda su un file nel volume, ma la mia intuizione mi dice che non è abbastanza. Così ho iniziato a evocare un altro tipo di servizio, che accetterebbe richieste di aggiornamento dai contenitori di base e li invierò. I contenitori pesanti informerebbero poi il dispatcher quando un lavoro è completato.
È un design sensato?
Ho trovato cose del tipo:
inteso per alcune attività in coda di attesa. Ma non ho esperienza con loro. Avrebbero fatto il lavoro più facilmente, o una auto-implementazione sarebbe stata più adatta a questo? Inoltre, mi chiedo, se il multiprocessing Python di base possa essere utilizzato per l'attività. Ma questo solleva un problema quando si usano più contenitori, e non sono sicuro di cosa pensare di questo.
Aggiornamento
È stato abbastanza semplice implementare una coda che combina multiprocessing.Queue
e multiprocessing.Process
in un singolo server che genera figli per elaborare i lavori. L'ho fatto come esempio in Python documentazione (esempi in basso) lo ha fatto, modificando qui e là. Ora posso collegarlo a un'altra porta per servire accanto al sistema principale. Quindi sembra funzionare per ora.