Come mantenere l'ordine delle richieste in arrivo su un server con multithreading

2

Voglio scrivere un'applicazione server multithread che sia in grado di elaborare le richieste in modo multithreading mantenendo l'ordine di esecuzione delle richieste in arrivo dello stesso client.

Ad esempio se il client A invia un messaggio M1 e quindi un messaggio M2, il server muiltithread deve elaborare queste richieste esattamente nello stesso ordine, prima M1 e poi M2. Tuttavia, non vi è alcuna garanzia che i thread che elaborano queste richieste in arrivo elaborino questi messaggi nello stesso ordine.

Ad esempio, il thread T1 utilizza il messaggio M1, il thread T2 utilizza il messaggio M2 e completa l'elaborazione del messaggio ed è in grado di accettare ulteriori messaggi prima che T1 abbia terminato il suo lavoro.

Dopo che un messaggio è stato elaborato, il risultato verrà passato ad un altro processo per l'ulteriore elaborazione (di cui solo uno esiste nell'intero calcolo), questo processo pianificherà l'invio di una risposta al client.

Questi thread multipli esistono solo allo scopo di preelaborare i dati per qualche altro processo. Questo particolare problema sembra un problema con le caratteristiche della pipeline, prima M1, poi M2, poi M3, ecc. Tuttavia, ho voluto parallelizzarlo il più possibile per ottenere un numero maggiore di cicli di comunicazione tra il server e i client.

Quale architettura / modello / tecnica è adatta per questo tipo di compito?

    
posta synRG 16.01.2013 - 10:06
fonte

3 risposte

4

Un nome per questo tipo di requisito è "Unità di ordine".

Ad esempio, in Weblogic JMS, fornisce tale funzionalità che concettualmente è possibile inserire un identificatore UOO nel messaggio quando si mette il messaggio in coda. Weblogic JMS garantirà che i messaggi dello stesso UOO vengano elaborati in ordine cronologico. Tuttavia, i messaggi in diversi UOO possono essere elaborati in parallelo.

Dipende tutto da quale piattaforma o tecnologia hai intenzione di implementarlo, che credo ci sia un sacco di modo per ottenere un effetto simile.

    
risposta data 16.01.2013 - 10:23
fonte
4

Come qualcuno ha già menzionato nei commenti, potresti usare una semplice coda di messaggi. Quando viene inviato un messaggio, tutto ciò che si fa è aggiungerlo alla coda. Si ha quindi un "Listener" o "Consumer" in modo asincrono che elabora semplicemente ogni messaggio recuperato dalla coda uno alla volta. Anche se il server è multi-thread, Listener / Consumer può essere a thread singolo (sebbene tu abbia la possibilità di utilizzare più quando l'ordine non è importante).

Modifica: come indicato da uno dei commenti seguenti, funzionerà solo se l'elaborazione prima dell'aggiunta alla coda è istantanea. L'idea alla base della separazione è anche quella di spostare tutta la tua logica e la tua elaborazione in Listener / Consumer e non tenerla nella porzione multi-thread del tuo codice.

    
risposta data 16.01.2013 - 20:39
fonte
0

Per ripristinare l'ordine originale dopo che hanno lasciato il pool di thread, è necessario un qualche tipo di struttura dati in grado di contenere i messaggi completati fino all'arrivo della prossima unità prevista e quindi riprenderli rilasciandoli al thread di attesa dell'utente.

Quale particolare approccio è il migliore dipende da quanti messaggi stanno arrivando, quanto è sensibile il destinatario finale a saltare (niente sta accadendo mentre aspetti che il messaggio fuori servizio finisca l'elaborazione), quanto lavoro ogni messaggio richiede per elaborare, memoria disponibile, ecc.

Se il consumatore si aspetta un certo numero di messaggi per periodo di tempo, potrebbe essere in grado di farlo sommando unità di lavoro completate a una struttura di dati di ordinamento (come un btree / binarytree / etc) e periodicamente eliminando il più basso unità classificata. Ciò presuppone che riceverai messaggi e li elaborerai a una velocità più che sufficiente per mantenere pieno il buffer. Se i messaggi completati arrivano in un ordine errato, potrebbe essere necessario eliminarli anziché metterli nella parte anteriore di un buffer).

    
risposta data 08.01.2015 - 21:37
fonte

Leggi altre domande sui tag