首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Polly HandleTransientHttpError没有捕捉到HttpRequestException

Polly HandleTransientHttpError没有捕捉到HttpRequestException
EN

Stack Overflow用户
提问于 2021-10-27 22:20:46
回答 1查看 2.5K关注 0票数 3

我在HttpClient方法中为我的Startup.ConfigureServices创建了一个重试策略。还请注意,默认情况下,asp.net Core2.1为HttpClient发出的每个调用记录4行信息行,这些信息行显示在我问题末尾的日志中。

代码语言:javascript
运行
AI代码解释
复制
services.AddHttpClient("ResilientClient")
            .AddPolicyHandler(
                Policy.WrapAsync(
                    PollyRetryPolicies.TransientErrorRetryPolicy(),
                    Policy.TimeoutAsync<HttpResponseMessage>(TimeSpan.FromSeconds(60))));

策略定义如下。请注意,我将重试尝试写入日志,因此我将知道是否调用了重试策略。

代码语言:javascript
运行
AI代码解释
复制
public static IAsyncPolicy < HttpResponseMessage > TransientErrorRetryPolicy() {
    return HttpPolicyExtensions
        .HandleTransientHttpError()
        .Or < TimeoutRejectedException > ()
        .WaitAndRetryAsync(sleepDurations: ExponentialBackoffPolicy.DecorrelatedJitter(3, SEED_DELAY, MAX_DELAY),
            onRetry: (message, timespan, attempt, context) => {
                context.GetLogger() ? .LogInformation($ "Retrying request to {message?.Result?.RequestMessage?.RequestUri} in {timespan.TotalSeconds} seconds. Retry attempt {attempt}.");
    });
}

HandleTransientHttpError()是一个Polly扩展,它在注释中声明:

配置为处理的条件是:·网络故障(如System.Net.Http.HttpRequestException)

我的httpclient用法如下:

代码语言:javascript
运行
AI代码解释
复制
using (HttpResponseMessage response = await _httpClient.SendAsync(request)) 
{
    response.EnsureSuccessStatusCode();

    try 
    {
        string result = await response.Content.ReadAsStringAsync();
        if (result == null || result.Trim().Length == 0) {
            result = "[]";
        }
        return JArray.Parse(result);
    } catch (Exception ex) {
        _logger.LogInformation($ "Failed to read response from {url}. {ex.GetType()}:{ex.Message}");
        throw new ActivityException($ "Failed to read response from {url}.", ex);
    }
}

捕获了以下日志:

代码语言:javascript
运行
AI代码解释
复制
[Information] System.Net.Http.HttpClient.ResilientClient.LogicalHandler: Start processing HTTP request GET https://api.au.... obfuscated
[Information] System.Net.Http.HttpClient.ResilientClient.CustomClientHandler: Sending HTTP request GET https://api.au..... obfuscated
[Information] System.Net.Http.HttpClient.ResilientClient.CustomClientHandler: Received HTTP response after 2421.8895ms - 200
[Information] System.Net.Http.HttpClient.ResilientClient.LogicalHandler: End processing HTTP request after 2422.1636ms - OK
    
Unknown error responding to request: HttpRequestException:
System.Net.Http.HttpRequestException: Error while copying content to a stream. ---> System.IO.IOException: The server returned an invalid or unrecognized response.

at System.Net.Http.HttpConnection.FillAsync()
at System.Net.Http.HttpConnection.ChunkedEncodingReadStream.CopyToAsyncCore(Stream destination, CancellationToken cancellationToken)
at System.Net.Http.HttpConnection.HttpConnectionResponseContent.SerializeToStreamAsync(Stream stream, TransportContext context, CancellationToken cancellationToken)
at System.Net.Http.HttpContent.LoadIntoBufferAsyncCore(Task serializeToStreamTask, MemoryStream tempBuffer)
--- End of inner exception stack trace ---
at System.Net.Http.HttpContent.LoadIntoBufferAsyncCore(Task serializeToStreamTask, MemoryStream tempBuffer)
at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
at nd_activity_service.Controllers.ActivityController.GetND(String url) in /codebuild/output/src251819872/src/src/nd-activity-service/Controllers/ActivityController.cs:line 561

Http调用成功,我可以看到它返回200-OK。但随后抛出了HttpRequestException。我假设没有调用策略,因为HttpClient消息管道已经解析,因为我们可以看到它返回200-OK。那么,它是如何抛出异常的呢?

我该怎么处理呢?围绕专门处理HttpRequestExceptions的方法包装另一个策略?

这个错误似乎是暂时的。这是一个计划好的作业,下次调用时可以工作。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-10-27 23:41:26

您的策略是针对HttpClient而不是针对HttpResponseMessage定义的。

因此,即使您收到例如428,response.EnsureSuccessStatusCode()也将而不是触发器重试。

如果从下游系统接收到408或5XX状态代码,则HandleTransientHttpError将触发重试。当SendAsync抛出HttpRequestException

因为您的异常StackTrace如下所示:

System.Net.Http.HttpRequestException:将内容复制到流中时出错。 System.IO.IOException:服务器返回无效或无法识别的响应。

这就是为什么我的猜测是,这个异常是由HttpContent类抛出的,而您试图读取响应体(ReadAsStringAsync)。

这将不会触发重试,因为您已经在HttpClient上定义了策略。

如果您想在这些情况下进行重试,那么当response.EnsureSuccessStatusCode()抛出HRE或response.Content.ReadAsStringAsync()抛出HRE时,您必须将整个http通信和响应处理逻辑封装到重试策略中。

我来教你怎么做。

首先使用PolicyRegistry而不是AddPolicyHandler

代码语言:javascript
运行
AI代码解释
复制
//services.AddHttpClient("ResilientClient")
//    .AddPolicyHandler(
//        Policy.WrapAsync(
//            TransientErrorRetryPolicy(),
//            Policy.TimeoutAsync<HttpResponseMessage>(TimeSpan.FromSeconds(60))));

services.AddHttpClient("ResilientClient");
var registry = services.AddPolicyRegistry();
registry.Add("retry", Policy.WrapAsync(
            TransientErrorRetryPolicy(),
            Policy.TimeoutAsync<HttpResponseMessage>(TimeSpan.FromSeconds(60))));

然后向DI请求注册,例如:

代码语言:javascript
运行
AI代码解释
复制
private readonly IHttpClientFactory factory;
private readonly IReadOnlyPolicyRegistry<string> registry;

public TestController(IHttpClientFactory factory, IReadOnlyPolicyRegistry<string> registry)
{
    this.factory = factory;
    this.registry = registry;
}

最后,检索组合策略并执行http调用:

代码语言:javascript
运行
AI代码解释
复制
var retryPolicy = registry.Get<IAsyncPolicy<HttpResponseMessage>>("retry");
await retryPolicy.ExecuteAsync(async () => await IssueRequest());
代码语言:javascript
运行
AI代码解释
复制
private async Task<HttpResponseMessage> IssueRequest()
{
    var _httpClient = factory.CreateClient("ResilientClient");
    HttpResponseMessage response = await _httpClient.GetAsync("http://httpstat.us/428");

    response.EnsureSuccessStatusCode();
    return response;
}

我使用httpstat.us来模拟428个响应。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69749167

复制
相关文章
.NET Core 3.0深入源码理解HttpClientFactory之实战
前面两篇文章透过源码角度,理解了HttpClientFactory的内部实现,当我们在项目中使用时,总会涉及以下几个问题:
AI.NET 极客圈
2019/08/06
1.3K0
ASP.NET Core 6框架揭秘实例演示[17]:利用IHttpClientFactory工厂来创建HttpClient
在一个采用依赖注入框架的应用中,我们一般不太推荐利用手工创建的HttpClient对象来进行HTTP调用,使用的HttpClient对象最好利用注入的IHttpClientFactory工厂来创建。前者引起的问题,以及后者带来的好处,将通过如下这几个演示程序展现出来。IHttpClientFactory类型由“Microsoft.Extensions.Http”这个NuGet包提供,“Microsoft.NET.Sdk.Web”SDK具有该包的默认引用。如果采用“Microsoft.NET.Sdk”这个SDK,需要添加该包的引用。(本篇提供的实例已经汇总到《ASP.NET Core 6框架揭秘-实例演示版》)
蒋金楠
2022/05/09
8620
ASP.NET Core 6框架揭秘实例演示[17]:利用IHttpClientFactory工厂来创建HttpClient
.Net Core with 微服务 - Polly 服务降级熔断
在我们实施微服务之后,服务间的调用变的异常频繁。多个服务之间可能是互相依赖的关系。某个服务出现故障或者是服务间的网络出现故障都会造成服务调用的失败,进而影响到某个业务服务处理失败。某一个服务调用失败轻则造成当前相关业务无法处理;重则可能耗尽资源而拉垮整个应用。为了尽可能的保证我们生产环境的可用性,至少是部分可用性我们就需要一些策略来保护我们的服务。
MJ.Zhou
2021/07/28
7030
API网关Ocelot 使用Polly 处理部分失败问题
在实现API Gateway过程中,另外一个需要考虑的问题就是部分失败。这个问题发生在分布式系统中当一个服务调用另外一个服务超时或者不可用的情况。API Gateway不应该被阻断并处于无限期等待下游服务的状态。但是,如何处理这种失败依赖于特定的场景和具体服务。如果是产品信息服务无响应,那么API Gateway就应该给客户端返回一个错误。 Ocelot 是一个使用.NET Core平台上的一个API Gateway,最近我在参与这个项目的开发,开发完成第一个就是使用Polly 处理部分失败问题。各位同学可
张善友
2018/01/22
1.3K0
ASP VNext 开源服务容错处理库Polly使用文档
在进入SOA之后,我们的代码从本地方法调用变成了跨机器的通信。任何一个新技术的引入都会为我们解决特定的问题,都会带来一些新的问题。比如网络故障、依赖服务崩溃、超时、服务器内存与CPU等其它问题。正是因为这些问题无法避免,所以我们在进行系统设计、特别是进行分布式系统设计的时候以“Design For Failure”(为失败而设计)为指导原则。把一些边缘场景以及服务之间的调用发生的异常和超时当成一定会发生的情况来预先进行处理。 Design For Failure 1. 一个依赖服务的故障不会严重破坏用户
用户1153966
2018/04/11
1.5K0
fatal: HttpRequestException encountered.
更新Windows的git凭证管理器 下载安装 GCMW-1.14.0.exe 地址在这里 https://github.com/Microsoft/Git-Credential-Manager-for-Windows/releases/tag/v1.14.0 拉到最下面点画圈圈的地方下载
longzeqiu
2019/08/20
1.1K0
fatal: HttpRequestException encountered.
Fatal: HttpRequestException encountered.
在使用git push时报出如下的错误: Fatal: HttpRequestException encountered. Username for ‘https://github.com‘: Password for ‘https://github.com‘: 之前时不需要输入的,现在需要输入了,原因是git更新了一个证书,我们本地需要再更新以下: https://github.com/Microsoft/Git-Credential-Manager-for-Windows/releases/tag
IT云清
2019/01/22
1.3K0
.NET 平台Http消息处理者工厂
Microsoft.Extensions.Http是一个设计非常优异的客户端工厂库,其提供了IHttpClientFactory用于创建HttpClient和IHttpMessageHandlerFactory用于创建HttpMessageHandler。
郑子铭
2023/08/30
2410
.NET 平台Http消息处理者工厂
asp.net core 使用HttpClientFactory Polly实现熔断降级
在NET Core2.1后也是增加更新了很多东西,当然HttpClientFactory更新中的一部分.虽然说HttpClient这个实现了disposable,但使用它的时候用using包装块的方式通常不是最好的选择。处理HttpClient,底层socket套接字不会立即释放。该HttpClient类是未多个请求重复使用而创建的。需要不同的基地址,不同的HTTP 标头和其他对请求个性化操作的场景时,需要动手管理多个HttpClient实例,为了简化HttpClient实例管理,.NET Core 2.1提供了一个新的HTTPClientFactory - 它可以创建,缓存和处理HttpClient实例。
HueiFeng
2020/02/12
8540
asp.net core 使用HttpClientFactory Polly实现熔断降级
ASP.NET Core 使用HttpClientFactory Polly实现熔断降级
在NET Core2.1后也是增加更新了很多东西,当然HttpClientFactory更新中的一部分.虽然说HttpClient这个实现了disposable,但使用它的时候用using包装块的方式通常不是最好的选择。处理HttpClient,底层socket套接字不会立即释放。该HttpClient类是未多个请求重复使用而创建的。需要不同的基地址,不同的HTTP 标头和其他对请求个性化操作的场景时,需要动手管理多个HttpClient实例,为了简化HttpClient实例管理,.NET Core 2.1提供了一个新的HTTPClientFactory - 它可以创建,缓存和处理HttpClient实例。
HueiFeng
2020/03/13
1.1K0
ASP.NET Core 使用HttpClientFactory Polly实现熔断降级
asp.net core 使用HttpClientFactory Polly实现熔断降级
在NET Core2.1后也是增加更新了很多东西,当然HttpClientFactory更新中的一部分.虽然说HttpClient这个实现了disposable,但使用它的时候用using包装块的方式通常不是最好的选择。
梁规晓
2019/09/24
9270
asp.net core 使用HttpClientFactory Polly实现熔断降级
git报错-fatal: HttpRequestException encountered.
点击下载安装 GCMW-1.14.0.exe 下载链接 https://github.com/Microsoft/Git-Credential-Manager-for-Windows/releases/tag/v1.14.0
王小婷
2019/05/14
1.9K0
.NET 基金会项目介绍-Polly
如今的云应用程序、移动设备、流数据处理和 IoT 技术等等都非常依赖于可靠的系统连通性。不过现实是:基础系统可能出现操作失败,网络波动时有发生:或中断、或延时、或瞬时波动、或峰值负载 —— 这些都对100%的系统连通性造成挑战。
newbe36524
2020/03/16
6150
AI+云计算,捕捉到了“宇宙闪烁”!
在2023世界人工智能大会上,我们宣布首次用AI,帮助世界最大的射电天文望远镜“中国天眼FAST”,找到了2颗快速射电暴!
腾讯云TI平台
2023/07/25
3810
AI+云计算,捕捉到了“宇宙闪烁”!
聊聊Asp.net Core中如何做服务的熔断与降级
而对于微服务来说,熔断就是我们常说的“保险丝”,意为当服务出现某些状况时,切断服务,从而防止应用程序不断地尝试执行可能会失败的操作造成系统的“雪崩”;或者大量的超时等待导致系统卡死等情况,很多地方也将其成为“过载保护”。
乔达摩@嘿
2023/07/21
3870
聊聊Asp.net Core中如何做服务的熔断与降级
.NET 5 中使用 Consul+Ocelot+Polly缓存、限流、熔断、降级
链接:cnblogs.com/wei325/archive/2021/09/27/15308498.html
郑子铭
2021/11/10
1.8K0
.NET 5 中使用 Consul+Ocelot+Polly缓存、限流、熔断、降级
Java运行时异常try-catch块能捕捉到吗
还记得2年前见过这个问题,当时没太在意,这次写demo复现了这个问题。Java运行时异常能捕捉吗?
砖业洋__
2023/05/06
5550
Java运行时异常try-catch块能捕捉到吗
没有Axe!没有Billions!
量化投资与机器学习微信公众号,是业内垂直于量化投资、对冲基金、Fintech、人工智能、大数据等领域的主流自媒体。公众号拥有来自公募、私募、券商、期货、银行、保险、高校等行业30W+关注者,荣获2021年度AMMA优秀品牌力、优秀洞察力大奖,连续2年被腾讯云+社区评选为“年度最佳作者”。 是时候了! 2022年伊始,公众号开始着手准备关于Billions的回顾与往期精彩内容。 如今随着Billions第六季进入尾声。QIML将与大家分享这几年对Billions的记录点点滴滴。 第五季最后一级: 从Bac
量化投资与机器学习微信公众号
2022/04/14
1.8K0
没有Axe!没有Billions!
.NET Core微服务之基于Polly+AspectCore实现熔断与降级机制
  在广义的解释中,熔断主要是指为控制股票、期货或其他金融衍生产品的交易风险,为其单日价格波动幅度规定区间限制,一旦成交价触及区间上下限,交易则自动中断一段时间(“熔即断”),或就此“躺平”而不得超过上限或下限(“熔而不断”)。
Edison Zhou
2018/08/07
2K0
.NET Core微服务之基于Polly+AspectCore实现熔断与降级机制
发送Http请求
这是第一部分, 主要使用的是AngleSharp: https://anglesharp.github.io/
solenovex
2022/11/24
4.3K0
发送Http请求

相似问题

Polly重试并不总是捕获HttpRequestException

18

HttpClient HttpRequestException

13

@catch没有捕捉到

11

InputMismatchException没有捕捉到

23

jQuery没有捕捉到事件

10
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
💥开发者 MCP广场重磅上线!
精选全网热门MCP server,让你的AI更好用 🚀
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档