Evitare loop infiniti nella messaggistica SOA / Enterprise Integration

Aug 31 2020

Pensando all'interno di un framework Service Oriented Architecture / Microservices / Enterprise Integration come evitare loop infiniti quando si pubblicano messaggi tra sistemi, specialmente quando si ha un controllo limitato su determinati servizi (ad esempio prodotti SaaS di terze parti).

Per esempio:

  • Il sistema A tiene traccia dell'entità E - Ho pochissimo controllo su come si comporta il sistema A, è proprietario.
  • Il sistema B vuole anche monitorare l'Entità E.

Problema:

A --> B: E viene creato, A pubblica un messaggio a B che E è stato creato.
B --> A: B emette un nuovo identificatore globale per E e lo rimanda ad A
A --> B.: A invia un nuovo messaggio su questo ultimo aggiornamento a B (non è a conoscenza che l'aggiornamento proviene da B).

Il problema è che A ora riceverà un nuovo aggiornamento e pubblicherà un nuovo messaggio su B, che a sua volta potrebbe inviare un messaggio indietro, avviando un ciclo / ciclo infinito.

Poiché ho poco controllo sul comportamento interno dell'IA, devo gestire questo problema all'interno del sistema B.

Come possiamo evitare questo tipo di problemi?

Ho considerato

  • chiave hash in stile etag contro l'entità E che il sistema B può confrontare con ciò che conosce di E per evitare di pubblicare ulteriori messaggi sui cambiamenti
  • confrontando i timestamp aggiornati, questo non funzionerà perché i messaggi da B possono causare aggiornamenti

Risposte

2 DocBrown Sep 02 2020 at 13:17

In un commento, hai scritto

Ad esempio A potrebbe gestire le informazioni bancarie di un cliente ma C gestisce il loro stato di credito, tutte le sincronizzazioni sono unidirezionali a seconda del set di informazioni che stiamo gestendo, con ogni campo che ha una fonte di verità definita.

Quindi il vero problema qui è che le modifiche ad alcuni attributi di un'entità vengono avviate in un sistema e gli attributi "specchiati" esistono in un altro sistema. Possono verificarsi modifiche da entrambe le parti a determinati attributi, che causano "eventi di cambiamento" in entrambe le direzioni, forse causando loop infiniti.

Un modo per interrompere i cicli di eventi è emettere eventi solo quando gli attributi cambiano realmente il loro valore . Per restare fedeli al tuo esempio, "l'identificatore globale" sembra essere un attributo rispecchiato:

A --> B: E viene creato, A pubblica un messaggio a B che E è stato creato.
B --> A: B emette un nuovo identificatore globale per E e lo rimanda ad A
A --> B.: A invia un nuovo messaggio su questo ultimo aggiornamento a B (non è a conoscenza che l'aggiornamento proviene da B).

... e ora B reagisce all'evento, si informa sui cambiamenti effettivi in ​​E, confronta attributi come l '"identificatore globale" con i valori correnti nel suo specchio di E e osserva che non c'è alcun cambiamento reale. L '"identificatore globale in E memorizzato in A" è lo stesso "identificatore globale in E memorizzato in B". E dal momento che non è cambiato nulla, non c'è motivo di pubblicare ulteriori eventi.

Se B funziona solo come "mediatore di eventi" per un altro sistema C, allora C deve decidere se un "evento di modifica" da un altro sistema causa davvero una modifica dei dati, ma il principio rimane lo stesso: confronta i valori degli attributi in entrata con quelli correnti e se i valori non sono cambiati, non generano ulteriori eventi.

Ciò funzionerà anche se le modifiche allo stesso attributo possono essere causate in sistemi diversi, senza dover definire una "singola fonte di verità". Quest'ultimo, tuttavia, può aiutare a rendere il sistema più prevedibile e stabile.

SerejaBogolubov Aug 31 2020 at 22:43

È un design terribilmente scadente.

O esplicitamente o no, ma essenzialmente hai a che fare con la transazione, che copre alcune parti del sistema distribuito in cui si trovano.

La transazione ha il proprio identificatore univoco.

Transaction ha il proprio stato macchina, almeno: in_progress, commited, rolledback. Lascia che sia la tua logica aziendale a dettare ciò che ha quella macchina a stati, eppure esiste sempre.

Tutte le attività coinvolte dovrebbero rientrare nella stessa transazione. Se il tuo sistema è così sofisticato, potresti dover costruire e mantenere un albero delle transazioni, in cui la transazione genitore può creare transazioni secondarie secondarie e monitorare i loro progressi. Qualunque cosa. Prima di procedere e fare qualcosa, controlli lo stato più recente della tua transazione e assicurati che la seguente modifica sia ancora valida e necessaria. Altrimenti lo salti semplicemente.

Non usciamo.

La topologia dei microservizi non è altro che un grafo diretto. Che potrebbe contenere cicli come hai detto. Come attraversi il grafico diretto evitando loop infiniti? Tieni traccia dei nodi che hai visto dall'inizio dell'attraversamento. L'approccio che ho descritto sopra è la stessa idea proiettata al tuo problema.

FluidCode Sep 01 2020 at 15:31

Nell'era della SOA prima che il concetto di microservizi nasceva lì dove regole rigide sull'interazione tra servizi. Le chiamate di servizio atomiche dovevano essere supervisionate da servizi compositi, assicurando così che il caso menzionato non si verificasse. Ai servizi Atomic era consentito chiamare direttamente solo servizi tecnici, come i servizi di audit, che eseguivano un'attività di basso livello senza restituire nuove informazioni / dati.

Lo stesso vale se invece di parlare di cicli infiniti parli di dipendenze circolari. Ovviamente se un sistema è molto complesso le dipendenze circolari potrebbero verificarsi anche seguendo le linee guida SOA, ma in un ambiente di microservizi è molto più probabile che accada.

Per risolvere il problema che descrivi, un mezzo passo indietro potrebbe essere la soluzione. Ma implicherebbe il ruolo degli architetti che supervisionano il lavoro di diversi gruppi. Tutti i microservizi dovrebbero essere classificati in categorie specifiche, quindi alcune regole dovrebbero essere definite per vincolare le dipendenze solo in determinate direzioni tra categorie diverse e persino alcune regole che stabiliscono come i servizi all'interno della stessa categoria possono interagire. Il problema principale con questa soluzione è quello che ha afflitto le grandi aziende sin dall'inizio dell'IT. Come applicare tali regole tra diversi gruppi e diversi dipartimenti aziendali? È più una questione politica che tecnica.