.NET Framework 4.8 HttpClient并发调用Springboot接口随机断连求解
根因定位
这个异常的核心是TCP连接半开问题:SpringBoot默认内置Tomcat服务端的长连接空闲超时默认仅20秒,超过该时长服务端会主动关闭连接;而.NET Framework默认的ServicePoint连接池空闲超时为100秒,就会出现服务端已经销毁连接、客户端仍持有过期连接发起请求的情况,最终触发远程主机关闭连接的报错。设置ConnectionClose=true相当于每次请求都新建短连接,自然不会触发过期连接复用问题,但会牺牲性能。
保留长连接的解决方案
- 方案1:对齐客户端与服务端的空闲超时(最通用,无需改服务端)
给目标API对应的ServicePoint配置小于服务端空闲超时的最大空闲时间,确保客户端先回收过期连接,同时开启TCP保活探测、调高并发连接上限:// 初始化HttpClient前先配置目标地址的连接参数 var targetUri = new Uri(API_URL); var servicePoint = ServicePointManager.FindServicePoint(targetUri); // 空闲超时设为15秒,小于SpringBoot默认的20秒空闲超时 servicePoint.MaxIdleTime = 15 * 1000; // 开启TCP保活,3秒后开始探测,每隔1秒探测一次 servicePoint.SetTcpKeepAlive(true, 3000, 1000); // 调高单域名并发连接上限,默认值2完全无法满足高并发场景 servicePoint.ConnectionLimit = 100; // 后续HttpClient初始化和业务逻辑保持不变 HttpClient client = new HttpClient(); - 方案2:配合调整服务端长连接配置(适合可以修改服务端的场景)
在SpringBoot的application.properties中调高长连接超时阈值,对应同步调整客户端MaxIdleTime略小于服务端配置即可:
对应客户端# 长连接空闲超时设为60秒 server.tomcat.keep-alive-timeout=60000 # 单个长连接最多支持复用1000次请求 server.tomcat.max-keep-alive-requests=1000 # 连接超时时间调整 server.tomcat.connection-timeout=60000MaxIdleTime设为55 * 1000即可。 - 方案3:修复类库已知Bug
.NET Framework自带的System.Net.Http程序集存在多个连接复用相关的已知问题,可将项目中System.Net.Http的引用替换为最新稳定版的NuGet包,规避类库层面的缺陷。
内容的提问来源于stack exchange,提问作者Raymond Peng
相关产品推荐
相关产品推荐

