Bilanciamento del carico delle partizioni per l'elaborazione di eventi

Il bilanciamento del carico delle partizioni è una tecnica in Hub eventi di Azure che distribuisce i carichi di lavoro di elaborazione degli eventi tra più istanze dell'applicazione. Il client del processore di eventi gestisce automaticamente la proprietà della partizione e coordina la distribuzione del lavoro tra tutte le istanze consumer attive.

Nelle versioni più recenti dell'SDK (5.0 e successive), EventProcessorClient (.NET e Java) o EventHubConsumerClient (Python e JavaScript) gestisce automaticamente il bilanciamento del carico. Si sottoscrive gli eventi a cui si è interessati registrando un gestore eventi.

Questo articolo descrive uno scenario di esempio per l'uso di più istanze di applicazioni client per leggere gli eventi da un hub eventi. Vengono inoltre illustrati i concetti chiave, ad esempio la proprietà della partizione, il checkpoint e il bilanciamento del carico.

Tip

Se si usa una versione precedente della libreria client, vedere le guide alla migrazione: .NET, Java, Python e JavaScript.

Nota

La chiave per il ridimensionamento degli Hub Eventi è l'idea di utenti partizionati. A differenza del modello dei consumatori concorrenti, il modello dei consumatori partizionati consente una scalabilità elevata rimuovendo il collo di bottiglia della contesa e facilitando il parallelismo end-to-end.

Scenario di esempio

Come scenario di esempio, si consideri una società per la sicurezza delle abitazioni che monitora 100.000 abitazioni. Ogni minuto, riceve dati da diversi sensori, ad esempio un rilevatore di movimento, un sensore di apertura di porte/finestre, un rilevatore di vetri rotti, e così via, installato in ogni abitazione. L'azienda fornisce un sito Web ai residenti per monitorare l'attività della propria abitazione quasi in tempo reale.

Ogni sensore esegue il push dei dati a un hub eventi. L'hub eventi è configurato con 16 partizioni. Dal lato del consumo, è necessario un meccanismo che riesca a leggere questi eventi, consolidarli (filtrarli, aggregarli, e così via) e scarichi l'aggregato in un blob di archiviazione, che viene poi proiettato in una pagina Web facile da usare.

Applicazione per il consumatore

Quando si progetta un consumer in un ambiente distribuito, lo scenario deve gestire i requisiti seguenti:

  • Scala: Crea più consumer, ognuno dei quali assume la responsabilità di leggere da alcune partizioni di Event Hubs.
  • Bilanciamento del carico: aumentare o ridurre in modo dinamico i clienti. Ad esempio, quando un nuovo tipo di sensore (ad esempio, un rilevatore di monossido di carbonio) viene aggiunto a ciascuna abitazione, il numero di eventi aumenta. In tal caso, l'operatore (un essere umano) aumenta il numero di istanze del consumatore. Quindi, il pool di consumatori può ribilanciare il numero di partizioni che possiedono, in modo da condividere il carico con i nuovi consumatori aggiunti.
  • Recupero intuitivo dagli errori: in caso di esito negativo da parte di un consumer (consumer A), ad esempio, la macchina virtuale che ospita il consumer si arresta improvvisamente, gli altri consumer possono acquisire le partizioni delle quali è proprietario il consumer A e procedere. Inoltre, il punto di continuazione, chiamato checkpoint oppure offset, deve trovarsi nel punto esatto in cui il consumer A non è riuscito, o leggermente prima.
  • Consumare eventi: mentre i tre punti precedenti affrontano la gestione del consumer, deve esistere del codice per consumare eventi e fare qualcosa di utile con esso. ad esempio, aggregandolo e caricandolo nell'archivio BLOB.

Processore di eventi o cliente consumatore

Non è necessario creare una soluzione personalizzata per soddisfare questi requisiti. Gli SDK di Hub eventi di Azure offrono questa funzionalità. Negli SDK di .NET o Java usare un client del processore di eventi (EventProcessorClient). Negli SDK Python e JavaScript usare EventHubConsumerClient. Nella versione precedente dell'SDK, l'host del processore di eventi (EventProcessorHost) supporta queste funzionalità.

Per la maggior parte degli scenari di produzione, usare il client processore di eventi per la lettura e l'elaborazione di eventi. Il client del processore offre un'esperienza affidabile per l'elaborazione di eventi in tutte le partizioni di un hub eventi in modo efficiente e a tolleranza di errore, fornendo allo stesso tempo un modo per verificarne lo stato di avanzamento. I client del processore di eventi possono lavorare in modo cooperativo all'interno del contesto di un gruppo di consumer per un determinato hub eventi. I client gestiscono automaticamente la distribuzione e il bilanciamento del lavoro man mano che le istanze diventano disponibili o non disponibili per il gruppo.

Proprietà della partizione

Un'istanza del processore di eventi è in genere proprietaria ed elabora eventi di una o più partizioni. Il sistema distribuisce uniformemente la proprietà delle partizioni tra tutte le istanze attive del processore di eventi associate a una combinazione di event hub e consumer group.

Ogni processore di eventi ha un identificatore univoco e rivendica la proprietà delle partizioni aggiungendo o aggiornando una voce in un archivio dei checkpoint. Tutte le istanze del processore di eventi comunicano periodicamente con questo archivio per aggiornare il proprio stato di elaborazione e per ottenere informazioni su altre istanze attive. Il sistema usa questi dati per bilanciare il carico tra i processori attivi. Le nuove istanze possono essere unite al pool di elaborazione per aumentare le prestazioni. Quando le istanze sono inattive, a causa di errori o di riduzione, il sistema trasferisce normalmente la proprietà della partizione ad altri processori attivi.

I record di proprietà delle partizioni nell'archivio checkpoint tengono traccia dello spazio dei nomi di Hub eventi, del nome dell'Hub eventi, del gruppo di consumer, dell'identificatore del processore di eventi (noto anche come proprietario), dell'ID della partizione e dell'ora dell'ultima modifica.

Spazio dei nomi Hub eventi Nome hub degli eventi Gruppo di consumer Proprietario ID di partizione Ora ultima modifica
mynamespace.servicebus.windows.net myeventhub myconsumergroup 3be3f9d3-9d9e-4c50-9491-85ece8334ff6 0 2020-01-15T01:22:15
mynamespace.servicebus.windows.net myeventhub myconsumergroup f5cc5176-ce96-4bb4-bbaa-a0e3a9054ecf 1 2020-01-15T01:22:17
mynamespace.servicebus.windows.net myeventhub il mio gruppo di consumatori 72b980e9-2efc-4ca7-ab1b-ffd7bece8472 2 2020-01-15T01:22:10
:
:
mynamespace.servicebus.windows.net myeventhub myconsumergroup 844bd8fb-1f3a-4580-984d-6324f9e208af 15 2020-01-15T01:22:00

Ogni istanza del processore di eventi acquisisce la proprietà di una partizione e avvia l'elaborazione della partizione dall'ultimo checkpoint noto. Se un processore si guasta (la macchina virtuale viene arrestata), altre istanze individuano l'errore esaminando l'ora dell'ultima modifica. Altre istanze tentano di ottenere la proprietà delle partizioni che erano precedentemente di proprietà dell'istanza che non è più attiva. L'archivio dei checkpoint garantisce che solo una delle istanze abbia esito positivo per rivendicare la proprietà di una partizione. Quindi, in un determinato momento, è presente al massimo un processore che riceve eventi da una partizione.

Ricevere messaggi

Quando si crea un processore di eventi, specificare funzioni che elaborano eventi ed errori. Ogni chiamata alla funzione che elabora gli eventi recapita un singolo evento da una partizione specifica. È necessario gestire questo evento. Se si vuole assicurarsi che il consumer elabori ogni messaggio almeno una volta, scrivere il proprio codice con la logica di retry. Ma fai attenzione ai messaggi dannosi.

Elaborare gli eventi relativamente in fretta. Ovvero, eseguire la minor quantità di elaborazione possibile. Se è necessario scrivere nell'archiviazione ed eseguire un po' di routing, è consigliabile usare due gruppi di consumatori e avere due processori di eventi.

Punto di controllo

Il checkpointing è un processo in cui un processore di eventi contrassegna o esegue il commit della posizione dell'ultimo evento elaborato correttamente all'interno di una partizione. Il segnare un checkpoint avviene generalmente all'interno della funzione che elabora gli eventi e si verifica su base per partizione all'interno di un gruppo di consumatori.

Se un processore di eventi si disconnette da una partizione, un'altra istanza può riprendere l'elaborazione della partizione dal checkpoint che l'ultimo processore di quella partizione in quel gruppo di consumer ha precedentemente registrato. Quando il processore si connette, passa l'offset all'hub eventi per specificare la posizione da cui iniziare la lettura. In questo modo, è possibile utilizzare il checkpointing sia per contrassegnare gli eventi come "completi" per le applicazioni downstream, sia per garantire resilienza quando un processore di eventi si arresta. È possibile tornare ai dati precedenti specificando un offset inferiore rispetto a questo processo di checkpoint.

Quando il checkpoint contrassegna un evento come elaborato, aggiunge o aggiorna una voce nell'archivio checkpoint con l'offset e il numero di sequenza dell'evento. Decidere la frequenza di aggiornamento del checkpoint. L'aggiornamento dopo che ogni evento elaborato correttamente può avere implicazioni in termini di prestazioni e costi perché attiva un'operazione di scrittura nell'archivio checkpoint sottostante. Inoltre, effettuare il checkpoint di ogni singolo evento è indicativo di un modello di messaggistica in cui i messaggi sono in coda, per il quale una coda del bus di servizio potrebbe essere un'opzione migliore rispetto a un Event Hub. L'idea alla base di Event Hubs è di ottenere la consegna "almeno una volta" su larga scala. Per rendere idempotenti i sistemi a valle, è più facile recuperare da errori o riavvii che fanno sì che gli stessi eventi vengano ricevuti più volte.

Seguire queste raccomandazioni quando si utilizza Archiviazione BLOB di Azure come archivio dei punti di controllo:

  • Usare un contenitore separato per ogni gruppo di consumer. È possibile usare lo stesso account di archiviazione, ma occorre usare un contenitore per ogni gruppo.
  • Non usare l'account di archiviazione per nient'altro.
  • Non usare il contenitore per nient'altro.
  • Creare l'account di archiviazione nella stessa area dell'applicazione distribuita. Se l'applicazione è locale, provare a scegliere l'area più vicina possibile.

Nella pagina Account di archiviazione del portale di Azure verificare che le impostazioni seguenti siano disabilitate nella sezione Servizio BLOB.

  • Spazio dei nomi gerarchico
  • Eliminazione morbida dei BLOB
  • Controllo delle versioni

Sicurezza del thread e istanze del processore

Per impostazione predefinita, la funzione che elabora gli eventi viene chiamata in sequenza per una determinata partizione. Le chiamate e gli eventi successivi per questa funzione provenienti dalla stessa partizione si accodano dietro le quinte mentre la "event pump" continua a funzionare in background in altri thread. Gli eventi provenienti da partizioni diverse possono essere elaborati simultaneamente. È necessario sincronizzare qualsiasi stato condiviso a cui si accede tra partizioni.

Consulta le seguenti guide rapide: