Failover per lavori ad alta frequenza

3

Ho un lavoro che funziona ad una frequenza abbastanza alta (~ 1x ogni secondo).

Questo lavoro deve essere eseguito costantemente fintanto che l'app web è in esecuzione. Tuttavia, desidero davvero solo 1 istanza del processo in esecuzione alla volta.

Attualmente, accendo solo un thread che esegue il lavoro in background, dormendo per ~ 800ms ogni loop. Ciò causa un problema quando voglio la ridondanza, perché il thread si avvia come parte dell'app.

So che posso fare qualcosa di semplice, come aggiungere un tavolo in un database e avere un server "primario" e "secondario" bloccare il record, tenere traccia di chi è responsabile, ecc. Ma sembra un po 'brutto, quindi ero curioso se qualcuno avesse esperienza con una situazione simile, e quale soluzione hai usato?

    
posta jvenema 13.05.2015 - 05:16
fonte

4 risposte

3

Lo vedo in definitiva come un problema di comunicazione tra processi (IPC). Hai un processo che genera lavoro e poi un altro che consuma le attività e fa il lavoro.

Ciò rientra in un layout classico per produttore e consumatore ( tutorial di RabittMQ ).

La cosa bella delle code dei messaggi è che garantiscono il contratto di "questo messaggio è garantito per essere consegnato a uno, e solo a un consumatore (se è stato consumato del tutto)." Ciò semplifica l'IPC in quanto non è necessario preoccuparsi dei semafori e dei segmenti di memoria condivisa o di altri canali di comunicazione.

Oltre a questo, puoi iniziare a essere fantasioso. È possibile avere due utenti in esecuzione, anche se solo uno afferrerà il messaggio che indica l'attività dalla coda. Potresti fare in modo che il produttore estrae le singole attività "considera questo" il più velocemente possibile (fino a una certa pienezza della coda) e i consumatori li elaborano una volta ogni 800ms, anche se l'implementazione esatta dipende dal problema.

La coda dei messaggi ha un vantaggio sui database in quanto è progettata per funzionare. Puoi fare cose simili tramite meccanismi nel database, ma poi inizierai a preoccuparti delle transazioni e dei blocchi. Alcuni database hanno acquisito ulteriori capacità di accodamento dei messaggi come parte del nucleo di funzionalità come descritto in questo post , ma una coda di messaggi ha un vantaggio generale sui database essere in grado di gestire più messaggi simultanei, bloccando fino a ottenere un messaggio, evitando deadlock e gare.

Come si progetta una soluzione utilizzando una coda di messaggi per questo problema specifico è ancora un po 'in aria in quanto vi sono molti aspetti del dominio che non vengono descritti, ma in generale la coda dei messaggi dovrebbe essere uno dei primi strumenti mi viene in mente quando si inizia a pensare a come inviare messaggi tra uno o più processi.

    
risposta data 14.05.2015 - 02:07
fonte
2

Posso consigliare Hangfire come soluzione. Punti chiave per il tuo caso (estratti dal sito web),

Persistente

I processi in background vengono salvati in una memoria persistente: SQL Server, Redis, PostgreSQL, MongoDB e altri. Puoi riavviare in sicurezza la tua applicazione e utilizzare Hangfire con ASP.NET senza preoccuparti del riciclo del pool di applicazioni.

affidabile

Una volta creato e inserito un lavoro in background in una memoria senza eccezioni, Hangfire si assume la responsabilità di elaborarlo almeno una volta. Sei libero di lanciare eccezioni non gestite o uccidere la tua applicazione: i processi in background verranno riprovati automaticamente.

Distributed

Le chiamate al metodo in background ei loro argomenti sono serializzati e possono superare i limiti del processo. È possibile utilizzare Hangfire su macchine diverse per ottenere maggiore potenza di elaborazione senza alcuna configurazione: la sincronizzazione viene eseguita automaticamente.

    
risposta data 14.05.2015 - 02:19
fonte
0

Buona domanda,

Vorrei spostare l'attività in un servizio separato. Questo aggira il tuo collegamento con il sito web, ma dovrai comunque rendere il servizio ridondante. Puoi procedere in due modi.

1: i servizi non si conoscono l'un l'altro. Se è possibile modificare il lavoro in modo che non si verifichi alcun errore quando viene eseguito contemporaneamente a se stesso, questa è la soluzione migliore in quanto è possibile attivare semplicemente 2 o più servizi e non preoccuparsi.

2 i servizi si conoscono l'un l'altro. Questo è più complicato, ma ne vale la pena se il lavoro è di lunga durata in quanto consente di distribuire il carico sui lavoratori. È possibile utilizzare una coda (msmq, zmq, rabbit) o una tabella di database (contrassegnare i processi come in corso) per influire sulla comunicazione

    
risposta data 13.05.2015 - 16:17
fonte
0

L'attività dovrebbe essere eseguita come un "servizio" separato che inizia all'avvio del server. È possibile utilizzare un modello singleton per garantire che non ci sia mai più di una istanza in esecuzione. Per una soluzione specifica .net guarda Mutex. Crea un modello singleton a livello di sistema.

Mentre dici che il processo dovrebbe essere eseguito solo quando l'app Web è ciò che è veramente importante è che il processo completi un po 'di lavoro periodico quando l'app web è in esecuzione. Può realizzare questo un numero di modi diversi. Uno sarebbe di avere il servizio in ascolto per vedere se l'app web è in esecuzione tra i cicli di sospensione.

L'unica cosa che non hai è la capacità di rilevare se il servizio non riesce a funzionare e riavviarlo. Ci sono modi per farlo, oltre a lanciare allarmi, ma se stai andando a tutto ciò dovresti cercare di rendere il tuo 'servizio' un vero servizio di Windows.

    
risposta data 15.05.2015 - 04:37
fonte

Leggi altre domande sui tag