要在 .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(); } } }
参考
https://learn.microsoft.com/zh-cn/dotnet/core/extensions/http-ratelimiter