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

Polly v8仅针对特定状态码重试失效问题咨询

问题描述

使用Polly v8和.NET Framework 4.7.2,希望仅针对特定HTTP状态码(比如InternalServerError)执行重试,但仅用HandleResult时重试不触发。添加Handle<HttpRequestException>能生效,但会对更多状态码重试,不符合快速失败并记录日志的需求。

示例代码:

public ResiliencePipelineBuilder<HttpResponseMessage> BuildStrategy()
{
    var statusCodes = new List<HttpStatusCode>
    {
        HttpStatusCode.InternalServerError
    };

    PredicateBuilder<HttpResponseMessage> predicateBuilder = new PredicateBuilder<HttpResponseMessage>()
        // .Handle<HttpRequestException>()  NOTE: this would work see explanation
        .HandleResult(response => statusCodes.Contains(response.StatusCode));

    ...

    return new ResiliencePipelineBuilder<HttpResponseMessage>()
        .AddRetry(new RetryStrategyOptions<HttpResponseMessage>()
        {
            ShouldHandle = predicateBuilder,
            ...
        });
}

public async Task<Data> SendIt()
{
    var strategy = BuildStrategy();

    var result = strategy.ExecuteAsync(async token => 
    {
        var response = await client.SendAsync(...);

        response.EnsureSuccessStatusCode();

        ...
    });
}

请问能否单独使用v8风格的HandleResult来捕获需要的请求?是否必须回退到v7的实现方式?Polly文档中同时展示了Handle和HandleResult两种方式,但多以成对形式出现。

解决方案

完全可以单独用Polly v8的HandleResult实现仅针对特定状态码的重试,问题出在你的代码逻辑上:

你在ExecuteAsync的委托里调用了response.EnsureSuccessStatusCode(),这个方法会在响应状态码不是2xx成功码时直接抛出HttpRequestException。而你的重试策略只监听HttpResponseMessage类型的返回结果,异常抛出后委托根本不会返回结果,HandleResult的条件自然永远不会触发。

有两种调整方案:

  • 方案一:移除response.EnsureSuccessStatusCode(),直接返回响应结果
    让重试策略能检查返回的HttpResponseMessage状态码,等重试逻辑执行完后,再处理成功响应或失败后的日志与异常:
public async Task<Data> SendIt()
{
    var strategy = BuildStrategy();

    var response = await strategy.ExecuteAsync(async token => 
    {
        return await client.SendAsync(...);
    });

    // 非目标重试状态码,按正常逻辑处理
    if (!statusCodes.Contains(response.StatusCode))
    {
        response.EnsureSuccessStatusCode();
        // 解析响应数据
        return ParseResponseData(response);
    }

    // 重试后仍失败,记录日志并抛出异常
    logger.LogError("请求多次重试后失败,状态码:{StatusCode}", response.StatusCode);
    throw new HttpRequestException("请求失败", null, response.StatusCode);
}
  • 方案二:精准捕获HttpRequestException中的目标状态码
    如果不想移除EnsureSuccessStatusCode(),可以在重试策略中处理HttpRequestException,但只针对你指定的状态码触发重试:
PredicateBuilder<HttpResponseMessage> predicateBuilder = new PredicateBuilder<HttpResponseMessage>()
    .Handle<HttpRequestException>(ex => 
    {
        return ex.StatusCode.HasValue && statusCodes.Contains(ex.StatusCode.Value);
    });

这两种方式都完全基于Polly v8的API实现,不需要回退到v7版本。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 18:04:52