.NET5 HttpClient多线程并发请求阻塞“发生一个或多个错误”解决方案
目录
前言
我在测试 WebApi NETCore框架时遇到麻烦,使用 HttpClient 多线程异步请求WebApi接口模拟大批量用户请求,随着模拟用户数量增加(线程数量增加)突然卡住,过了1,2分钟后系统报错:“发生一个或多个错误”。
解决方案
1. 使用 HttpClient 请求完成立即关闭和释放连接。
解决方案1:在使用using将HttpClient包裹起来,调用完成立即释放连接。
使用HttpClient 异步多线程请求接口的时候,每次请求到第47个的时候,就报了异常:“发生请求是出错,发生一个或多个错误”。然后stacktrace提示: 在 System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions) 在 System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
在使用using将HttpClient包裹起来,调用完成立即释放连接,即:using(Httpclient client = new Httpclient){}。初步猜想造成这个异常的原因是httpclient被频繁使用,当未被回收导致出现异常!
C#源码:
HttpResponseMessage response;
using (HttpClient client = new HttpClient())
{
client.Timeout = TimeSpan.FromMinutes(2); //客户端超时2分钟
response = client.PostAsync(url, httpContent).Result;
}
2. 在客户端调用前设置 System.Net.ServicePoint 对象所允许的最大并发连接数。
HttpClient是否有默认并发数限制?
在.Net 4.0之前,一直是依靠HttpWebRequest实现Http操作的。它默认有一个非常保守的同一站点下最大2并发数限制,导致默认情况下HttpWebRequest往往得不到理想的速度(估计这个策略郁闷了不少码农),必须修改App.config或ServicePointManager.DefaultConnectionLimit的值。
MS在.Net 4.5中引入了一个HttpClient类专门处理Http操作,本来我以为HttpClient和HttpWebRequest遵循一样的策略的。今天在写一个多线程下载的程序的时候,用到了10个并发连接,发现在默认的情况下,HttpClient并没有并发数限制。
最初我以为是.Net 4.5取消了这个并发数限制(毕竟现在基本上没有谁遵循这个标准了),然后用WebRequest重写了相关代码,发现依然是2并发上限,并且ServicePointManager.DefaultConnectionLimit的值也是2。也就是说: HttpClient不受HttpWebRequest并发策略控制,也没有系统级的并发限制。
另外,测试的时候发现,HttpWebRequest默认也不是对所有地址都2并发上限的。例如,对本地的http地址连接(http://localhost/*)就没有并发限制。
在Http协议中,规定了同个Http请求的并发连接数最大为2. 这个数值,可谓是太小了。而目前的浏览器,已基本不再遵循这个限制,但是Dot Net平台上的 System.Net 还是默认遵循了这个标准的。从而造成了,在使用HttpWebRequset 或者 WebClient 利用多线程的方式,访问某个网站时,经常出现 连接被异常关闭 的错误,大大降低了效率。这个限制的值,是可以自己设置或配置的。System.Net.ServicePointManager.DefaultConnectionLimit 就是设置的地方。 可以根据实际情况,来设置这个值的大小,不过,建议不要超过1024,推荐为512,已经足够了。
解决方案2:在客户端调用前设置 System.Net.ServicePoint 对象所允许的最大并发连接数。
//这个值最好不要超过1024。
System.Net.ServicePointManager.DefaultConnectionLimit = 512;
模拟20000个用户端并发请求