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

.NET 6中HttpMessageInvoker连接超时未生效问题求助

问题描述

使用SocketsHttpHandler初始化HttpMessageInvoker,已将ConnectTimeout、KeepAlivePingTimeout、PooledConnectionIdleTimeout均设置为120秒,同时传入120秒超时的CancellationToken,调用SendAsync代码如下:

destinationResponse = await httpClient.SendAsync(destinationRequest, requestTimeoutToken);

HttpMessageInvoker创建代码:

var handler = new SocketsHttpHandler
{
    UseProxy = false,
    AllowAutoRedirect = false,
    AutomaticDecompression = DecompressionMethods.None,
    UseCookies = false, 
    EnableMultipleHttp2Connections = true, 
    MaxConnectionsPerServer = 5000, 
};

handler.ConnectTimeout = TimeSpan.FromSeconds(120);
handler.KeepAlivePingTimeout = TimeSpan.FromSeconds(120);
handler.PooledConnectionIdleTimeout = TimeSpan.FromSeconds(120);

return new HttpMessageInvoker(new ActivityPropagationHandler(handler), disposeHandler: true);

但访问不可达URL时,总是在21.2秒左右触发超时,而非预期的120秒。运行环境为Windows 11/Windows Server 2022,使用.NET 6.0版本。

解决方案

问题原因

21秒左右的超时是Windows系统TCP栈的默认重传总时长。Windows TCP默认会对未建立的连接进行多次重传,总耗时约21秒,这个行为会覆盖SocketsHttpHandler设置的ConnectTimeout,导致应用层超时设置不生效。

解决办法

方法一:修改系统TCP参数(需管理员权限)

通过调整注册表中的TCP配置,让系统尊重应用层的超时设置:

  1. 打开注册表编辑器,定位到路径:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
  2. 添加或修改以下DWORD值:
    • TcpInitialRtt:设置为120000(单位:毫秒,对应120秒),调整初始往返时间阈值
    • TcpMaxRetransmissions:设置为0,禁用TCP栈的自动重传逻辑
  3. 重启系统使配置生效

方法二:自定义连接回调(代码层面解决)

通过重写SocketsHttpHandler的ConnectCallback属性,手动控制Socket连接超时,绕过系统TCP的默认重传:

var handler = new SocketsHttpHandler
{
    UseProxy = false,
    AllowAutoRedirect = false,
    AutomaticDecompression = DecompressionMethods.None,
    UseCookies = false,
    EnableMultipleHttp2Connections = true,
    MaxConnectionsPerServer = 5000,
    // 自定义连接回调,手动控制超时
    ConnectCallback = async (context, cancellationToken) =>
    {
        using var socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
        socket.NoDelay = true;
        try
        {
            // 关联传入的取消令牌并设置120秒超时
            using var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
            cts.CancelAfter(TimeSpan.FromSeconds(120));
            await socket.ConnectAsync(context.DnsEndPoint, cts.Token);
            // 返回NetworkStream,让HttpHandler使用该连接
            return new NetworkStream(socket, ownsSocket: true);
        }
        catch
        {
            socket.Dispose();
            throw;
        }
    }
};

handler.KeepAlivePingTimeout = TimeSpan.FromSeconds(120);
handler.PooledConnectionIdleTimeout = TimeSpan.FromSeconds(120);

return new HttpMessageInvoker(new ActivityPropagationHandler(handler), disposeHandler: true);

这种方式无需修改系统配置,直接在代码中控制连接超时逻辑,确保120秒超时生效。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 06:25:30