web-dev-qa-db-ja.com

Azure Event HubsのReceiverDisconnectedException / LeaseLostExceptionの原因は何ですか?

EventProcessorHostとIEventProcessorクラスを使用して、EventHubからイベントを受信して​​います(MyEventProcessorと呼びます)。両方のサーバーでEPHを実行し、同じConsumerGroupを使用して(マシン名を使用して)一意のhostNameを使用してハブに接続することにより、これを2台のサーバーにスケールアウトします。

問題は次のとおりです。昼夜のランダムな時間に、アプリはこれをログに記録します。

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)

この例外は、LeaseLostExceptionと同時に発生し、MyEventProcessorのCloseAsyncメソッドがチェックポイントを試みたときにスローされます。 (おそらくReceiverDisconnectedExceptionのためにCloseが呼び出されていますか?)

これは、複数のマシンにスケールアウトする際のEvent Hubsの自動リース管理が原因で発生していると思います。しかし、私はそれをよりきれいに機能させ、これらの例外を回避するために別のことをする必要があるかどうか疑問に思っていますか?例:エポックのあるもの?

23
plukich

[〜#〜] tldr [〜#〜]:この動作はまったく正常です。

リース管理を円滑かつ例外なく行うことができない理由:開発者に状況をより詳細に制御するため。

本当に長い話-基本からの道のりEventProcessorhost(これによりEPH-は、 __consumer_offset topicKafka Consumersに対して行います(パーティションの所有権とチェックポイントストア)はMicrosoft Azure EventHubsチーム自身によって記述され、EventHubs partition receiver Guのすべてを単純なonReceive(Events)コールバックに変換します。

EPHは、EventHubsのような高スループットのパーティション化されたストリームからの読み取り中に、2つの一般的な主要な既知の問題に対処するために使用されます。

  1. フォールトトレラントな受信パイプライン-例:単純なバージョンの問題-PartitionReceiverを実行しているホストが停止して復帰した場合-元の場所から処理を再開する必要があります。最後に正常に処理されたEventDataを記憶するために、EPHblobコンストラクターに提供されたEPHを使用してチェックポイントを格納します-ユーザーがcontext.CheckpointAsync()。最終的に、ホストプロセスが停止すると(例:突然再起動するか、ハードウェアの障害に遭遇し、決して/カムバックしません)-すべてのEPHインスタンスがこのタスクを受け取り、そのCheckpointから再開できます。

  2. EPHインスタンス間でパーティションのバランスをとる/分散する-たとえば、10個のパーティションと2つのEPHインスタンス処理イベントがある場合これら10個のパーティションから-インスタンス間でパーティションを分割する方法が必要です(PartitionManagerライブラリのEPHコンポーネントがこれを行います)。これを実装するには、Azure Storage - Blob LeaseManagement-featureを使用します。バージョン 2.2.10 -問題を簡単にするために、EPHすべてのパーティションが均等にロードされると想定します

これで、何が起こっているのかを確認してみましょう:まず、上記の10イベントハブパーティションと2EPHインスタンスがそこからイベントを処理する例を見てみましょう。

  1. 最初のEPHインスタンス-EPH1が最初に起動し、単独で起動の一部であるとしましょう。10個のパーティションすべてにレシーバーを作成し、イベントを処理しています。起動時に、EPH1は、これらの10イベントハブパーティションを表す10ストレージBLOBのリースを取得することにより、これらすべての10パーティションを所有していることを通知します(標準nomenclature- EPHがストレージアカウントで内部的に作成するもの-StorageConnectionStringからctorに渡されます)。リースは 設定された時間で取得 となり、その後、EPHインスタンスはこのパーティションの所有権を失います。
  2. EPH1継続的にannouncesがたまにrenewingによって、これらのパーティションをまだ所有している-renewalによってBLOBがリースされます。 PartitionManagerOptionsの頻度は、他の有用なチューニングとともに、 AzureStorageAccount を使用して実行できます。
  3. さて、EPH2が起動し、EPH1と同じctorEPH2EPHにも提供したとします。現在、処理する0パーティションがあります。したがって、downloadインスタンス間でパーティションのバランスを達成するために、それは先に進み、leaseblobsownerから_へのマッピングを持つすべてのpartitionIdのリスト[$ var] _。これから、それはSTEALの公平な配分のためにpartitions leasesになります-これは5ですこの例では、そのlease blobに関する情報を発表します。この一部として、EPH2PartitionXによって書き込まれた最新のチェックポイントを読み取り、リースを盗み取り、先に進み、対応するPartitionReceiverEpochと同じに作成します。 Checkpointの1つとして。
  4. その結果、EPH1はこれら5つのpartitionsの所有権を失い、現在の状態に基づいてさまざまなエラーが発生します。
    • EPH1が実際にPartitionReceiver.Receive()呼び出しを呼び出している場合-EPH2が同じレシーバーでPartitionReceiverを作成している場合-EPH1が発生します ReceiverDisconnectedException 。これにより、最終的にIEventProcessor.Close(CloseReason=LeaseLost)が呼び出されます。受信されるメッセージが大きい場合、またはPrefetchCountが小さい場合、この特定の例外にヒットする可能性が高くなることに注意してください。どちらの場合も、レシーバーはより積極的なI/Oを実行します。
    • EPH1checkpointing the leaseまたはrenewing the leaseの状態の場合、EPH2stoleリース、EventProcessorOptions.ExceptionReceived eventHandlerはleaselostExceptionleaseblobでの409競合エラーとともに)で通知されます-これは最終的にIEventProcess.Close(LeaseLost)

リース管理を円滑かつ例外なく行うことができない理由

コンシューマをシンプルでエラーのない状態に保つために、リース管理関連の例外がEPHによって飲み込まれ、ユーザーコードにまったく通知されない可能性があります。ただし、LeaseLostExceptionをスローすると、IEventProcessor.ProcessEvents()コールバックで興味深いバグを発見できるようになる可能性があることに気づきました-症状は次のとおりです-パーティションの頻繁な移動

  • 特定のマシンでのマイナーなネットワーク停止-これにより、EPH1renewのリースに失敗し、復旧します。 -そして、このマシンのn/wが1日間不安定であると想像してみてください-EPHインスタンスがping-pongPartitionsと再生します!このマシンは、他のマシンからリースを継続的に盗もうとします-これはEPHの観点からは正当ですが、EPHのユーザーにとっては完全な障害であるため、完全な災害です処理パイプ付き。 EPH-n/wがこの不安定なm/cに戻ったとき、ReceiverDisconnectedExceptionが正確に表示されます。私たちは、開発者がこれを嗅ぐことを可能にすることが最善で実際的な唯一の方法であると考えています!
  • または、ProcessEventsロジックにバグがある-致命的な未処理の例外をスローし、プロセス全体を停止させるような単純なシナリオ-例:有害イベント。このパーティションは頻繁に移動します。
  • EPHも使用しているのと同じストレージアカウントで書き込み/削除操作を実行しているお客様-誤って(自動クリーンアップスクリプトなど)など。
  • 最後になりましたが、決して起こりません-特定のEventHub.Partitionが配置されているAzure d.cで5分outageと言ってください。パーティションはEPHインスタンス間を移動します。

基本的に、ほとんどの状況で、差分を検出するのは難しいでしょう。これらのシチュエーションとバランシングによる正当なleaseLostの間で、これらのシチュエーションの制御を開発者に委任したいと考えています。

イベントハブの詳細...

46