簡體   English   中英

使用 Castle.Windsor 和 Polly 響應 429 異常(節流)

[英]Responding to 429 exceptions (throttling) using Castle.Windsor and Polly

我們正在處理 429 個 HTTP 異常(來自 SharePoint 在線或 Microsoft Graph),我想利用 Polly 和 Castle.Windsor 來處理這個問題。

我的代碼是(摘錄)

在我的 Castle.Windsor 容器中注冊 Polly 的東西:

_container.Register(Component.For<IRepository>()
            .ImplementedBy<Repository>()
            .DependsOn(Dependency.OnValue<ImportSettings>(_importSettings))
            .Interceptors(InterceptorReference.ForKey("throttle")).Anywhere
            .LifestyleTransient());

 _container.Register(Component.For<WaitAndRetryInterceptor<WebException>>().LifeStyle.Singleton
    .Named("throttle"));

我的波莉資料:

 public class WaitAndRetryInterceptor<T> : IInterceptor where T : WebException
    {
        private readonly RetryPolicy _policy;

        public void Intercept(IInvocation invocation)
        {
            var dictionary = new Dictionary<string, object> {{"methodName", invocation.Method.Name}};

            _policy.Execute(invocation.Proceed, dictionary);
        }

        public WaitAndRetryInterceptor()
        {
            _policy =
                Policy
                    .Handle<T>()
                    .WaitAndRetry(new[]
                    {
                        TimeSpan.FromSeconds(16), TimeSpan.FromSeconds(32), TimeSpan.FromSeconds(64),
                        TimeSpan.FromSeconds(128), TimeSpan.FromSeconds(256), TimeSpan.FromSeconds(512)
                    });
        }
    }

所以這個實現滿足了我的需要——但它非常保守。 因此,我嘗試實現對拋出的 429 異常的直接支持——特別是對服務器提供的Reply-After header 的支持。

我從這個https://github.com/App-vNext/Polly/issues/414中發現,我需要實現對采用sleepDurationProvider的重載之一的支持,但是我在正確編寫代碼時遇到了問題。

我的實現是這樣的:

_policy =
  Policy
    .Handle<HttpRequestException>()
    .OrResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.Accepted) //needs to be changed to 429
    .WaitAndRetryAsync(
        retryCount: 3,
        sleepDurationProvider: (retryCount, response) =>
        {
            return getServerWaitDuration(response);
        })
;

getServerWaitDuration只返回一個TimeSpan

private TimeSpan getServerWaitDuration(DelegateResult<HttpResponseMessage> response)
{
    return TimeSpan.Zero;  //not actual code ;-)
}

這個想法是我將簡單地查看來自服務器的響應的標頭並將時間跨度傳遞回sleepDurationProvider

但是 - 我從配置sleepDurationProvider的行中收到錯誤。 我被告知(retryCount, response)是“不兼容的匿名 function 簽名”

我覺得我在這里遺漏了一些明顯的東西。 但為什么? 如何訪問response object 以提取Retry-After持續時間?

您可能會像這樣查看標題

public AsyncRetryPolicy<HttpResponseMessage> GetRetryPolicy()
        {
            return HttpPolicyExtensions
                .HandleTransientHttpError()
                .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.TooManyRequests)
                .OrResult(r =>  r?.Headers?.RetryAfter != null)
                .WaitAndRetryAsync(
                    3,
                    sleepDurationProvider: (retryCount, response, context) =>
                    {
                        return response.Result.Headers.RetryAfter.Delta.Value;
                    },
                    onRetryAsync: (e, ts, i, ctx) => Task.CompletedTask
                );
        }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM