.net 写了一个支持重试、熔断和超时策略的 HttpClient 实例池

编程入门 行业动态 更新时间:2024-10-28 02:26:16

.net <a href=https://www.elefans.com/category/jswz/34/1771059.html style=写了一个支持重试、熔断和超时策略的 HttpClient 实例池"/>

.net 写了一个支持重试、熔断和超时策略的 HttpClient 实例池

public class HttpClientPool : IDisposable
{private readonly ConcurrentQueue<HttpClient> _httpClientPool; // HttpClient 对象池private readonly SemaphoreSlim _semaphore; // 控制同时访问 HttpClient 对象池的线程数private readonly TimeSpan _timeout; // 获取 HttpClient 的超时时间private readonly int _maxRetries; // 最大重试次数private readonly TimeSpan _circuitBreakerTimeout; // 熔断器超时时间private readonly int _consecutiveFailuresThreshold; // 连续失败阈值private bool _circuitBreakerTripped; // 熔断器是否触发private DateTime _circuitBreakerTrippedTime; // 熔断器触发时间private int _consecutiveFailures; // 连续失败计数器public HttpClientPool(int maxPoolSize, // 最大 HttpClient 对象池大小TimeSpan timeout, // 获取 HttpClient 的超时时间int maxRetries, // 最大重试次数TimeSpan circuitBreakerTimeout, // 熔断器超时时间int consecutiveFailuresThreshold // 连续失败阈值){_httpClientPool = new ConcurrentQueue<HttpClient>();_semaphore = new SemaphoreSlim(maxPoolSize);_timeout = timeout;_maxRetries = maxRetries;_circuitBreakerTimeout = circuitBreakerTimeout;_consecutiveFailuresThreshold = consecutiveFailuresThreshold;_circuitBreakerTripped = false;}public async Task<HttpResponseMessage> SendRequestWithRetries(string url){var retryCount = 0;_consecutiveFailures = 0;while (retryCount <= _maxRetries){try{var httpClient = await GetHttpClientAsync();var response = await httpClient.GetAsync(url);if (response.IsSuccessStatusCode){_consecutiveFailures = 0; // 重置连续失败计数器return response;}else{_consecutiveFailures++;if (_consecutiveFailures >= _consecutiveFailuresThreshold){TripCircuitBreaker(); // 连续失败达到阈值,触发熔断器throw new InvalidOperationException("连续失败次数达到阈值,熔断器已触发。");}retryCount++;}}catch (Exception ex){_consecutiveFailures++;if (_consecutiveFailures >= _consecutiveFailuresThreshold){TripCircuitBreaker(); // 连续失败达到阈值,触发熔断器throw new InvalidOperationException("连续失败次数达到阈值,熔断器已触发。");}retryCount++;}}throw new Exception($"重试 {_maxRetries} 次后仍然无法发送请求。");}private async Task<HttpClient> GetHttpClientAsync(){if (_circuitBreakerTripped){var elapsedTime = DateTime.Now - _circuitBreakerTrippedTime;if (elapsedTime < _circuitBreakerTimeout){throw new InvalidOperationException("熔断器已触发,请稍后重试。");}else{// 重置熔断器_circuitBreakerTripped = false;}}if (await _semaphore.WaitAsync(_timeout)){if (_httpClientPool.TryDequeue(out var httpClient)){return httpClient;}}throw new TimeoutException("获取 HttpClient 超时。");}public void ReturnHttpClient(HttpClient httpClient, bool success){if (success){_httpClientPool.Enqueue(httpClient);_semaphore.Release();}else{// 触发熔断器TripCircuitBreaker();httpClient.Dispose();_semaphore.Release();}}private void TripCircuitBreaker(){_circuitBreakerTripped = true;_circuitBreakerTrippedTime = DateTime.Now;_consecutiveFailures = 0;}public void Dispose(){foreach (var httpClient in _httpClientPool){httpClient.Dispose();}_httpClientPool.Clear();_semaphore.Dispose();}
}

调用端
 

public class Program
{public static async Task Main(){// 创建 HttpClientPoolvar httpClientPool = new HttpClientPool(maxPoolSize: 10,timeout: TimeSpan.FromSeconds(5),maxRetries: 3,circuitBreakerTimeout: TimeSpan.FromMinutes(10),consecutiveFailuresThreshold: 5);try{var response = await httpClientPool.SendRequestWithRetries("");var content = await response.Content.ReadAsStringAsync();Console.WriteLine(content);}catch (Exception ex){Console.WriteLine($"请求失败:{ex.Message}");}}
}

更多推荐

.net 写了一个支持重试、熔断和超时策略的 HttpClient 实例池

本文发布于:2023-11-30 14:00:46,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1651019.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:写了   重试   实例   策略   net

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!