Messaggi correlati a Kafka

0

Contesto

Stiamo costruendo un'applicazione che si comporta come un hub per i messaggi provenienti da più produttori e che assegna ai consumatori in base a determinati criteri.

È necessario che il design sia altamente scalabile, ma allo stesso tempo, le funzionalità principali della correlazione messaggio-interazione non dovrebbero essere interrotte.

Principali entità nel sistema:

Produttore (pronuncia P1 in questo esempio): entità che avvia un'interazione con un consumatore (tuttavia il produttore non può scegliere in modo esplicito a quale consumatore può parlare)

Consumatore (pronuncia C1 in questo esempio): entità che serve richieste come richiesto dal Prodcuer.

Interazione (dire I1 in questo esempio): è un contenitore logico per i messaggi scambiati tra P1 e C1

Messaggio : un pacchetto di informazioni da inviare all'altro interlocutore. Sia P1 che C1 possono generare un messaggio da inviare all'altro interlocutore.           Per questo esempio, prendiamo uno scenario di un'interazione di 3 messaggi in ordine cronologico           M1 - > Primo messaggio in I1 creato da P1           M2 - > Secondo messaggio in I1 creato da C1 in risposta a M1           M3 - > Terzo messaggio in I1 creato da P1 in risposta a M2

Ogni volta che un Prodcuer invia un messaggio, il produttore deve inviare l'ID di interazione nell'intestazione del messaggio in modo che i messaggi dei produttori vengano indirizzati allo stesso Consumatore che ha il contesto. Esempio: Quando P1 invia M3, deve specificare I1 nel payload, in modo che M3 sia correttamente indirizzato a C1.

Se P1 non fornisce I1 nel messaggio M3, M3 verrà trattato come un nuovo messaggio e quindi una nuova interazione. Ciò causerà alla M3 di creare una nuova Interaction Say Ix e atterrare con un diverso Consumer (Say Cn)

Al punto di accesso dell'applicazione è un gateway API che espone un formato di immissione dei messaggi comune e accetta i payload JSON. Ogni volta che un messaggio (Say M) viene ricevuto nell'API viene eseguita la seguente logica di co-relazione (percorso felice)

IF (M.referenceId == null)
{
    Create a new Interaction //I1
    Find a Consumer from a list of consumers who is free. //C1
    Assign the interaction to the Consumer //Assign I1 to C1
}
Else IF (M.referenceId != null)
{
    Check in application database IF an interaction with this ID exists. //check I1.id = M.referenceId
    If an interaction is found, associate M with the interaction
    Find the Consumer already associated with the interaction and deliver the message.
}

Ecco come apparirebbe il DB

|| ID messaggio || Creato da || Consegnato a || ID interazione ||

| M1 | P1 | C1 | I1 |

| M2 | C1 | P1 | I1 |

| M3 | P1 | C1 | I1 |

Dichiarazione di problemi: Vogliamo utilizzare una coda per essere in grado di scalare pesantemente, ma la nostra operazione principale richiede l'accesso al DB. Dobbiamo scegliere tra 2 possibili approcci.

Approccio # 1: Il flusso delle chiamate è simile a questo: Gateway API < - > Kafka Queue < - > NoSQL-DB (o RDBMS per quella materia)

Pro: 1. Consente una buona messa in coda, Contro: Poiché la logica di co-relazione non è stata eseguita, non possiamo correlare il messaggio e quindi non possiamo dire al produttore quale sia l'ID di interazione

Approccio # 2: Il flusso delle chiamate è simile a questo: Gateway API < - > NoSQLDB (o RDBMS per quella materia)

Pro: Permette alla logica di correlazione di funzionare e quindi possiamo fornire in modo affidabile l'ID di interazione al produttore.

Contro: non può utilizzare la potenza di Kafka

Domanda : Esiste un approccio che possa facilitare la potenza di Kafka ma allo stesso tempo ci consenta di fare la logica di ricerca del DB senza causare alcun rallentamento?

    
posta Ayusman 05.07.2018 - 16:53
fonte

1 risposta

1

Penso che Kafka sia esattamente la scelta sbagliata in questa situazione.

Kafka funziona al meglio quando un argomento viene letto dai consumatori che sono in grado di prendere una serie di record, elaborarli e registrare gli offset.

Nel tuo caso, hai consumatori che elaboreranno singoli messaggi. E mentre Kafka può farlo, stai pagando una penalità di I / O più elevata rispetto al throughput.

Inoltre, hai una situazione in cui hai una coda indifferenziata che può essere letta da qualsiasi consumatore e coppie di code differenziate che rappresentano le comunicazioni tra i produttori e un consumatore specifico. Per fare ciò in modo sano, dovrai creare un argomento separato per ciascuna interazione (in realtà, due di essi, per la comunicazione bidirezionale). Tutto questo, ma elimina il beneficio delle scritture sequenziali che considero il vero "potere" di Kafka.

Invece, la tua applicazione sembra un buon uso di una coda in stile AMQP, dove puoi usare l'indirizzamento per instradare i messaggi. O in alternativa, una qualche forma di connessione TCP persistente con un servizio di bilanciamento del carico per stabilire l'interazione ( nginx lo farà). Se i tuoi produttori sono in realtà dei client Web, le prese di rete sembrano una buona idea, poiché gran parte dell'implementazione esiste già.

    
risposta data 06.07.2018 - 14:02
fonte

Leggi altre domande sui tag