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

.NET 6 Web API中GetHttpClient()调用抛出SocketException问题排查

问题:.NET 6中复用HttpClient发起请求抛出连接被强制关闭异常

我在.NET 6开发Web API时,定义了抽象类AdminApiClient继承自ApiClientBase,代码如下:

public abstract class AdminApiClient : ApiClientBase
{
    protected static HttpClient? client;

    public AdminApiClient()
    {
        client = client ?? new HttpClient
        {
            BaseAddress = new Uri("http://localhost:44355/")
        };
    }

    protected override HttpClient GetHttpClient()
    {
        return client;
    }
}

ApiClientBase类代码如下:调用Test方法时,方法内新建的HttpClient发起请求正常,但通过GetHttpClient()获取的复用HttpClient发起请求会抛出异常:

public abstract class ApiClientBase
{
    protected abstract HttpClient GetHttpClient();

    protected async Task<TResult> Test<TResult>()
    {
        var apiName = "api/users/GetTest";

        var httpClient = new HttpClient();

        httpClient.BaseAddress = new Uri("https://localhost:44355/");

        // 运行正常
        var response1 = await httpClient.GetAsync(apiName);

        // 抛出异常
        var response2 = await GetHttpClient().GetAsync(apiName);
    }
}

我困惑的是这段代码能正常运行:

var response1 = await httpClient.GetAsync(apiName);

但这段代码会抛出异常:

var response2 = await GetHttpClient().GetAsync(apiName);

异常信息:

System.Net.Http.HttpRequestException: 发送请求时出错。
---> System.IO.IOException: 无法从传输连接读取数据: 远程主机强迫关闭了一个现有的连接。
---> System.Net.Sockets.SocketException (10054): 远程主机强迫关闭了一个现有的连接。
--- 内部异常堆栈跟踪结束 ---
在 System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)
在 System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource<System.Int32>.GetResult(Int16 token)
在 System.Net.Http.HttpConnection.InitialFillAsync(Boolean async)
在 System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
--- 内部异常堆栈跟踪结束 ---
在 System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
在 System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
在 System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
在 System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
在 System.Net.Http.HttpClient.g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
在 Web.Core.ApiClientBase.Test() in C:\Web.Core\ApiClientBase.cs:line 76


原因分析

  1. BaseAddress协议不匹配:复用的HttpClient使用的是http://localhost:44355/,而测试方法里新建的HttpClient用的是https://localhost:44355/。如果API服务仅监听HTTPS端口,HTTP请求会被直接拒绝,进而导致连接被强制关闭。
  2. 静态HttpClient的潜在问题:静态HttpClient实例长期存活,可能出现DNS缓存过期、连接池失效等问题,但本次异常的核心诱因是协议不匹配。

解决方案

  1. 统一BaseAddress协议:将AdminApiClient中的BaseAddress修改为HTTPS,与测试代码保持一致:
client = client ?? new HttpClient
{
    BaseAddress = new Uri("https://localhost:44355/")
};
  1. 使用官方推荐的IHttpClientFactory管理实例:.NET官方推荐通过IHttpClientFactory来管理HttpClient生命周期,既能避免静态实例的各种潜在问题,又能自动维护连接池、处理DNS更新:
    • 在Program.cs中注册服务:
      builder.Services.AddHttpClient<IAdminApiClient, AdminApiClient>(client =>
      {
          client.BaseAddress = new Uri("https://localhost:44355/");
      });
      
    • 修改AdminApiClient通过构造注入获取HttpClient:
      public abstract class AdminApiClient : ApiClientBase
      {
          private readonly HttpClient _client;
      
          public AdminApiClient(HttpClient client)
          {
              _client = client;
          }
      
          protected override HttpClient GetHttpClient()
          {
              return _client;
          }
      }
      

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 16:15:37