Sincronizza il lavoro sui contenitori finestra mobile in una coda

2

Ho una configurazione piuttosto semplice (ho pensato) che mi causa un po 'di dolore.

Utilizzo un sistema di accodamento (AWS SQS) e alcuni container docker di lavoro con codice scritto in .net core che estrae da una coda e processa i messaggi. Più operatori possono effettuare il pull da una coda allo stesso tempo.

Alcune operazioni appartengono a un singolo lavoro. Per esempio. otteniamo 100 unità da elaborare, quindi possiamo creare un job nel nostro db SQL e quindi inviare 100 messaggi a SQS da elaborare. Quando tutti i dipendenti hanno finito, e solo una volta, vogliamo eliminare il lavoro e inviare messaggi al servizio esterno che abbiamo terminato. È fondamentale inviare un messaggio al servizio esterno solo una volta, poiché il servizio potrebbe comportare un'attività visibile all'utente.

Ciò che accade è che spesso l'ultimo paio di unità termina l'elaborazione quasi al millisecondo allo stesso tempo, quindi stiamo facendo uscire i messaggi duplicati (se prima scriviamo il messaggio e poi cancelliamo il job record) o vari eccezioni se proviamo a eliminare il lavoro contemporaneamente.

Qual è il meccanismo più appropriato per gestire il blocco qui? Una cosa che abbiamo provato è aggiungere tempi di attesa casuali quando sappiamo che siamo vicini alla fine del lavoro, ma quelli non sembrano funzionare in modo affidabile.

    
posta zaitsman 18.06.2018 - 08:39
fonte

2 risposte

1

Il modo tipico per gestire qualcosa di simile è quello di fare in modo che ogni lavoratore pubblichi un messaggio "fatto" su un'altra coda, quindi avere un'attività aggiuntiva che attende solo tutti i messaggi completati prima di ripulire il lavoro.

Un altro modo che è un po 'più accoppiato all'implementazione del database consiste nell'usare le garanzie del database per eseguire la sincronizzazione. Ad esempio, in cassandra , puoi fare un DELETE IF EXISTS , che notificherà al chiamante se ha tentato di cancellarlo ma è già stato eliminato. Quindi, solo il lavoratore riuscito eseguirà il passaggio di notifica.

    
risposta data 18.06.2018 - 19:57
fonte
1

Nel cuore della tua domanda c'è uno dei blocchi di intervento nella progettazione di sistemi distribuiti asincroni: sapere quando un lavoro batch è completo. Ci sono molti modi in cui puoi tentare di aggirare ciò che non è terribilmente affidabile. Ecco due soluzioni robuste:

La prima risposta è che ridisegnare il sistema in modo che non sia asincrono. Sbarazzati delle code e fai il lavoro. È possibile eseguire più di un thread se ciò è ritenuto necessario. Gli svantaggi sono che questo potrebbe significare una quantità significativa di rilavorazione e riprogettazione e può essere più difficile da ridimensionare.

L'altra risposta è che hai bisogno di un processo di osservazione. Sa quante attività devono essere eseguite e verifica quando sono complete. È questo processo che gestirà qualsiasi lavoro pre o post-batch. Ciò consente di lasciare le code distribuite in posizione, ma è necessario disporre di una sorta di meccanismo per la notifica del processo di controllo al completamento di ciascuna attività. Un modo intelligente per farlo è una parte fondamentale del progetto Apache Storm. L'idea di base è che tu dia ad ogni compito un ID unico. Quando l'osservatore invia un ID, restituisce XOR rispetto a un valore che inizia da 0. Al termine dell'attività, XOR riporta l'ID in quel valore. Quando tutte le attività sono state eseguite, quel valore verrà ripristinato a 0. Naturalmente puoi sempre tenere un libro mastro e questo ti dirà cosa è ancora in sospeso.

    
risposta data 17.08.2018 - 23:00
fonte

Leggi altre domande sui tag