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

未预热时ASP.NET 6并发Web请求触发异常的排查求助

ASP.NET 6 Linux部署下并发WebRequest偶发超时问题排查与解决思路

问题背景

在Linux系统部署的ASP.NET 6服务器中,为实现并发WebRequest自定义了BarrierTask类处理并行逻辑,但出现偶发请求超时失败:首次发起大并发请求时多数抛出System.IO.IOException: The response ended prematurely.异常,预热请求后恢复正常,服务器闲置数分钟后问题复现。

关键代码片段

启动阶段ThreadPool配置

System.Net.ServicePointManager.DefaultConnectionLimit = 500;
System.Threading.ThreadPool.SetMinThreads(1000, 500);

并行WebRequests执行代码

BarrierTask<int, TestDto> barrierTask = new BarrierTask<int, TestDto>();
int[] arr = new int[count];
for (int i = 0; i < arr.Length; i++)
{
 arr[i] = i;
}
TestDto[] results = barrierTask.Run((a) =>
{
 var id = new TestDto()
 {
     TimestampStart = DateTime.UtcNow,
     TimestampEnd = new DateTime(),
     Delay = delay,
     Name = $"Test request {a}",
     Error = "OK"
 };
 string str = Newtonsoft.Json.JsonConvert.SerializeObject(id);
 try
 {
     string json = DoRequest("https://.../apidebug/delay", str);
     var ret = Newtonsoft.Json.JsonConvert.DeserializeObject<TestDto>(json);
     return ret;
 }
 catch (Exception ex)
 {
     id.Error = ex.ToString().Replace("\r","\\r").Replace("\n","\\n");
     id.TimestampEnd = DateTime.UtcNow;
     return id;
 }
}
, arr);
 
 
string DoRequest(string uri, string body)
{
    using var client = new HttpClient();
    using (var webRequest = new HttpRequestMessage(HttpMethod.Post, uri)
    {
        Content = new StringContent(body, Encoding.UTF8, "application/json"),
    })
    {
        using (var response = client.Send(webRequest))
        {
            using (var reader = new StreamReader(response.Content.ReadAsStream()))
            {
                return reader.ReadToEnd();
            }
        }
    }
}

BarrierTask实现代码

public class BarrierTask<TArgs,TResult>
{

 Barrier barrier;

 public TResult[] Run(Func<TArgs, TResult> action, TArgs[] args)
 {
     List<TResult> ret = new List<TResult>();
     barrier = new Barrier(args.Length + 1);
     foreach (TArgs arg in args)
     {
         Task.Run(() =>
         {
             try
             {
                 TResult result = action(arg);
                 lock (this)
                 {
                     ret.Add(result);
                 }
             }
             catch (Exception ex)
             {
                 AppLog.Log("BarrierTask.Run: Input: " + arg.ToString() + " Ex: " + ex.Message, AppLog.MessageType.Error);
             }
             finally
             {
                 barrier.SignalAndWait();
             }
         });
     }
     barrier.SignalAndWait();
     return ret.ToArray();
 }
}

目标端点代码

[Route("api/delay")]
[ApiController]
public class DelayController : ControllerBase
{
    [HttpPost]
    public TestDto Post(TestDto testDto)
    {
        System.Threading.Thread.Sleep(testDto.Delay);
        testDto.TimestampEnd = DateTime.UtcNow;
        return testDto;
    }
}

测试场景

  • 服务器启动后直接发起100个延迟4000ms的并发请求:部分成功,多数抛出System.IO.IOException: The response ended prematurely.异常,推测为Apache超时终止连接;二次请求正常。
  • 先发起预热请求再执行100个并发请求:全部正常。
  • 闲置数分钟后:需再次预热,否则部分请求仍异常。

解决思路

  1. 复用HttpClient实例:当前DoRequest方法每次创建新HttpClient,会导致频繁创建/释放TCP连接,Linux下TIME_WAIT状态的连接会占用资源,首次大并发时连接池未建立易触发超时。改用单例HttpClient或依赖注入IHttpClientFactory管理实例,复用HTTP连接池。

  2. 调整Apache超时配置:若确认是Apache侧主动断开连接,检查并调整Timeout、ProxyTimeout参数,延长至覆盖请求延迟+网络耗时(比如设置为10s以上);同时优化KeepAliveTimeout和MaxKeepAliveRequests参数,提升长连接复用效率。

  3. 优化并行逻辑:

    • 替换Task.Run无限制创建任务的方式,改用Parallel.ForEach并指定最大并行度(如new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount * 2 }),避免线程池过载。
    • 用ConcurrentBag<TResult>替代List<TResult>加锁添加元素,减少锁竞争开销。
    • 确保Barrier的Signal逻辑在所有分支都能执行,避免主线程无限等待。
  4. 优化TCP与HTTP参数:

    • 设置ServicePointManager.Expect100Continue = false,减少HTTP握手阶段的开销。
    • 调整Linux系统TCP参数:开启net.ipv4.tcp_tw_reuse = 1允许复用TIME_WAIT状态连接,缩短net.ipv4.tcp_fin_timeout时间,缓解连接资源不足问题。
  5. 添加自动预热逻辑:在服务器启动后自动发起少量预热请求,提前初始化线程池并建立HTTP连接池,避免首次大并发请求时的资源初始化延迟。可在Program.cs中添加启动后执行的异步预热任务。

内容的提问来源于stack exchange,提问作者Jaromír Konečný

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 01:18:10