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

从Web应用调用外部API时,如何处理各类HttpRequestException异常?

解决.NET HttpClient调用外部API时的连接超时(10060)与连接拒绝(10061)异常

一、先做基础网络排查

  • 验证目标API可用性:在部署应用的服务器上,用curl或Postman持续测试目标URL,确认是否是对方服务间歇性故障、网络链路抖动导致的问题。
  • 检查网络权限:
    • 确认服务器防火墙/安全组允许出站访问目标API的端口(比如HTTPS的443)。
    • 核实目标API服务器是否将当前应用服务器的IP加入白名单,10061错误常因IP被拒绝访问导致。

二、优化HttpClient配置

1. 细粒度超时与连接池配置

默认的Timeout是全局超时,可通过SocketsHttpHandler拆分连接超时、读取超时,同时优化连接池避免复用失效连接:

services.AddHttpClient("LoginClient", client =>
{
    client.BaseAddress = new Uri(settings.LoginUrl);
    client.DefaultRequestHeaders.Add("Accept", "application/json");
    client.Timeout = TimeSpan.FromSeconds(settings.APITimeoutInSeconds); // 全局请求超时
}).ConfigurePrimaryHttpMessageHandler(() => new SocketsHttpHandler
{
    ConnectTimeout = TimeSpan.FromSeconds(10), // 单独设置连接阶段超时
    PooledConnectionLifetime = TimeSpan.FromMinutes(5), // 定期更换连接池中的连接,避免DNS缓存过期
    PooledConnectionIdleTimeout = TimeSpan.FromMinutes(2), // 空闲连接超时回收
    MaxConnectionsPerServer = 100 // 根据并发量调整,避免连接耗尽
});

2. 移除不必要的using包裹

HttpClientFactory创建的HttpClient无需手动Dispose,Factory会管理底层Handler的生命周期。滥用using会破坏连接池复用,反而引发连接问题:

// 正确写法:不要用using包裹HttpClient
var client = _httpClientFactory.CreateClient("LoginClient");
var response = await client.PostAsync(requestUri, content);
try
{
    if (response.IsSuccessStatusCode)
    {
        var responseContent = await response.Content.ReadAsStringAsync();
        res = JsonConvert.DeserializeObject<TokenResponseModel>(responseContent);
    }
    else
    {
        apiLog.Response = response;
    }
}
finally
{
    await response.Content.DisposeAsync(); // 仅释放响应内容
}

三、添加重试机制应对临时故障

针对偶尔的网络波动或服务不可用,用Polly库实现指数退避重试(仅适合幂等请求,POST请求需确认接口支持重试):

  1. 先安装NuGet包:Microsoft.Extensions.Http.Polly、Polly
  2. 配置重试策略:
services.AddHttpClient("LoginClient", client =>
{
    // 原有客户端配置
}).AddPolicyHandler(Policy
    .Handle<HttpRequestException>()
    .Or<SocketException>(ex => ex.ErrorCode is 10060 or 10061) // 针对目标异常重试
    .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))) // 指数退避:2s、4s、8s后重试
);

四、增强日志与监控

  • 记录详细异常信息:捕获异常时记录Socket错误码、请求时间、目标URL,方便定位问题根源:
try
{
    var client = _httpClientFactory.CreateClient("LoginClient");
    var response = await client.PostAsync(requestUri, content);
    // 原有业务逻辑
}
catch (HttpRequestException ex) when (ex.InnerException is SocketException socketEx)
{
    apiLog.ExceptionMessage = ex.Message;
    apiLog.SocketErrorCode = socketEx.ErrorCode;
    apiLog.TargetUrl = settings.LoginUrl + requestUri;
    apiLog.RequestTime = DateTime.UtcNow;
    // 写入日志系统
}
  • 监控API可用性:用Application Insights或Prometheus+Grafana监控请求成功率、响应时间,及时发现对方服务的异常波动。

五、解决DNS缓存过期问题

如果目标API的IP地址会变更,可缩短DNS缓存刷新时间:

new SocketsHttpHandler
{
    DnsRefreshTimeout = TimeSpan.FromMinutes(1), // 每分钟刷新DNS缓存
    // 其他配置
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 06:15:00