我在结合HttpClient
设置Polly的断路器时遇到了问题。
具体来说,CircuitBreaker
和HttpClient
用于ASP.NET Core Web API Controller,其链接如下:
>
重试策略:如果出现暂时错误,则对每个请求重试3次。
cicuit断路器策略:如果所有请求中出现五个瞬态错误,则生效。
问题所在
配置Polly重试策略和断路器策略,并对自定义HttpClient,HttpClientService
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpClient();
services.AddHttpClient<IHttpClientService, HttpClientService>()
.AddPolicyHandler((service, request) =>
HttpPolicyExtensions.HandleTransientHttpError()
.WaitAndRetryAsync(3,
retryCount => TimeSpan.FromSeconds(Math.Pow(2, retryCount)),
onRetry: (outcome, timespan, retryCount, context) =>
{
service.GetService<ILog>().Error("Delaying for {delay}ms, then making retry {retry}.",
timespan.TotalMilliseconds, retryCount);
}
)
)
)
.AddPolicyHandler((service, request) =>
HttpPolicyExtensions.HandleTransientHttpError()
//Further external requests are blocked for 30 seconds if five failed attempts occur sequentially.
//Circuit breaker policies are stateful.All calls through this client share the same circuit state.
.CircuitBreakerAsync(5,
TimeSpan.FromSeconds(30),
(result, timeSpan, context)=>
service.GetService<ILog>().Error("CircuitBreaker onBreak for {delay}ms", timeSpan.TotalMilliseconds),
context =>
service.GetService<ILog>().Error("CircuitBreaker onReset")));
}
CarController
IHttpClientService
是在ConfiguReservices
的Polly策略中指定的。HttpClientService
使用HttpClient
。
[ApiVersion("1")]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiController]
public class CarController : ControllerBase
{
private readonly ILog _logger;
private readonly IHttpClientService _httpClientService;
private readonly IOptions<Config> _config;
public CarController(ILog logger, IHttpClientService httpClientService, IOptions<Config> config)
{
_logger = logger;
_httpClientService = httpClientService;
_config = config;
}
[HttpPost]
public async Task<ActionResult> Post()
{
using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8))
{
string body = reader.ReadToEnd();
var statusCode = await _httpClientService.PostAsync(
"url",
new Dictionary<string, string>
{
{"headerID", "Id"}
},
body);
return StatusCode((int)statusCode);
}
}
}
public class HttpClientService
{
private readonly HttpClient _httpClient;
public HttpClientService(HttpClient client)
{
_httpClient = client;
}
public async Task<HttpStatusCode> PostAsync(string url, Dictionary<string, string> headers, string body)
{
using (var content = new StringContent(body, Encoding.UTF8, "application/json"))
{
foreach (var keyValue in headers)
{
content.Headers.Add(keyValue.Key, keyValue.Value);
}
var request = new HttpRequestMessage(HttpMethod.Post, url)
{
Content = content
};
var response = await _httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
return response.StatusCode;
}
}
ASP.NET核心API 2.2
更新已更新的SetWaitAndRetryPolicy扩展方法以使用IServiceProvider。
断路器策略是有状态的,可以跟踪各个调用的故障率,因此需要长期使用,而不是根据每个请求创建。
所发布代码中HttpClientFactory上重载的使用方式:
.AddPolicyHandler((service, request) => HttpPolicyExtensions.HandleTransientHttpError()
.CircuitBreakerAsync( /* etc */
是制造一个实例的断路器每一个请求,所以断路器从来没有时间建立一个故障状态。
.AddPolicyHandler(HttpPolicyExtensions.HandleTransientHttpError()
.WaitAndRetryAsync(/* etc */))
.AddPolicyHandler(HttpPolicyExtensions.HandleTransientHttpError()
.CircuitBreakerAsync(/* etc */))
var circuitBreaker = HttpPolicyExtensions.HandleTransientHttpError().CircuitBreakerAsync(/* etc */);
services.AddHttpClient<IHttpClientService, HttpClientService>()
.AddPolicyHandler((service, request) => circuitBreaker); // By way of example technique: more typically with this overload, there is some more complex logic to select different policies for different kinds of request.
编辑以回答注释中的问题:该实例不必声明static
以使其长期存在。它可以在startup.configureservices(...)
方法中声明,就在使用之前,如上面的代码示例所示。lambda并在HttpClientFactory上配置它将捕获它并使其长期存在。
circuitbreaker
实例应该在您想要中断的调用之间共享。如果将断路器附加到通过HttpClientFactory声明的特定HttpClient
配置,则所有通过该HttpClient
配置实例的调用都将共享该断路器,从而共享中断。
当将断路器与HttpClientFactory一起使用时,这通常意味着您可以在每个子系统上声明一个HttpClient
配置(键入或命名),您希望对其进行断路器调用。
旁注:所选断路器的变种也根据连续故障计数触发。(这里提到的只是一个额外的因素;发布的问题提到了跨请求发生的5个错误,但不是具体连续发生的。)
.NET核心和ASP.NET核心到底有什么区别?
我有以下政策: 我是这样执行政策的: 问题是,当一个动作在开路上执行时,我在断路器回调中没有得到命中。 我希望通过策略放置一个API调用,要处理的异常类型为。政策定义有问题吗?为什么不叫断路器后备?
我和我的朋友在我们的应用编程接口和角客户端上遇到了CORS问题。我们试图建立一个链接,我们正在使用SignalR和客户端(Angular 7)注册自己来接收来自服务器(ASP)的消息。NET核心2.2)。 在浏览器控制台中,我收到以下消息: CORS策略阻止了对来自http://localhost:4200的https://ourEndpoint/坐标中心/谈判的XMLHttpRequest的访问
我目前正在尝试为客户端界面-服务器交互构建一个API。我已经决定使用ASP.NET核心作为API,Nginx作为托管平台(在Ubuntu 18.04上)。由于ASP.NET使用Kestrel,我们设置了一个反向代理,将请求从Nginx转发到Kestrel——也就是托管API的服务器。我们在NGINX服务器上设置了SSL,但是它没有在Kestrel服务器上设置。 简单地说,我不知道如何在 Kestr
0.15 新版功能. 该节文档讲述Scrapy核心API,目标用户是开发Scrapy扩展(extensions)和中间件(middlewares)的开发人员。 Crawler API Scrapy API的主要入口是 Crawler 的实例对象, 通过类方法 from_crawler 将它传递给扩展(extensions)。 该对象提供对所有Scrapy核心组件的访问, 也是扩展访问Scrapy核
谢谢,麦克斯