Passaggio dei messaggi: come rilevare e / o gestire "vicoli ciechi"

2

Sto giocando con un modello mentale per il sistema di attori distribuiti che comunica usando i messaggi. In questo, è possibile per un attore creare un altro attore. Ho incontrato una situazione specifica in cui non sono davvero sicuro su come risolvere. Considera questa sequenza di eventi:

  1. L'attore 1 richiede la creazione dell'attore 2. Come parte della "costruzione", passa il proprio ID.
  2. L'attore 1 richiede la propria cancellazione.
  3. Il sistema invia un messaggio KILL a tutti gli attori che si sono abbonati a {Actor1 | KILL}
  4. Viene creato l'attore 2, salva l'ID di "1" inviato come parametro di costruzione.
  5. L'attore 2 tenta di inviare un messaggio all'attore 1.
  6. ???
  7. L'attore 2 rileva che l'attore 1 è scomparso e reagisce.

Poiché gli attori 1 e 2 possono essere su macchine fisicamente diverse, eseguendo una query "Esiste l'attore X?" ogni volta che (o prima di ogni volta) si tenta di inviare un messaggio si introdurrà una latenza che non dovrebbe essere presente nel caso tipico. Allo stesso modo, bloccare fino a quando non si sa "Invia successo" o "Invia fallito" sembra una cattiva idea. Sembra anche che il codice di scrittura con if(send() == fail) { ... } sia brutto e soggetto a errori. Esistono soluzioni note per gestire in modo efficace e pulito questo tipo di situazioni?

    
posta PatrickB 20.05.2014 - 22:01
fonte

1 risposta

3

Questo problema è stato affrontato a volte quando si tenta di costruire un protocollo di comunicazione affidabile in cima a uno inaffidabile. Questo inizia con TCP (poiché il protocollo IP sottostante non è affidabile) e qualsiasi protocollo che usa UDP come meccanismo di trasporto.

L'idea di base è che ogni messaggio / pacchetto ottenga un numero di identificazione e il destinatario mandi un riconoscimento dei messaggi / pacchetti che ha ricevuto. Se il mittente non riceve una conferma entro un certo periodo di tempo, il messaggio viene considerato perso e il mittente prova a inviarlo. Dopo un certo numero di tentativi, il recapito del messaggio viene generalmente abbandonato e viene segnalato un errore all'applicazione.

A livello di applicazione, ci sono due modi principali per gestirlo:

  1. Una funzione di blocco send . Questo dovrebbe essere usato solo se i timeout sono relativamente brevi. Non vuoi bloccare il tuo attore per un minuto perché il destinatario è difficile da raggiungere. Una funzione di blocco send può restituire uno stato che indica successo / fallimento oppure può generare un'eccezione (se l'errore viene considerato una situazione eccezionale e / o è probabile che i chiamanti diretti di send non possano realmente fare nulla con l'errore eccetto passarlo sullo stack).

  2. Una funzione di send non bloccante. In questo caso, la notifica di errore sarà spesso sotto forma di un callback o evento che arriva qualche tempo dopo l'invio del messaggio.

In entrambi i casi, per i messaggi in cui l'attore non è interessato al successo / fallimento della consegna, l'attore può semplicemente scegliere di ignorare le indicazioni di errore, oppure può esserci un meccanismo per dire agli strati inferiori "no preoccuparsi di riprovare questo messaggio ".

    
risposta data 21.05.2014 - 08:48
fonte

Leggi altre domande sui tag