web-dev-qa-db-fra.com

Qu'est-ce qui cause Azure Event Hubs ReceiverDisconnectedException / LeaseLostException?

Je reçois des événements d'un EventHub utilisant EventProcessorHost et une classe IEventProcessor (appelez-le: MyEventProcessor). J'élargis cela à deux serveurs en exécutant mon EPH sur les deux serveurs et en les faisant se connecter au concentrateur en utilisant le même ConsumerGroup, mais un nom d'hôte unique (en utilisant le nom de la machine).

Le problème est: à des heures aléatoires du jour/de la nuit, l'application enregistre ceci:

Exception information: 
Exception type: ReceiverDisconnectedException 
Exception message: New receiver with higher Epoch of '186' is created hence current receiver with Epoch '186' is getting disconnected. If you are recreating the receiver, make sure a higher Epoch is used.
  at Microsoft.ServiceBus.Common.ExceptionDispatcher.Throw(Exception exception)
  at Microsoft.ServiceBus.Common.Parallel.TaskHelpers.EndAsyncResult(IAsyncResult asyncResult)
  at Microsoft.ServiceBus.Messaging.IteratorAsyncResult`1.StepCallback(IAsyncResult result)

Cette exception se produit en même temps qu'une LeaseLostException, levée à partir de la méthode CloseAsync de MyEventProcessor lorsqu'il essaie de vérifier. (On peut supposer que Close est appelé en raison de ReceiverDisconnectedException?)

Je pense que cela se produit en raison de la gestion automatique des baux d'Event Hubs lors de la mise à l'échelle sur plusieurs machines. Mais je me demande si je dois faire quelque chose de différent pour le faire fonctionner plus proprement et éviter ces exceptions? Par exemple: quelque chose avec des époques?

23
plukich

[~ # ~] tldr [~ # ~] : Ce comportement est absolument normal.

Pourquoi la gestion des baux ne peut-elle pas être fluide et sans exception : Pour donner plus de contrôle sur la situation au développeur.

La très longue histoire - tout le chemin depuis les bases EventProcessorhost (ici EPH - est très similaire à ce que __consumer_offset topic Fait pour Kafka Consumers - propriété de la partition et magasin de points de contrôle) est écrit par l'équipe de Microsoft Azure EventHubs Elle-même - pour traduire tous les EventHubs partition receiver Gu En une simple fonction onReceive(Events) rappeler.

EPH est utilisé pour résoudre 2 problèmes généraux, majeurs et bien connus lors de la lecture d'un flux partitionné à haut débit comme EventHubs:

  1. pipe-line de réception tolérant aux pannes - par exemple: une version plus simple du problème - si l'hôte exécutant un PartitionReceiver meurt et revient - il doit reprendre le traitement là où il est parti. Pour se souvenir du dernier traitement réussi de EventData, EPH utilise le blob fourni au constructeur EPH pour stocker les points de contrôle - chaque fois que l'utilisateur invoque context.CheckpointAsync(). Finalement, lorsque le processus hôte meurt (par exemple, redémarre brusquement ou frappe une défaillance matérielle et ne revient jamais) - n'importe quelle instance EPH peut reprendre cette tâche et reprendre à partir de cette Checkpoint.

  2. Équilibrer/distribuer des partitions sur EPH instances - disons s'il y a 10 partitions et 2 EPH instances traitant des événements à partir de ces 10 partitions - nous avons besoin d'un moyen de diviser les partitions entre les instances (le composant PartitionManager de la bibliothèque EPH le fait). Nous utilisons Azure Storage - Blob LeaseManagement-feature pour implémenter cela. Depuis la version 2.2.10 - pour simplifier le problème, EPH suppose que toutes les partitions sont chargées de manière égale .

Avec cela, essayons de voir ce qui se passe: Donc, pour commencer, dans l'exemple ci-dessus de partitions de concentrateur d'événements 10 Et d'instances 2EPH traitant des événements à partir de celles-ci :

  1. disons que la première instance de EPH - EPH1 a démarré, au début, seule et une partie du démarrage, elle a créé des récepteurs pour les 10 partitions et traite les événements. Au démarrage - EPH1 Annoncera qu'il possède toutes ces partitions 10 En acquérant des baux sur des objets de stockage 10 Représentant ces partitions de concentrateur d'événements 10 (Avec un nomenclature standard - que EPH crée en interne dans le compte de stockage - du StorageConnectionString transmis au ctor). Les baux seront acquis pour une durée définie , après quoi l'instance EPH perdra la propriété de cette partition.
  2. EPH1 Continuellement announces de temps en temps - qu'il est toujours propriétaire de ces partitions - par renewing baux sur le blob. La fréquence de renewal, ainsi que d'autres réglages utiles, peuvent être effectués en utilisant PartitionManagerOptions
  3. maintenant, disons, EPH2 démarre - et vous avez également fourni le même AzureStorageAccount que EPH1 au ctor de EPH2. À l'heure actuelle, il a des partitions 0 À traiter. Ainsi, pour atteindre l'équilibre des partitions entre les instances de EPH, il ira de l'avant et download la liste de tous leaseblobs qui a le mappage de owner vers partitionId. À partir de cela, il louera STEAL pour sa juste part de partitions - qui est 5 dans notre exemple, et annoncera cette information sur ce lease blob. Dans ce cadre, EPH2 Lit le dernier point de contrôle écrit par PartitionX pour lequel il veut voler le bail et va de l'avant et crée les PartitionReceiver correspondants avec le Epoch identique à celui du Checkpoint.
  4. Par conséquent, EPH1 Perdra la propriété de ces 5 partitions et se heurtera à différentes erreurs en fonction de l'état exact dans lequel il se trouve.
    • si EPH1 invoque réellement l'appel PartitionReceiver.Receive() - tandis que EPH2 crée le PartitionReceiver sur le même récepteur - EPH1 connaîtra - ReceiverDisconnectedException . Cela finira par appeler IEventProcessor.Close(CloseReason=LeaseLost). Notez que la probabilité de toucher cette exception spécifique est plus élevée si les messages reçus sont plus gros ou si PrefetchCount est plus petit - comme dans les deux cas, le récepteur effectuerait des E/S plus agressives.
    • si EPH1 est dans l'état de checkpointing le lease ou renewing le lease, tandis que le EPH2stole le bail, le gestionnaire d'événements EventProcessorOptions.ExceptionReceived Serait signalé avec une erreur de conflit leaselostException (avec 409 Sur le leaseblob) - qui finit également par être invoquée IEventProcess.Close(LeaseLost).

Pourquoi la gestion des baux ne peut-elle pas être fluide et sans exception :

Pour que le consommateur reste simple et sans erreur, les exceptions liées à la gestion des baux auraient pu être avalées par EPH et non notifiées du tout au code utilisateur. Cependant, nous avons réalisé que lancer LeaseLostException pourrait permettre aux clients de trouver des bogues intéressants dans la fonction de rappel IEventProcessor.ProcessEvents() - pour lequel le symptôme serait - des mouvements de partition fréquents

  • panne de réseau mineure sur une machine spécifique - en raison de laquelle EPH1 ne parvient pas à renew baux et revient! - et imaginez si le n/w de cette machine est instable pendant un jour - EPH les instances vont jouer ping-pong avec Partitions! Cette machine essaiera continuellement de voler le bail d'une autre machine - ce qui est légitime du point de vue EPH - mais, c'est un désastre total pour l'utilisateur de EPH - car il interfère complètement avec le tuyau de traitement. EPH - verrait exactement un ReceiverDisconnectedException, lorsque le n/w revient sur ce m/c feuilleté! Nous pensons que le meilleur et en fait le seul moyen est de permettre au développeur de sentir cela!
  • ou un scénario simple comme, avoir un bogue dans la logique ProcessEvents - qui lève des exceptions non gérées qui sont fatales et fait tomber tout le processus - ex: un événement empoisonné. Cette partition va beaucoup bouger.
  • clients, effectuant des opérations d'écriture/suppression sur le même compte de stockage que EPH utilise également - par erreur (comme un script de nettoyage automatisé), etc.
  • dernier point mais non le moindre - ce que nous ne souhaitons jamais que cela puisse arriver - disons un 5 $ outage sur Azure d.c où se trouve un EventHub.Partition spécifique - disons un incident n/w. Les partitions vont se déplacer entre les instances de EPH.

Fondamentalement, dans la majorité des situations, il serait difficile - pour nous de détecter le diff. entre ces situations et un bail légitime perdu en raison de l'équilibrage et nous voulons déléguer le contrôle de ces situations au développeur.

plus sur Event Hubs ...

46
Sreeram Garlapati