1

Service Fabric でホストされるステートフル サービスを作成しています。このサービスの仕事は、外部キューからのメッセージを消費し、それらを変換して、独自のメッセージング システムに配置することです。サプライヤのドキュメントによると、スループットは最大 6k メッセージ/秒です。

メッセージの負荷を分散するためにサービスを複数のパーティションに構成しました。各パーティションには最小 2/最大 3 のレプリカがあります。障害から回復するには、サプライヤ キューにサブスクライブし、メッセージを受信したい時点からタイムスタンプを渡します。これを行うために、サービス状態で処理された最後のメッセージのタイムスタンプを保存しています。メッセージの量が多いため、タイマーでこれを「保存」することにしました(そして、ダウンストリームのメッセージの潜在的な重複を許可します)

これは、その時点で呼び出されるコードです。

private async void _timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        var saveRetryPolicy = Policy
            .Handle<Exception>()
            .WaitAndRetryAsync(5, retryAttempt =>
                TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))
            );

        await saveRetryPolicy.ExecuteAsync(async () =>
        {
            using (var tx = _stateManager.CreateTransaction())
            {
                var state = await _stateManager.TryGetAsync<IReliableDictionary<string, long>>(TimestampStateName);

                if (state.HasValue)
                {
                    await state.Value.AddOrUpdateAsync(tx, TimestampStateName, _lastTXTimestamp,
                        (s, l) => _lastTXTimestamp);

                    await tx.CommitAsync();
                }
                else
                {
                    var s =
                        await _stateManager.GetOrAddAsync<IReliableDictionary<string, long>>(tx, TimestampStateName);

                    await tx.CommitAsync();
                    _timer_Elapsed(this, null);
                }
            }
        });
    }

これを永続化しようとするたびに、各パーティションで「System.Fabric.FabricNotPrimaryException」エラーが発生します。

再試行ポリシー (Polly Retry の好意による) を含めました。これを行うことを推奨する同様の問題に関するコメントがあったためです。これは効果がなく、エラーが報告されるまでの時間が長くなりました。

SF をどのように使用すべきかについて、何か根本的なことを誤解していますか? これは私には単純な使用例のようです。

4

1 に答える 1

2

コメントからの回答:

すべてのレプリカでタイマーを開始するのではなく、プライマリ レプリカでのみ開始するようにしてください。

于 2016-11-22T12:56:59.840 に答える