You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Polly构建弹性策略时AsyncCircuitBreaker转Policy类型错误如何解决

问题根源
  • 类型不匹配:Polly的策略分为同步Policy/ISyncPolicy和异步IAsyncPolicy两大分支,异步方法返回的异步策略不能赋值给同步基类Policy。同时你的重试策略是带返回值的泛型IAsyncPolicy<HttpResponseMessage>,最初声明的熔断策略是无返回值的非泛型IAsyncPolicy,两种泛型参数不同的策略无法直接组合。
  • 策略处理条件不对齐:熔断策略仅处理TimeoutException,没有覆盖重试策略处理的HttpRequestException和500状态码响应,会导致部分异常不会触发熔断逻辑。
  • 策略组合顺序错误:WrapAsync的规则是外层策略调用该方法传入内层策略,常规弹性链路的执行顺序应为超时→重试→熔断,顺序错误会导致熔断逻辑不生效。
修复方案

1. 调整熔断策略声明

对齐重试策略的处理条件,声明为同类型的泛型异步策略:

var circuitBreakerPolicy = Policy
    .Handle<TimeoutException>()
    .Or<HttpRequestException>()
    .OrResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.InternalServerError)
    .CircuitBreakerAsync(3, TimeSpan.FromSeconds(2));

2. 修正策略组合逻辑与类型声明

全局静态策略不要用Policy类型,改为对应的异步泛型类型IAsyncPolicy<HttpResponseMessage>,同时调整Wrap顺序:

// 全局静态组合策略声明
public static IAsyncPolicy<HttpResponseMessage> ResilientAsyncStrategy;

public static IAsyncPolicy<HttpResponseMessage> CreateResiliencePolicy()
{
    // 超时策略也要对齐泛型类型
    var timeoutPolicy = Policy.TimeoutAsync<HttpResponseMessage>(TimeSpan.FromSeconds(180));

    var circuitBreakerPolicy = Policy
        .Handle<TimeoutException>()
        .Or<HttpRequestException>()
        .OrResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.InternalServerError)
        .CircuitBreakerAsync(3, TimeSpan.FromSeconds(2));

    var waitAndRetryPolicy = Polly.Policy
        .Handle<HttpRequestException>()
        .Or<TimeoutException>()
        .OrResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.InternalServerError)
        .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(3, retryAttempt)),
        (result, timeSpan, context) =>
        {
        });
    
    // 组合顺序:超时(最外层)→ 重试 → 熔断(最内层)
    ResilientAsyncStrategy = timeoutPolicy.WrapAsync(waitAndRetryPolicy).WrapAsync(circuitBreakerPolicy);
    return ResilientAsyncStrategy;
}

3. 调整调用逻辑

策略执行返回的是HttpResponseMessage,需要补充反序列化为DTO的逻辑:

public async Task<IEnumerable<PaymentDetailDto>> GetAsync()
{
    var response = await ResilientAsyncStrategy.ExecuteAsync(async () => await client.GetAsync());
    response.EnsureSuccessStatusCode();
    return await response.Content.ReadFromJsonAsync<IEnumerable<PaymentDetailDto>>();
}

内容的提问来源于stack exchange,提问作者Golide

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.12 21:30:03