为何使用线程时HTTP并发连接数受限?如何解除限制?
这个问题我之前也遇到过,结合你的测试结果,咱们一步步拆解:
答案是**.NET Framework的ServicePointManager类**。你用的WebClient底层依赖HttpWebRequest,而HttpWebRequest会通过ServicePointManager管理针对每个目标主机的连接池,它默认对同一主机的并发连接数设置了10个上限。这就是为什么你的25个请求会分成3批(10+10+5)依次完成,每批间隔正好是服务器的2秒响应时间。
早期的HTTP/1.1规范(RFC 2616)建议客户端对同一服务器的并发连接数不超过2个,目的是避免给服务器造成过大压力。后来微软考虑到现代服务器的承载能力,把.NET Framework的默认值调整到了10——既保证了一定的并发性能,又不会过度消耗服务器资源。
要修改这个上限,只需要在创建WebClient之前,设置ServicePointManager.DefaultConnectionLimit的值:
// 在启动线程前添加这行,设置为极大值(接近无限制) ServicePointManager.DefaultConnectionLimit = int.MaxValue; // 或者根据你的需求设置具体数值,比如50 // ServicePointManager.DefaultConnectionLimit = 50;
如果只想针对特定主机调整(不影响其他请求),可以单独获取该主机的ServicePoint来设置:
var targetUri = new Uri("http://192.168.1.101:8090/"); var servicePoint = ServicePointManager.FindServicePoint(targetUri); servicePoint.ConnectionLimit = int.MaxValue;
注意:如果是用.NET Core/.NET 5+,默认的并发上限已经很高(比如
SocketsHttpHandler的MaxConnectionsPerServer默认是65536),所以不需要额外修改;但如果在.NET Core中仍使用旧的WebClient,它内部包装了HttpClient,可以通过配置HttpClientHandler来调整。
这里给你几个常见语言的调整方式:
Python(requests库)
requests默认连接池上限是10,通过HTTPAdapter修改:
import requests from requests.adapters import HTTPAdapter session = requests.Session() # 设置每个主机的最大连接数为100 adapter = HTTPAdapter(pool_connections=100, pool_maxsize=100) session.mount("http://", adapter) session.mount("https://", adapter) # 之后用session.get()发起请求即可
Java
OkHttp(推荐)
OkHttp默认连接池上限是5,调整方式:
OkHttpClient client = new OkHttpClient.Builder() .connectionPool(new ConnectionPool(50, 5, TimeUnit.MINUTES)) // 50=最大空闲连接数,5分钟=连接空闲超时时间 .build();
原生HttpURLConnection
默认上限是5,通过系统属性修改:
System.setProperty("http.maxConnections", "100");
Node.js(axios)
axios基于http模块,默认并发上限是5,通过自定义Agent调整:
const axios = require('axios'); const http = require('http'); const customAgent = new http.Agent({ maxSockets: 100 // 每个主机的最大并发连接数 }); // 发起请求时指定agent axios.get('http://192.168.1.101:8090/', { httpAgent: customAgent });
虽然可以调高并发上限,但不建议设置成“完全无限制”——操作系统本身有套接字资源的限制,过高的并发会导致CPU、内存或端口耗尽,反而让请求变慢甚至失败。最好根据你的服务器承载能力和业务需求,设置一个合理的数值。
内容的提问来源于stack exchange,提问作者Mohi




