.NET HttpClient并行多请求耗时过长(仅HTTP 1.0无此问题)
解决.NET HttpClient请求排队60秒的问题
嘿,这个问题我之前也踩过坑!前几次请求飞快,后面的突然集体卡60秒才批量完成,大概率是这几个原因,给你逐个拆解解决:
1. 未释放响应导致连接池耗尽
这是最容易忽略的坑!如果你发起请求后,只是拿到了HttpResponseMessage,但没有读取响应内容或者没有释放响应对象,HttpClient不会把连接放回连接池。这些被占用的连接会一直挂着,直到默认的60秒空闲超时后才被关闭,后面的请求只能乖乖等这60秒,等连接释放后才能继续。
解决办法很简单:
- 用
using包裹HttpResponseMessage,确保自动释放,同时必须读取内容(哪怕你不需要):foreach (var task in tasks) { using var response = await task; // 强制读取内容,触发连接释放 var content = await response.Content.ReadAsStringAsync(); } - 或者直接用
GetStringAsync这类方法,它会自动处理响应的释放逻辑:tasks.Add(client.GetStringAsync("https://your-api.com/endpoint"));
2. 并发连接数限制
如果你的并行请求数超过了客户端或服务器允许的最大并发连接数,后面的请求会进入排队状态。
- 针对.NET Framework:全局的
ServicePointManager.DefaultConnectionLimit默认只有2,这意味着同一个域名最多同时开2个连接!你需要在应用启动时把它调大:ServicePointManager.DefaultConnectionLimit = 100; // 根据你的并发需求调整 - 针对.NET Core/.NET 5+:默认连接数很高,但如果还是不够,可以手动设置
HttpClientHandler的连接上限:var handler = new HttpClientHandler { MaxConnectionsPerServer = 100 // 按需设置合适的数值 }; var client = new HttpClient(handler);
3. 服务器端的连接限制
有些服务器(比如Nginx、IIS)会限制单个客户端的并发连接数,如果你的请求数超过了服务器的限制,也会导致排队。这种情况你可以:
- 联系服务器管理员调整并发限制;
- 在客户端用
SemaphoreSlim主动控制并发请求数,避免一下子发太多请求:var semaphore = new SemaphoreSlim(10); // 限制同时最多10个请求 var tasks = new List<Task>(); for (int i = 0; i < 50; i++) { tasks.Add(Task.Run(async () => { await semaphore.WaitAsync(); try { using var response = await client.GetAsync("https://your-api.com/endpoint"); var content = await response.Content.ReadAsStringAsync(); } finally { semaphore.Release(); } })); } await Task.WhenAll(tasks);
最后再提一句:HttpClient一定要复用,别每次请求都new一个,不然会耗尽套接字资源,也会搞砸连接池的效率。
内容的提问来源于stack exchange,提问作者p3tch
相关产品推荐
相关产品推荐

