Programmazione di attività distribuita in modo corretto con RabbitMQ

6

Problema: un singolo client del nostro sistema può riempire completamente tutte le risorse disponibili con un enorme carico di lavoro. Puoi considerare di avere solo una coda, e chiunque può pianificare qualsiasi quantità di lavoro al suo interno. Qualsiasi altro cliente che successivamente invierà una piccola quantità di lavoro dovrà attendere fino a quando le prime attività saranno state completamente trattate. È un sistema asincrono quindi non ci sarà alcun rischio per DOS. Il problema che vorremmo risolvere è consentire ai nostri clienti di avere una buona dose di elaborazione in qualsiasi momento, indipendentemente dal fatto che alcuni clienti abbiano inviato molto lavoro. È un sistema distribuito con una buona quantità di lavoratori, tutto il lavoro è suddiviso in piccoli pezzi in modo che le attività scorrano correttamente attraverso il sistema.

Questo mi sembra un problema molto comune e sono un po 'allarmato dal fatto che non trovo una soluzione molto semplice. È simile alla pianificazione dei processi in un sistema operativo in quanto i processi sono dotati di slot di elaborazione in modalità round robin, nessun processo può preschedule un sacco di lavoro.

Una soluzione sarebbe utilizzare una particolare topologia di accodamento. Una coda per utente, che alimenta una piccola coda limitata. A causa della piccola quantità di lavoro nella seconda coda, nessun processo può monopolizzare i lavoratori per un lungo periodo di tempo. In questo modo

Mi aspettavo che fosse facile da implementare in RabbitMQ o forse in ZeroMQ, ma ci sono diverse sfide. Per prima cosa ho bisogno di creare manualmente una nuova coda se un nuovo utente invia il lavoro. In secondo luogo, e soprattutto, sembra che dovrei implementare io stesso la parte rossa, ascoltando tutte le code in modo non bloccante per inviarle alla coda limitata.

La mia preoccupazione è che sto lavorando con astrazioni di livello molto basso qui, tutto ciò che voglio è una corretta pianificazione delle attività di limitazione della capacità. In pratica, crea una certa contropressione per consentire la pianificazione prima del lavoro effettivo e quindi non consentire a nessun utente di monopolizzare il sistema.

Ci sono migliori astrazioni con cui lavorare?

    
posta Johan Martinsson 01.06.2018 - 23:04
fonte

2 risposte

0

Penso che lo schema che descrivi sia quello comune. (In questo programma si programma il proprio "lavoratore di routing") ma si potrebbe condensare, spostando la logica di routing (rossa) nell'operatore.

Ad esempio, dire al posto di un lavoratore che ascolta una singola coda, aggiungo il codice che è a conoscenza degli utenti.

Posso quindi attivare un thread per coda utente nello stesso servizio di lavoro e lasciare che la CPU diffonda il suo tempo su ogni thread.

Potrebbe essere leggermente sub ottimale per un numero elevato di utenti o attività associate alla CPU, ma semplificherebbe la soluzione complessiva.

Lungo una linea simile, se riesci a trasferire i costi, una buona soluzione è quella di far ruotare un nuovo lavoratore su una nuova macchina nel cloud e una coda per utente.

    
risposta data 03.06.2018 - 08:58
fonte
0

Non sono sicuro di essere d'accordo con la premessa della domanda - ed ecco perché.

Teoria matematica

In base alla Teoria delle code , in qualsiasi processo stocastico First-In-First-Out, hai una tariffa di arrivo per richieste e un tempo medio che il processo impiega per soddisfare le richieste. Il processo quindi opera secondo le regole di un Processo di Poisson , e possiamo dire analiticamente per quanto tempo è probabile che la lunghezza della coda essere in qualsiasi momento, così come il throughput del processo.

Quindi, da un punto di vista analitico / progettuale, dobbiamo assicurarci che alcune ipotesi siano valide:

  • L'arrivo delle richieste è una variabile casuale con distribuzione esponenziale
  • Il tempo di servizio per una singola richiesta è una variabile casuale con distribuzione esponenziale

In pratica, queste ipotesi sono difficili da soddisfare esattamente, ma forniscono approssimazioni abbastanza buone per fare alcune progettazioni e analisi di base. Se sono gravemente violati (ad esempio il tuo sistema gestisce richieste di batch o alcune richieste richiedono molto più tempo rispetto ad altri per loro natura), allora il tuo lavoro di progettazione dovrebbe concentrarsi sul portare il sistema in uno stato in cui le ipotesi di base non sono più violate.

The Situation

Quindi, dato quanto sopra, supporrò che tu abbia un processo stocastico con tasso di arrivo della richiesta l e tempo di servizio m , e numero di processori c . Se c * m è inferiore alla tua tariffa di arrivo, allora il tuo processo è instabile e la dimensione della coda diventerà grande.

Quindi, l'obiettivo della progettazione del sistema è garantire che in tutti i momenti ragionevoli siano disponibili processori sufficienti ( c ) per soddisfare le richieste che dovrebbero arrivare durante l'intervallo (~ l ) in base a il tempo di elaborazione della richiesta tipica ( m ) e soggetto a un tempo massimo ragionevole trascorso nel sistema, inclusa la coda.

Se hai fatto questo, allora hai progettato adeguatamente il sistema per soddisfare le richieste che si aspetta di gestire. In pratica, questo approccio funziona per così tante situazioni che non sono a conoscenza di altri approcci di accodamento comunemente usati in questi tipi di sistemi. È possibile impostare l'accodamento prioritario senza prelazione con relativa facilità (simile a come funzionano le corsie di prima classe al check-in dell'aeroporto), ma come sarebbe più "giusto"?

    
risposta data 21.09.2018 - 18:50
fonte

Leggi altre domande sui tag