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

HttpClient请求间隔超80秒后执行耗时变长原因排查

问题现象
  • 两次HTTP请求间隔小于80秒时,单次请求执行耗时稳定在400-700ms区间
  • 两次HTTP请求间隔超过80秒时,请求执行耗时升至1000-1500ms,耗时水平与首次发起请求基本一致
  • 该问题会导致连续80秒以上无用户访问的Telegram机器人,收到新请求时响应延迟明显升高
复现代码
using System.Diagnostics;

var httpClient = new HttpClient();
var watch = new Stopwatch();

watch.Start();
var data1 = await httpClient.GetAsync("https://google.com");
watch.Stop();
Console.WriteLine($"{data1.StatusCode} {watch.ElapsedMilliseconds}");
watch.Reset();

Thread.Sleep(10000);

watch.Start();
var data2 = await httpClient.GetAsync("https://google.com");
watch.Stop();
Console.WriteLine($"{data2.StatusCode} {watch.ElapsedMilliseconds}");
测试结果
  • 代码中Thread.Sleep参数设为10000(请求间隔10秒)时,控制台输出:OK 1319 | OK 457
  • 代码中Thread.Sleep参数设为85000(请求间隔85秒)时,控制台输出:OK 1399 | OK 1183
产生原因

该现象是HTTP长连接复用机制与空闲连接超时回收规则共同作用的结果:

  • 首次发起HTTP请求时,客户端需要完成完整的TCP三次握手、TLS握手流程,这部分固定网络交互开销占总耗时的60%以上,因此首次请求耗时普遍在1000ms以上。
  • 请求完成后,已建立的TCP连接不会被立即释放,会存入HttpClient连接池保持空闲状态;后续短时间内发起同域名请求时,可直接复用池内现成连接,省去握手环节开销,因此请求耗时降至400-700ms区间。
  • 客户端运行时、服务端网关、中间链路网络设备均配置了空闲连接回收规则:当TCP连接连续空闲超过阈值(当前场景下阈值约为80秒),连接会被主动断开回收。
    • 请求间隔小于80秒时,池内连接仍处于可用状态,可直接复用,耗时较低
    • 请求间隔超过80秒时,原有空闲连接已被回收,发起请求时需要重新完成完整的TCP+TLS握手建立新连接,耗时回到首次请求水平
优化方案

可根据项目使用的.NET版本选择对应方案解决:

  • 启用HTTP KeepAlive探活(.NET 5及以上版本支持):通过SocketsHttpHandler配置连接空闲时自动发送探活包,避免连接被链路节点或服务端判定为空闲回收,配置示例:
var handler = new SocketsHttpHandler
{
    KeepAlivePingPolicy = HttpKeepAlivePingPolicy.Always,
    KeepAlivePingDelay = TimeSpan.FromSeconds(60),
    KeepAlivePingTimeout = TimeSpan.FromSeconds(10)
};
var httpClient = new HttpClient(handler);
  • 定时预热连接:低版本.NET可在后台运行定时任务,每隔70秒向目标API发送一个轻量请求,保持连接池内的长连接持续活跃,避免被回收。

内容的提问来源于stack exchange,提问作者Роман

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 13:24:21