Condividi tramite


Bilanciare il carico delle partizioni tra più istanze dell'applicazione

Per ridimensionare l'applicazione di elaborazione degli eventi, è possibile eseguire più istanze dell'applicazione e bilanciare il carico tra loro. Nelle versioni precedenti e deprecate EventProcessorHost è possibile bilanciare il carico tra più istanze del programma ed eventi di checkpoint quando si ricevono gli eventi. Nelle versioni più recenti (5.0 e successive), EventProcessorClient (.NET e Java) o EventHubConsumerClient (Python e JavaScript) consente di eseguire la stessa operazione. Il modello di sviluppo è reso più semplice usando gli eventi. È possibile sottoscrivere gli eventi a cui si è interessati registrando un gestore eventi. Se si usa la versione precedente della libreria client, vedere le guide alla migrazione seguenti: .NET, Java, Python e JavaScript.

Questo articolo descrive uno scenario di esempio per l'uso di più istanze di applicazioni client per leggere gli eventi da un hub eventi. Fornisce anche informazioni dettagliate sulle funzionalità del client del processore di eventi, che consente di ricevere eventi da più partizioni contemporaneamente e di bilanciare il carico con altri consumer che usano lo stesso hub eventi e lo stesso gruppo di consumer.

Nota

Il ridimensionamento di Hub eventi si basa sul concetto di consumer partizionati. A differenza dei criteri relativi ai consumer concorrenti, il modello consumer partizionato consente un'elevata scalabilità rimuovendo il collo di bottiglia dovuto alla contesa e agevolare 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 consumer, è necessario un meccanismo che riesca a leggere questi eventi, consolidarli (filtrarli, aggregarli, e così via) ed esegua il dump dell'aggregazione in un BLOB di archiviazione, previsto quindi in una pagina Web intuitiva.

Applicazione consumer

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

  1. Scalabilità: creare diversi consumer, ciascuno tra questi che dispone di proprietà di lettura derivanti da alcune partizioni di Hub eventi.
  2. Bilanciamento del carico: aumentare o ridurre in modo dinamico i consumer. 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 consumer. Quindi, il pool di consumer può ribilanciare il numero di partizioni di cui è proprietario, condividendo il carico con i consumer appena aggiunti.
  3. 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 ha avuto esito negativo, o leggermente prima rispetto al punto.
  4. Uso di eventi: mentre i tre punti precedenti affrontano la gestione del consumer, è necessario che esista un codice per gli eventi e che questo venga usato a uno scopo utile. ad esempio, aggregandolo e caricandolo nell'archivio BLOB.

Processore di eventi o client consumer

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

Per la maggior parte degli scenari di produzione, è consigliabile usare il client processore di eventi per la lettura e l'elaborazione degli eventi. Il client del processore è progettato per offrire 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 gestiranno 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. La proprietà delle partizioni viene distribuita uniformemente tra tutte le istanze del processore di eventi attive associate a una combinazione di hub eventi e gruppo di consumer.

Ogni processore di eventi dispone di un identificatore univoco e attesta la proprietà delle partizioni aggiungendo o aggiornando una voce in un archivio 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. Questi dati vengono quindi usati 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 per ridurre le prestazioni, la proprietà della partizione viene trasferita normalmente ad altri processori attivi.

I record di proprietà della partizione 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 partizione e dell'ora dell'ultima modifica.

Spazio dei nomi Hub eventi Nome hub eventi Gruppo di consumer Proprietario ID 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 myconsumergroup 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 ha esito negativo (la VM viene arrestata), le altre istanze lo rilevano esaminando l'ora dell'ultima modifica. Altre istanze tentano di ottenere la proprietà delle partizioni di proprietà precedentemente dell'istanza inattiva. 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, si specificano funzioni che elaborano eventi ed errori. Ogni chiamata alla funzione che elabora gli eventi recapita un singolo evento da una partizione specifica. È responsabilità dell'utente gestire questo evento. Se si vuole avere la certezza che il consumer elabori ogni messaggio almeno una volta, è necessario scrivere il proprio codice con la logica di ripetizione dei tentativi. Fare attenzione, tuttavia, a inserire messaggi non elaborabili.

È consigliabile eseguire operazioni relativamente veloci. Ovvero, eseguire la minor quantità di elaborazione possibile. Se è necessario scrivere nell'archiviazione ed eseguire alcune route, è consigliabile usare due gruppi di consumer e avere due processori di eventi.

Checkpoint

Il checkpoint è un processo tramite il quale un processore di eventi contrassegna o esegue il commit della posizione dell'ultimo evento elaborato correttamente all'interno di una partizione. Il contrassegno di un checkpoint viene in genere eseguito all'interno della funzione che elabora gli eventi e si verifica in base alla partizione all'interno di un gruppo di consumer.

Se un processore di eventi si disconnette da una partizione, un'altra istanza può riprendere l'elaborazione della partizione nel checkpoint di cui è stato eseguito il commit in precedenza dall'ultimo processore di tale partizione nel gruppo di consumer. Quando il processore si connette, passa l'offset all'hub eventi per specificare la posizione da cui iniziare la lettura. In questo modo è possibile usare l'impostazione del checkpoint sia per contrassegnare gli eventi come "completi" da parte delle applicazioni downstream che per offrire resilienza in caso di inattività di un processore eventi. È possibile tornare a dati precedenti specificando un offset inferiore da questo processo di checkpoint.

Quando il checkpoint viene eseguito per contrassegnare un evento come elaborato, viene aggiunta o aggiornata una voce nell'archivio checkpoint con l'offset e il numero di sequenza dell'evento. Gli utenti devono 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, il checkpoint di ogni singolo evento è indicativo di un modello di messaggistica in coda per il quale una coda del bus di servizio potrebbe essere un'opzione migliore rispetto a un hub eventi. L'idea alla base di Hub eventi è di ottenere "almeno un" recapito su larga scala. Per rendere idempotenti i sistemi a valle, è facile eseguire il ripristino a seguito di errori o il riavvio del risultato negli stessi eventi ricevuti più volte.

Seguire queste raccomandazioni quando si usa Archiviazione BLOB di Azure come archivio checkpoint:

  • 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 il contenitore per altri elementi e non usare l'account di archiviazione per altri elementi.
  • L'account di archiviazione deve trovarsi nella stessa area in cui si trova l'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 temporanea dei BLOB
  • Controllo delle versioni

Istanze di elaborazione e sicurezza del thread

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 in background mentre l'event pump continua a essere eseguito in background in altri thread. Gli eventi di partizioni diverse possono essere elaborati simultaneamente e qualsiasi stato condiviso a cui si accede tra partizioni deve essere sincronizzato.

Vedere le guide introduttive seguenti: