个人资料

跳过导航链接首页 > 博客列表 > 博客正文

C#限制http client访问速度

:

要在 .NET 中使用速率限制,请引用 System.Threading.RateLimiting NuGet 包

使用示例

 //HttpClient client = new HttpClient();
 HttpClient client = StaticHttpClient._client;

 client.DefaultRequestHeaders.Accept.Clear();
 string region = host_platform.GetHostFromPlatform(platform);

 var url = $"https://{region}/lol/summoner/v4/summoners/{sid}";

 HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url);
 request.Headers.Add("X-Riot-Token", UserSearch.api_key);

 var ms = await client.SendAsync(request);
 var json = await ms.Content.ReadAsStringAsync();

 var result = JsonConvert.DeserializeObject<Summoner>(json);
代码
    internal class StaticHttpClient
    {

        static StaticHttpClient() 
        {

            
            var options = new TokenBucketRateLimiterOptions
            {
                TokenLimit = 100,
                QueueProcessingOrder = QueueProcessingOrder.OldestFirst,
                QueueLimit = 100,
                ReplenishmentPeriod = TimeSpan.FromSeconds(0.05),///1.2s    //0.05
                TokensPerPeriod = 200,
                AutoReplenishment = true
            };

            // Create an HTTP client with the client-side rate limited handler.
            _client = new HttpClient(new ClientSideRateLimitedHandler(new TokenBucketRateLimiter(options)));
       


        }




        public static HttpClient _client { get; set; }




    }


    internal sealed class ClientSideRateLimitedHandler : DelegatingHandler, IAsyncDisposable
    {

        RateLimiter limiter;
        public ClientSideRateLimitedHandler(RateLimiter _limiter) : base(new HttpClientHandler())
        {
            limiter = _limiter;
        }



        protected override async Task<HttpResponseMessage> SendAsync(
            HttpRequestMessage request, CancellationToken cancellationToken)
        {

            using (RateLimitLease lease = await limiter.AcquireAsync(permitCount: 1, cancellationToken))
            {
                if (lease.IsAcquired)
                {
                    return await base.SendAsync(request, cancellationToken);
                }

                var response = new HttpResponseMessage((System.Net.HttpStatusCode)429);
                if (lease.TryGetMetadata(
                        MetadataName.RetryAfter, out TimeSpan retryAfter))
                {
                    response.Headers.Add(
                        "Retry-After",
                        ((int)retryAfter.TotalSeconds).ToString(
                            NumberFormatInfo.InvariantInfo));
                }

                return response;
            }



        }


        async ValueTask IAsyncDisposable.DisposeAsync()
        {
            await limiter.DisposeAsync().ConfigureAwait(false);

            Dispose(disposing: false);
            GC.SuppressFinalize(this);
        }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);

            if (disposing)
            {
                limiter.Dispose();
            }
        }
    }

核心参数解释:

1.ReplenishmentPeriod‌:令牌补充的时间间隔(如 TimeSpan.FromSeconds(1) 表示每隔1秒补充一次)

2.TokensPerPeriod‌:每个补充周期添加的令牌数量(如设置为10,则每秒补充10个令牌)

3.TokenLimit‌:令牌桶的容量上限(如设为100,桶内令牌数最多为100)

实际允许的请求速率由 ‌TokensPerPeriod / ReplenishmentPeriod‌ 计算得出。例如:
若 ReplenishmentPeriod = 1秒, TokensPerPeriod = 10 → ‌每秒允许10次请求‌

参考

https://learn.microsoft.com/zh-cn/dotnet/core/extensions/http-ratelimiter

songshizhao
最初发表2024/10/13 12:48:08 最近更新2025/6/10 9:31:05 362
为此篇作品打分
10