web-dev-qa-db-ja.com

eventhubでのチェックポインティングを理解する

Eventhubクライアント(現在はコンソールアプリケーション)がクラッシュした場合に、eventhubからまだ取得していないイベントのみを取得するようにしたいです。これを実現する1つの方法は、オフセットを利用することです。ただし、これは(私の理解では)クライアントが最新のオフセットを格納する必要があります(イベントがSequenceNumberで順序付けられたProcessEventsAsyncメソッドのforeachループにヒットするとは限らないことを除いて)。

別の方法は、チェックポイントを使用することです。提供されたストレージアカウントの資格情報を使用して、サーバー(eventhub)を介して永続化されると思います。これは正しいです?

これは私が現在使用しているいくつかの予備的なコードです:

public class SimpleEventProcessor : IEventProcessor
{
    private Stopwatch _checkpointStopWatch;

    async Task IEventProcessor.CloseAsync(PartitionContext context, CloseReason reason)
    {
        Console.WriteLine("Processor Shutting Down. Partition '{0}', Reason: '{1}'.", context.Lease.PartitionId, reason);
        if (reason == CloseReason.Shutdown)
        {
            await context.CheckpointAsync();
        }
    }

    Task IEventProcessor.OpenAsync(PartitionContext context)
    {
        Console.WriteLine("SimpleEventProcessor initialized.  Partition: '{0}', Offset: '{1}'", context.Lease.PartitionId, context.Lease.Offset);
        _checkpointStopWatch = new Stopwatch();
        _checkpointStopWatch.Start();
        return Task.FromResult<object>(null);
    }

    async Task IEventProcessor.ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> messages)
    {
        foreach (var eventData in messages)
        {
            // do something                    
        }

        //Call checkpoint every 5 minutes, so that worker can resume processing from 5 minutes back if it restarts.
        if (_checkpointStopWatch.Elapsed > TimeSpan.FromMinutes(5))
        {
            await context.CheckpointAsync();
            _checkpointStopWatch.Restart();
        }
    }
}

5分ごとにサーバーにチェックポイントを送信すると思います。サーバーは、どのクライアントが(コンテキストを介して)チェックポイントを送信したかをどのように認識しますか?また、クライアントが再起動した場合にイベントが再度処理されないようにするにはどうすればよいですか?さらに、イベントが再度処理される最大5分のウィンドウが存在する可能性があります。おそらく、要件を考慮して、キュー/トピックを使用する必要がありますか?

PS:

これで十分なようです:

async Task IEventProcessor.ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> messages)
{
    foreach (var eventData in messages)
    {
        // do something
    }
    await context.CheckpointAsync();
}
13
cs0815

Lemmeは、答える前にいくつかの基本的な用語を提示しました

EventHubs は、高スループットで耐久性のあるイベント取り込みパイプラインです。簡単に言えば、クラウド上の信頼できるイベントのストリームです。

EventDataのオフセット(ストリーム内の1つのイベント)は、文字通りストリーム上のカーソルです。このカーソルを設定すると、次のような操作が可能になります。このカーソルからの読み取りを再開します(別名オフセット)。包括的または排他的です。

EventProcessorライブラリは、EventHubsチームが構築したフレームワークであり、ServiceBus SDKの上に、「eventhubレシーバーgu」をより簡単に表示します。 ZooKeeper for Kafka <-> EPH for Event Hub 。特定のパーティションでEventProcessorを実行しているプロセスが停止/クラッシュしたときに確認します- 最後のチェックポイントオフセットから再開-他の利用可能なEventProcessorHostインスタンスで。

CheckPoint :本日現在-EventHubsはクライアント側のチェックポイントのみをサポートします。クライアントコードからチェックポイントを呼び出す場合:

await context.CheckpointAsync();

-ストレージ呼び出しに変換されます(クライアントから直接)-指定したストレージアカウントに現在のオフセットを保存します。 EventHubsサービスはチェックポイントのためにストレージと通信しません。

答え

EventProcessorフレームワークは、まさにあなたが探しているものを達成することを目的としています。

チェックポイントはサーバー(別名EVENTHUBSサービス)を介して永続化されません。その純粋にクライアント側。 Azureストレージと通信しています。これが、EventProcessorライブラリが新しい追加の依存関係をもたらす理由です AzureStorageClient 。チェックポイントが書き込まれるストレージアカウントとコンテナに接続できます-所有権情報を維持します-所有するEventHubsのパーティションへのEPHインスタンス(名前)と、現在どのチェックポイントで読み取り/処理されるか。

タイマーベースのチェックポイントのパターン(元々あった)に従って、プロセスがダウンした場合、最後の5分間のウィンドウでイベントを再実行します。これは次のような健全なパターンです。

  1. 基本的な前提は、障害はまれなイベントであるということです-したがって、重複するイベントを処理することはめったにありません
  2. 最終的にはストレージサービスへの呼び出しが少なくなります(頻繁にチェックポイントを設定することで簡単に圧倒される可能性があります)。私はさらに一歩進んで、実際には、チェックポイント呼び出しを非同期で起動します。チェックポイントが失敗しても、OnProcessEventsは失敗する必要はありません。

イベントをまったく繰り返さないようにする場合は、この重複排除ロジックをダウンストリームパイプラインで構築する必要があります。

  • eventProcessorImplが開始するたびに、ダウンストリームに最後のシーケンス番号を照会します。現在のシーケンス番号までイベントを取得して破棄し続けます。

イベントハブに関するより一般的な読み物です...

21