当前位置: 首页 > article >正文

.NET 10了,HttpClient还是不能用using吗?我做了一个实验

会突然变成玄学有的人能跑有的人会炸有人说这是一个这是一个“bug”在某某版本中会修复其实并没有有人说这是一个feature设计就是如此……所以我决定做一个实验来重现一下10年前就有的现象看这些现象是否有任何不同。本文用一组可复现的压测同机 server/clientWindowsrequests20000parallel200对比每请求new HttpClientDispose()也就是大家常说的“using 写法”复用一个HttpClient静态/单例使用IHttpClientFactory并观察关键指标TIME_WAIT 数量以及是否出现经典的端口耗尽错误通常每个套接字地址(协议/网络地址/端口)只允许使用一次。实验目标验证“每请求 new HttpClient 并 using 释放”在高并发下会导致 TIME_WAIT 激增并对比复用 HttpClient / IHttpClientFactory 的表现。实验环境与参数OS: WindowsSDK: .NET SDK 10.0.102服务器: HttpLeakServertarget net6通过 roll-forward 运行客户端: net48 / net6 / net8 / net10压测参数: requests20000, parallel200, timeoutSeconds5TIME_WAIT 统计:netstat -an过滤端口 5055隔离策略: 每轮结束后等待 TIME_WAIT baseline 200每 10 秒检查最长 300 秒如何运行可复现完整项目我放在 GitHubhttps://github.com/sdcb/http-client-exp1启动服务端单独窗口dotnet run --project Server/HttpLeakServer/HttpLeakServer.csproj2运行实验脚本另一个窗口scripts/run-experiment-external-server.ps1本次日志目录logs/run-20260119-095017解读为什么“using HttpClient”会把你推向端口耗尽很多人直觉会觉得HttpClient是托管对象用完Dispose()不就释放资源了吗但这里有两个关键点经常被忽略HttpClient并不是“请求一次就关一次连接”的简单模型。HTTP Keep-Alive 连接池的存在意味着正确姿势应该是复用底层连接或至少复用 handler 的连接池让大量请求复用少量 TCP 连接。你频繁new HttpClientDispose()等价于频繁建立 TCP 连接并快速关闭。而 TCP 连接的关闭会进入TIME_WAIT具体哪一端进入 TIME_WAIT 与关闭时序有关TIME_WAIT 存在的意义是保护网络不被“旧连接的残留包”污染。在“200 并发 2 万次请求”这种参数下如果你让每个请求都创建新连接那么很容易短时间制造大量 TIME_WAIT一旦本机可用的临时端口范围被 TIME_WAIT 占满或接近占满新连接就会开始失败典型异常就是通常每个套接字地址(协议/网络地址/端口)只允许使用一次。这也是为什么同样的代码在低并发下“看起来完全没问题”在压力一上来就开始“玄学报错”那到底怎么写才对本文不展开“所有场景的最佳实践”只给两条最能落地的结论业务代码不要每次请求 new HttpClient。要么复用单例/静态HttpClient要么使用IHttpClientFactory。可以 using 的是HttpResponseMessage/HttpContent它们确实应该及时释放而不是“每个请求一个 HttpClient”。下面我把这次实验的完整代码和原始日志全部贴出来方便你自己复跑/改参数/做二次验证。完整代码精简版一份源码 条件编译完整项目地址https://github.com/sdcb/http-client-exp为了避免同样的代码贴四遍这里把 net48/net6/net8/net10 的客户端合并成一份用#if / #elif表示差异实验输出与原始日志仍按“多份结果”原样保留在后文。简单服务端HttpLeakServerServer/HttpLeakServer/HttpLeakServer.csprojProject SdkMicrosoft.NET.Sdk.Web PropertyGroup TargetFrameworknet6.0/TargetFramework Nullableenable/Nullable ImplicitUsingsenable/ImplicitUsings /PropertyGroup /ProjectServer/HttpLeakServer/Program.csusing Microsoft.AspNetCore.Builder; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; var builder WebApplication.CreateBuilder(args); builder.Logging.ClearProviders(); builder.Logging.AddSimpleConsole(options { options.SingleLine true; options.TimestampFormat HH:mm:ss ; }); var app builder.Build(); app.MapGet(/, () Results.Text(ok)); app.MapGet(/ping, () Results.Text(ok)); app.MapGet(/slow, async () { await Task.Delay(50); return Results.Text(ok); }); var url Environment.GetEnvironmentVariable(HTTPLEAK_URL) ?? http://localhost:5055; app.Urls.Add(url); app.Lifetime.ApplicationStarted.Register(() { Console.WriteLine($Listening on {url}); }); await app.RunAsync();客户端HttpLeakClientnet48/net6/net8/net10 共用一份Clients/HttpLeakClient/HttpLeakClient.csproj示意多目标 条件依赖Project SdkMicrosoft.NET.Sdk PropertyGroup OutputTypeExe/OutputType TargetFrameworksnet48;net6.0;net8.0;net10.0/TargetFrameworks LangVersionlatest/LangVersion Nullableenable/Nullable ImplicitUsingsenable/ImplicitUsings /PropertyGroup ItemGroup Condition$(TargetFramework) net48 Reference IncludeSystem.Net.Http / /ItemGroup ItemGroup Condition$(TargetFramework) net10.0 PackageReference IncludeMicrosoft.Extensions.Http Version10.0.0 / /ItemGroup /ProjectClients/HttpLeakClient/Program.cs用#if表示差异using System.Diagnostics; using System.Net.Http; #if NET48 using System.Net; #endif #if NET10_0_OR_GREATER using Microsoft.Extensions.DependencyInjection; #endif static string? GetArg(string[] args, string name) { for (var i 0; i args.Length - 1; i) { if (string.Equals(args[i], name, StringComparison.OrdinalIgnoreCase)) { return args[i 1]; } } return null; } static int GetArgInt(string[] args, string name, int defaultValue) { var value GetArg(args, name); return int.TryParse(value, out var parsed) ? parsed : defaultValue; } var url GetArg(args, --url) ?? http://localhost:5055/ping; var requests GetArgInt(args, --requests, 20000); var parallel GetArgInt(args, --parallel, 200); var logEvery GetArgInt(args, --logEvery, 1000); var timeoutSeconds GetArgInt(args, --timeoutSeconds, 5); #if NET10_0_OR_GREATER var mode GetArg(args, --mode) ?? new; // new | static | factory #endif Console.WriteLine($url{url}); #if NET10_0_OR_GREATER Console.WriteLine($requests{requests}, parallel{parallel}, timeoutSeconds{timeoutSeconds}, mode{mode}); #else Console.WriteLine($requests{requests}, parallel{parallel}, timeoutSeconds{timeoutSeconds}); #endif #if NET48 ServicePointManager.DefaultConnectionLimit 1000; ServicePointManager.Expect100Continue false; #endif var throttler new SemaphoreSlim(parallel); var tasks new ListTask(requests); var sw Stopwatch.StartNew(); var success 0; var failed 0; #if NET10_0_OR_GREATER HttpClient? staticClient null; if (string.Equals(mode, static, StringComparison.OrdinalIgnoreCase)) { staticClient new HttpClient { Timeout TimeSpan.FromSeconds(timeoutSeconds) }; } IHttpClientFactory? httpClientFactory null; ServiceProvider? serviceProvider null; if (string.Equals(mode, factory, StringComparison.OrdinalIgnoreCase)) { var services new ServiceCollection(); services.AddHttpClient(); serviceProvider services.BuildServiceProvider(); httpClientFactory serviceProvider.GetRequiredServiceIHttpClientFactory(); } #endif for (var i 0; i requests; i) { await throttler.WaitAsync(); var index i 1; tasks.Add(Task.Run(async () { try { #if NET10_0_OR_GREATER HttpClient client; if (staticClient ! null) { client staticClient; } else if (httpClientFactory ! null) { client httpClientFactory.CreateClient(); client.Timeout TimeSpan.FromSeconds(timeoutSeconds); } else { client new HttpClient(); client.Timeout TimeSpan.FromSeconds(timeoutSeconds); } using var response await client.GetAsync(url); response.EnsureSuccessStatusCode(); Interlocked.Increment(ref success); if (staticClient null httpClientFactory null) { client.Dispose(); } #else using var client new HttpClient(); client.Timeout TimeSpan.FromSeconds(timeoutSeconds); using var response await client.GetAsync(url); response.EnsureSuccessStatusCode(); Interlocked.Increment(ref success); #endif } catch (Exception ex) { var fail Interlocked.Increment(ref failed); if (fail 5) { Console.WriteLine($ERR#{fail}: {ex.GetType().Name} {ex.Message}); } } finally { throttler.Release(); } })); if (index % logEvery 0) { Console.WriteLine($queued: {index}/{requests}, success: {Volatile.Read(ref success)}, failed: {Volatile.Read(ref failed)}, elapsed: {sw.Elapsed}); } } await Task.WhenAll(tasks); Console.WriteLine($done: success{success}, failed{failed}, elapsed{sw.Elapsed}); #if NET10_0_OR_GREATER staticClient?.Dispose(); serviceProvider?.Dispose(); #endifPowerShell 脚本脚本我就不在文章里全文贴了外部启动 Server 版本https://github.com/sdcb/http-client-exp/blob/main/scripts/run-experiment-external-server.ps1脚本内启动 Server 版本https://github.com/sdcb/http-client-exp/blob/main/scripts/run-experiment.ps1原始实验结果日志完整贴出日志目录logs/run-20260119-095017experiment-summary.log[2026-01-19T09:51:13.718085708:00] net48 ExitCode0 OutLogC:\Users\ZhouJie\source\repos\http-client-exp\logs\\run-20260119-095017\net48.out.log ErrLogC:\Users\ZhouJie\source\repos\http-client-exp\logs\\run-20260119-095017\net48.err.log [2026-01-19T09:53:33.036252308:00] net6 ExitCode0 OutLogC:\Users\ZhouJie\source\repos\http-client-exp\logs\\run-20260119-095017\net6.out.log ErrLogC:\Users\ZhouJie\source\repos\http-client-exp\logs\\run-20260119-095017\net6.err.log [2026-01-19T09:56:00.457452708:00] net8 ExitCode0 OutLogC:\Users\ZhouJie\source\repos\http-client-exp\logs\\run-20260119-095017\net8.out.log ErrLogC:\Users\ZhouJie\source\repos\http-client-exp\logs\\run-20260119-095017\net8.err.log [2026-01-19T09:58:27.261813908:00] net10-new ExitCode0 OutLogC:\Users\ZhouJie\source\repos\http-client-exp\logs\\run-20260119-095017\net10-new.out.log ErrLogC:\Users\ZhouJie\source\repos\http-client-exp\logs\\run-20260119-095017\net10-new.err.log [2026-01-19T10:00:53.049047208:00] net10-static ExitCode0 OutLogC:\Users\ZhouJie\source\repos\http-client-exp\logs\\run-20260119-095017\net10-static.out.log ErrLogC:\Users\ZhouJie\source\repos\http-client-exp\logs\\run-20260119-095017\net10-static.err.log [2026-01-19T10:01:10.209616408:00] net10-factory ExitCode0 OutLogC:\Users\ZhouJie\source\repos\http-client-exp\logs\\run-20260119-095017\net10-factory.out.log ErrLogC:\Users\ZhouJie\source\repos\http-client-exp\logs\\run-20260119-095017\net10-factory.err.lognetstat.log[2026-01-19T09:50:55.662745508:00] before-net48 TIME_WAIT2 ESTABLISHED0 CLOSE_WAIT0 [2026-01-19T09:51:15.468660308:00] after-net48 TIME_WAIT20002 ESTABLISHED0 CLOSE_WAIT0 [2026-01-19T09:53:13.964748508:00] before-net6 TIME_WAIT0 ESTABLISHED0 CLOSE_WAIT0 [2026-01-19T09:53:33.811229408:00] after-net6 TIME_WAIT20000 ESTABLISHED0 CLOSE_WAIT0 [2026-01-19T09:55:42.643501508:00] before-net8 TIME_WAIT0 ESTABLISHED0 CLOSE_WAIT0 [2026-01-19T09:56:01.190000008:00] after-net8 TIME_WAIT18361 ESTABLISHED0 CLOSE_WAIT0 [2026-01-19T09:58:08.860312908:00] before-net10-new TIME_WAIT0 ESTABLISHED0 CLOSE_WAIT0 [2026-01-19T09:58:28.150073708:00] after-net10-new TIME_WAIT18860 ESTABLISHED0 CLOSE_WAIT0 [2026-01-19T10:00:36.103875708:00] before-net10-static TIME_WAIT0 ESTABLISHED0 CLOSE_WAIT0 [2026-01-19T10:00:53.100725908:00] after-net10-static TIME_WAIT200 ESTABLISHED0 CLOSE_WAIT0 [2026-01-19T10:00:53.245879808:00] before-net10-factory TIME_WAIT200 ESTABLISHED0 CLOSE_WAIT0 [2026-01-19T10:01:10.257467808:00] after-net10-factory TIME_WAIT200 ESTABLISHED0 CLOSE_WAIT0cooldown.log[2026-01-19T09:51:16.268766608:00] cooldown-net48 TIME_WAIT20002 baseline2 limit202 [2026-01-19T09:51:27.042780508:00] cooldown-net48 TIME_WAIT20002 baseline2 limit202 [2026-01-19T09:51:37.818438208:00] cooldown-net48 TIME_WAIT20002 baseline2 limit202 [2026-01-19T09:51:48.540449208:00] cooldown-net48 TIME_WAIT20002 baseline2 limit202 [2026-01-19T09:51:59.284696808:00] cooldown-net48 TIME_WAIT20002 baseline2 limit202 [2026-01-19T09:52:10.156207908:00] cooldown-net48 TIME_WAIT20002 baseline2 limit202 [2026-01-19T09:52:21.058862208:00] cooldown-net48 TIME_WAIT20002 baseline2 limit202 [2026-01-19T09:52:31.777770408:00] cooldown-net48 TIME_WAIT20002 baseline2 limit202 [2026-01-19T09:52:42.566435008:00] cooldown-net48 TIME_WAIT20002 baseline2 limit202 [2026-01-19T09:52:53.329961408:00] cooldown-net48 TIME_WAIT20001 baseline2 limit202 [2026-01-19T09:53:03.810973408:00] cooldown-net48 TIME_WAIT10752 baseline2 limit202 [2026-01-19T09:53:13.856083108:00] cooldown-net48 TIME_WAIT0 baseline2 limit202 [2026-01-19T09:53:34.637071108:00] cooldown-net6 TIME_WAIT20000 baseline0 limit200 [2026-01-19T09:53:45.516697408:00] cooldown-net6 TIME_WAIT20000 baseline0 limit200 [2026-01-19T09:53:56.289973608:00] cooldown-net6 TIME_WAIT20000 baseline0 limit200 [2026-01-19T09:54:07.016542808:00] cooldown-net6 TIME_WAIT20000 baseline0 limit200 [2026-01-19T09:54:17.887213708:00] cooldown-net6 TIME_WAIT20000 baseline0 limit200 [2026-01-19T09:54:28.767352908:00] cooldown-net6 TIME_WAIT20000 baseline0 limit200 [2026-01-19T09:54:39.520009108:00] cooldown-net6 TIME_WAIT20000 baseline0 limit200 [2026-01-19T09:54:50.309065908:00] cooldown-net6 TIME_WAIT20000 baseline0 limit200 [2026-01-19T09:55:01.063892008:00] cooldown-net6 TIME_WAIT20000 baseline0 limit200 [2026-01-19T09:55:11.752952808:00] cooldown-net6 TIME_WAIT20000 baseline0 limit200 [2026-01-19T09:55:22.388644508:00] cooldown-net6 TIME_WAIT12540 baseline0 limit200 [2026-01-19T09:55:32.465878608:00] cooldown-net6 TIME_WAIT435 baseline0 limit200 [2026-01-19T09:55:42.535487808:00] cooldown-net6 TIME_WAIT0 baseline0 limit200 [2026-01-19T09:56:01.887649308:00] cooldown-net8 TIME_WAIT18361 baseline0 limit200 [2026-01-19T09:56:12.634154108:00] cooldown-net8 TIME_WAIT18361 baseline0 limit200 [2026-01-19T09:56:23.280660408:00] cooldown-net8 TIME_WAIT18361 baseline0 limit200 [2026-01-19T09:56:33.942587308:00] cooldown-net8 TIME_WAIT18361 baseline0 limit200 [2026-01-19T09:56:44.627756108:00] cooldown-net8 TIME_WAIT18361 baseline0 limit200 [2026-01-19T09:56:55.301367408:00] cooldown-net8 TIME_WAIT18361 baseline0 limit200 [2026-01-19T09:57:06.027812808:00] cooldown-net8 TIME_WAIT18361 baseline0 limit200 [2026-01-19T09:57:16.731557808:00] cooldown-net8 TIME_WAIT18361 baseline0 limit200 [2026-01-19T09:57:27.388792508:00] cooldown-net8 TIME_WAIT18361 baseline0 limit200 [2026-01-19T09:57:38.044245308:00] cooldown-net8 TIME_WAIT18361 baseline0 limit200 [2026-01-19T09:57:48.656683908:00] cooldown-net8 TIME_WAIT12989 baseline0 limit200 [2026-01-19T09:57:58.734733708:00] cooldown-net8 TIME_WAIT1069 baseline0 limit200 [2026-01-19T09:58:08.778066008:00] cooldown-net8 TIME_WAIT0 baseline0 limit200 [2026-01-19T09:58:29.026129108:00] cooldown-net10-new TIME_WAIT18860 baseline0 limit200 [2026-01-19T09:58:39.749104308:00] cooldown-net10-new TIME_WAIT18860 baseline0 limit200 [2026-01-19T09:58:50.461379608:00] cooldown-net10-new TIME_WAIT18860 baseline0 limit200 [2026-01-19T09:59:01.206454508:00] cooldown-net10-new TIME_WAIT18860 baseline0 limit200 [2026-01-19T09:59:11.871015308:00] cooldown-net10-new TIME_WAIT18860 baseline0 limit200 [2026-01-19T09:59:22.564848608:00] cooldown-net10-new TIME_WAIT18860 baseline0 limit200 [2026-01-19T09:59:33.275595808:00] cooldown-net10-new TIME_WAIT18860 baseline0 limit200 [2026-01-19T09:59:43.963154708:00] cooldown-net10-new TIME_WAIT18860 baseline0 limit200 [2026-01-19T09:59:54.697924308:00] cooldown-net10-new TIME_WAIT18860 baseline0 limit200 [2026-01-19T10:00:05.396139708:00] cooldown-net10-new TIME_WAIT18860 baseline0 limit200 [2026-01-19T10:00:15.860737808:00] cooldown-net10-new TIME_WAIT11840 baseline0 limit200 [2026-01-19T10:00:25.947140708:00] cooldown-net10-new TIME_WAIT614 baseline0 limit200 [2026-01-19T10:00:36.011170108:00] cooldown-net10-new TIME_WAIT0 baseline0 limit200 [2026-01-19T10:00:53.151064908:00] cooldown-net10-static TIME_WAIT200 baseline0 limit200 [2026-01-19T10:01:10.305778508:00] cooldown-net10-factory TIME_WAIT200 baseline200 limit400net48.out.logurlhttp://localhost:5055/ping requests20000, parallel200, timeoutSeconds5 queued: 1000/20000, success: 803, failed: 0, elapsed: 00:00:00.7170409 queued: 2000/20000, success: 1803, failed: 0, elapsed: 00:00:01.5455465 queued: 3000/20000, success: 2800, failed: 0, elapsed: 00:00:02.3559601 queued: 4000/20000, success: 3801, failed: 0, elapsed: 00:00:03.1925172 queued: 5000/20000, success: 4802, failed: 0, elapsed: 00:00:04.0184093 queued: 6000/20000, success: 5802, failed: 0, elapsed: 00:00:04.8348862 queued: 7000/20000, success: 6800, failed: 0, elapsed: 00:00:05.6775563 queued: 8000/20000, success: 7801, failed: 0, elapsed: 00:00:06.5458377 queued: 9000/20000, success: 8802, failed: 0, elapsed: 00:00:07.4397727 queued: 10000/20000, success: 9803, failed: 0, elapsed: 00:00:08.3348468 queued: 11000/20000, success: 10802, failed: 0, elapsed: 00:00:09.2035416 queued: 12000/20000, success: 11804, failed: 0, elapsed: 00:00:10.0393223 queued: 13000/20000, success: 12806, failed: 0, elapsed: 00:00:10.8262272 queued: 14000/20000, success: 13804, failed: 0, elapsed: 00:00:11.6636597 queued: 15000/20000, success: 14802, failed: 0, elapsed: 00:00:12.4799716 queued: 16000/20000, success: 15819, failed: 0, elapsed: 00:00:13.4697834 queued: 17000/20000, success: 16822, failed: 0, elapsed: 00:00:14.5332049 queued: 18000/20000, success: 17818, failed: 0, elapsed: 00:00:15.5317397 queued: 19000/20000, success: 18816, failed: 0, elapsed: 00:00:16.5405963 queued: 20000/20000, success: 19819, failed: 0, elapsed: 00:00:17.6652081 done: success20000, failed0, elapsed00:00:17.7541839net6.out.logurlhttp://localhost:5055/ping requests20000, parallel200, timeoutSeconds5 queued: 1000/20000, success: 803, failed: 0, elapsed: 00:00:00.7159800 queued: 2000/20000, success: 1803, failed: 0, elapsed: 00:00:01.6028433 queued: 3000/20000, success: 2802, failed: 0, elapsed: 00:00:02.4876237 queued: 4000/20000, success: 3802, failed: 0, elapsed: 00:00:03.3549543 queued: 5000/20000, success: 4802, failed: 0, elapsed: 00:00:04.2710795 queued: 6000/20000, success: 5801, failed: 0, elapsed: 00:00:05.1637653 queued: 7000/20000, success: 6802, failed: 0, elapsed: 00:00:06.0729777 queued: 8000/20000, success: 7802, failed: 0, elapsed: 00:00:07.0697555 queued: 9000/20000, success: 8801, failed: 0, elapsed: 00:00:08.0143162 queued: 10000/20000, success: 9800, failed: 0, elapsed: 00:00:08.9633860 queued: 11000/20000, success: 10802, failed: 0, elapsed: 00:00:09.9344239 queued: 12000/20000, success: 11802, failed: 0, elapsed: 00:00:10.8379783 queued: 13000/20000, success: 12801, failed: 0, elapsed: 00:00:11.6810601 queued: 14000/20000, success: 13801, failed: 0, elapsed: 00:00:12.5122642 queued: 15000/20000, success: 14800, failed: 0, elapsed: 00:00:13.3692282 queued: 16000/20000, success: 15803, failed: 0, elapsed: 00:00:14.2782829 queued: 17000/20000, success: 16801, failed: 0, elapsed: 00:00:15.2187642 queued: 18000/20000, success: 17802, failed: 0, elapsed: 00:00:16.0811154 queued: 19000/20000, success: 18810, failed: 0, elapsed: 00:00:16.9798536 queued: 20000/20000, success: 19817, failed: 0, elapsed: 00:00:17.8952478 done: success20000, failed0, elapsed00:00:18.0175351net8.out.logurlhttp://localhost:5055/ping requests20000, parallel200, timeoutSeconds5 queued: 1000/20000, success: 800, failed: 0, elapsed: 00:00:00.8405997 queued: 2000/20000, success: 1802, failed: 0, elapsed: 00:00:01.6913251 queued: 3000/20000, success: 2800, failed: 0, elapsed: 00:00:02.6176324 queued: 4000/20000, success: 3802, failed: 0, elapsed: 00:00:03.4744051 queued: 5000/20000, success: 4801, failed: 0, elapsed: 00:00:04.2873345 queued: 6000/20000, success: 5800, failed: 0, elapsed: 00:00:05.0960137 queued: 7000/20000, success: 6803, failed: 0, elapsed: 00:00:05.8940500 queued: 8000/20000, success: 7802, failed: 0, elapsed: 00:00:06.7207568 queued: 9000/20000, success: 8803, failed: 0, elapsed: 00:00:07.5346954 queued: 10000/20000, success: 9800, failed: 0, elapsed: 00:00:08.3507870 queued: 11000/20000, success: 10802, failed: 0, elapsed: 00:00:09.1985154 queued: 12000/20000, success: 11803, failed: 0, elapsed: 00:00:10.0035216 queued: 13000/20000, success: 12803, failed: 0, elapsed: 00:00:10.7763067 queued: 14000/20000, success: 13802, failed: 0, elapsed: 00:00:11.6251384 queued: 15000/20000, success: 14802, failed: 0, elapsed: 00:00:12.4436652 queued: 16000/20000, success: 15807, failed: 0, elapsed: 00:00:13.3164599 queued: 17000/20000, success: 16801, failed: 0, elapsed: 00:00:14.2231530 ERR#1: HttpRequestException 通常每个套接字地址(协议/网络地址/端口)只允许使用一次。 (localhost:5055) ERR#2: HttpRequestException 通常每个套接字地址(协议/网络地址/端口)只允许使用一次。 (localhost:5055) ERR#3: HttpRequestException 通常每个套接地址(协议/网络地址/端口)只允许使用一次。 (localhost:5055) ERR#5: HttpRequestException 通常每个套接字地址(协议/网络地址/端口)只允许使用一次。 (localhost:5055) ERR#4: HttpRequestException 通常每个套接字地址(协议/网络地址/端口)只允许使用一次。 (localhost:5055) queued: 18000/20000, success: 17605, failed: 201, elapsed: 00:00:15.0862152 queued: 19000/20000, success: 17711, failed: 1090, elapsed: 00:00:15.6168905 queued: 20000/20000, success: 18165, failed: 1639, elapsed: 00:00:16.3332350 done: success18361, failed1639, elapsed00:00:16.4268168net10-new.out.logurlhttp://localhost:5055/ping requests20000, parallel200, timeoutSeconds5, modenew queued: 1000/20000, success: 805, failed: 0, elapsed: 00:00:00.7099803 queued: 2000/20000, success: 1800, failed: 0, elapsed: 00:00:01.5324361 queued: 3000/20000, success: 2800, failed: 0, elapsed: 00:00:02.3573877 queued: 4000/20000, success: 3800, failed: 0, elapsed: 00:00:03.2069000 queued: 5000/20000, success: 4800, failed: 0, elapsed: 00:00:04.0313423 queued: 6000/20000, success: 5802, failed: 0, elapsed: 00:00:04.8687039 queued: 7000/20000, success: 6801, failed: 0, elapsed: 00:00:05.7252572 queued: 8000/20000, success: 7800, failed: 0, elapsed: 00:00:06.5624078 queued: 9000/20000, success: 8800, failed: 0, elapsed: 00:00:07.4244971 queued: 10000/20000, success: 9800, failed: 0, elapsed: 00:00:08.2911306 queued: 11000/20000, success: 10800, failed: 0, elapsed: 00:00:09.1755667 queued: 12000/20000, success: 11801, failed: 0, elapsed: 00:00:10.1160925 queued: 13000/20000, success: 12802, failed: 0, elapsed: 00:00:11.0165038 queued: 14000/20000, success: 13801, failed: 0, elapsed: 00:00:11.9382103 queued: 15000/20000, success: 14802, failed: 0, elapsed: 00:00:12.8002543 queued: 16000/20000, success: 15801, failed: 0, elapsed: 00:00:13.7185127 ERR#3: HttpRequestException 通常每个套接字地址(协议/网络地址/端口)只允许使用一次。 (localhost:5055) ERR#2: HttpRequestException 通常每个套接字地址(协议/网络地址/端口)只允许使用一次。 (localhost:5055) ERR#1: HttpRequestException 通常每个套接字地址(协议/网络地址/端口)只允许使用一次。 (localhost:5055) ERR#5: HttpRequestException 通常每个套接字地址(协议/网络地址/端口)只允许使用一次。 (localhost:5055) ERR#4: HttpRequestException 通常每个套接字地址(协议/网络地址/端口)只允许使用一次。 (localhost:5055) queued: 17000/20000, success: 16682, failed: 118, elapsed: 00:00:14.7578539 queued: 18000/20000, success: 16684, failed: 1118, elapsed: 00:00:15.4297844 queued: 19000/20000, success: 17661, failed: 1140, elapsed: 00:00:16.2796589 queued: 20000/20000, success: 18661, failed: 1140, elapsed: 00:00:17.3258406 done: success18860, failed1140, elapsed00:00:17.3996862net10-static.out.logurlhttp://localhost:5055/ping requests20000, parallel200, timeoutSeconds5, modestatic queued: 1000/20000, success: 801, failed: 0, elapsed: 00:00:00.6551470 queued: 2000/20000, success: 1800, failed: 0, elapsed: 00:00:01.5355394 queued: 3000/20000, success: 2800, failed: 0, elapsed: 00:00:02.3480456 queued: 4000/20000, success: 3800, failed: 0, elapsed: 00:00:03.0999050 queued: 5000/20000, success: 4800, failed: 0, elapsed: 00:00:03.8470820 queued: 6000/20000, success: 5800, failed: 0, elapsed: 00:00:04.5759884 queued: 7000/20000, success: 6800, failed: 0, elapsed: 00:00:05.3461919 queued: 8000/20000, success: 7801, failed: 0, elapsed: 00:00:06.0916621 queued: 9000/20000, success: 8802, failed: 0, elapsed: 00:00:06.9085343 queued: 10000/20000, success: 9800, failed: 0, elapsed: 00:00:07.8274125 queued: 11000/20000, success: 10800, failed: 0, elapsed: 00:00:08.6757231 queued: 12000/20000, success: 11800, failed: 0, elapsed: 00:00:09.5154490 queued: 13000/20000, success: 12800, failed: 0, elapsed: 00:00:10.3306765 queued: 14000/20000, success: 13800, failed: 0, elapsed: 00:00:11.1493724 queued: 15000/20000, success: 14800, failed: 0, elapsed: 00:00:11.9658212 queued: 16000/20000, success: 15801, failed: 0, elapsed: 00:00:12.7510706 queued: 17000/20000, success: 16800, failed: 0, elapsed: 00:00:13.4735304 queued: 18000/20000, success: 17800, failed: 0, elapsed: 00:00:14.2777953 queued: 19000/20000, success: 18800, failed: 0, elapsed: 00:00:15.0219907 queued: 20000/20000, success: 19801, failed: 0, elapsed: 00:00:15.7699702 done: success20000, failed0, elapsed00:00:15.8507052net10-factory.out.logurlhttp://localhost:5055/ping requests20000, parallel200, timeoutSeconds5, modefactory queued: 1000/20000, success: 801, failed: 0, elapsed: 00:00:00.7094395 queued: 2000/20000, success: 1801, failed: 0, elapsed: 00:00:01.5072383 queued: 3000/20000, success: 2800, failed: 0, elapsed: 00:00:02.3047647 queued: 4000/20000, success: 3800, failed: 0, elapsed: 00:00:03.0607252 queued: 5000/20000, success: 4800, failed: 0, elapsed: 00:00:03.8370598 queued: 6000/20000, success: 5800, failed: 0, elapsed: 00:00:04.6621606 queued: 7000/20000, success: 6800, failed: 0, elapsed: 00:00:05.4589104 queued: 8000/20000, success: 7800, failed: 0, elapsed: 00:00:06.2913588 queued: 9000/20000, success: 8800, failed: 0, elapsed: 00:00:07.0629536 queued: 10000/20000, success: 9800, failed: 0, elapsed: 00:00:07.8438472 queued: 11000/20000, success: 10800, failed: 0, elapsed: 00:00:08.5796209 queued: 12000/20000, success: 11800, failed: 0, elapsed: 00:00:09.3663975 queued: 13000/20000, success: 12801, failed: 0, elapsed: 00:00:10.1984757 queued: 14000/20000, success: 13800, failed: 0, elapsed: 00:00:11.0474925 queued: 15000/20000, success: 14800, failed: 0, elapsed: 00:00:11.9175753 queued: 16000/20000, success: 15800, failed: 0, elapsed: 00:00:12.7356429 queued: 17000/20000, success: 16801, failed: 0, elapsed: 00:00:13.4991148 queued: 18000/20000, success: 17800, failed: 0, elapsed: 00:00:14.2912941 queued: 19000/20000, success: 18800, failed: 0, elapsed: 00:00:15.0844828 queued: 20000/20000, success: 19800, failed: 0, elapsed: 00:00:15.8439387 done: success20000, failed0, elapsed00:00:15.9485251局限与备注别把结论用错地方客户端与服务器同机TIME_WAIT 统计包含两端连接不能完全归因于“客户端端口耗尽”但它足以说明“短时间制造大量短连接”这件事本身的风险。net48 设置了ServicePointManager.DefaultConnectionLimit 1000与 net6/net10 的连接管理策略存在差异。关键结果汇总TIME_WAIT 统计端口 5055运行before TIME_WAITafter TIME_WAIT耗时秒net4822000217.754net602000018.018net801836116.427net1001886017.400net10-static020015.851net10-factory20020015.949来源logs/run-20260119-095017/netstat.log客户端执行结果摘要net48: success20000, failed0net6: success20000, failed0net8: success18361, failed1639报错“通常每个套接字地址只允许使用一次”net10-new: success18860, failed1140报错“通常每个套接字地址只允许使用一次”net10-static: success20000, failed0net10-factory: success20000, failed0来源logs/run-20260119-095017/*.out.log结论“.NET 10 了HttpClient 还能不能 using”——答案依然是别把 HttpClient 当成一次性对象。

相关文章:

.NET 10了,HttpClient还是不能用using吗?我做了一个实验

会突然变成玄学:有的人能跑,有的人会炸,有人说这是一个这是一个“bug”,在某某版本中会修复(其实并没有),有人说这是一个feature,设计就是如此……所以我决定做一个实验,…...

别再手动配准点云了!用C++ Eigen库的SVD方法,5分钟搞定刚体变换(附完整代码)

5分钟用Eigen实现点云刚体变换:SVD方法的工程实践指南 在三维视觉和机器人领域,点云配准是基础且关键的任务。想象一下,当你需要将不同视角扫描的点云拼接成一个完整的三维模型,或者让机器人识别物体的位姿时,快速准确…...

UEFI开发实战指南 – 从环境搭建到国产平台适配

1. UEFI开发环境搭建全攻略 第一次接触UEFI开发时,我被各种陌生的术语搞得晕头转向。经过几个实际项目的摸爬滚打,终于摸清了门道。UEFI开发环境的搭建其实就像搭积木,只要掌握关键步骤,新手也能快速上手。 在Windows系统下搭建环…...

一款实用汉化工具快速安装使用指南 -- cheat-engine中文版安装教程入口

文章目录安装方式安装后在哪里找到?(重点补全)使用说明温馨提示首先呢,大家可能在用 cheat engine (CE修改器)的时候呢,可能总是使用的是英文版,用的不太舒服啊,这个时候呢&#xff…...

效率革命:基于快马AI生成opencode自动化安装工具,告别手动敲命令

效率革命:基于快马AI生成opencode自动化安装工具,告别手动敲命令 最近在团队协作中,经常遇到新成员需要配置opencode开发环境的情况。每次看到同事手动输入一长串命令,还要处理各种依赖报错,我就想:能不能…...

Claude Code 是怎么跑起来的:从 Agent Loop 理解代理循环实现

如果你已经会调用大模型、也知道 tool calling 和 agent 的基本概念,那接下来最值得看的问题通常不是“怎么再包一层 prompt”,而是:一个真正能跑任务的 agent,到底是怎么在代码里运转起来的。 这篇文章不从抽象定义讲起&#xff…...

AI 焦虑别乱投!3 个问题秒懂要不要养「虾」

作者 | 张辉清 责编 | 梦依丹出品 | 程序人生(ID:coder_life)当下 AI 热度居高不下,企业该如何抉择?是大举投入布局,还是保持观望?我们借以下三个问题来展开思考。AI 当下处在什么阶段&#xf…...

python实现skip-gram(跳词)示例

文章目录示例什么是跳词? 一句话,就是用中心词,去预测它周围的词。它是 Word2Vec 里最常用的一种训练方式。 示例 1、安装依赖 pip install matplotlib # 其他torch等依赖早就安装了2、创建python文件skip_gram_demo.py,代码:…...

项目介绍 MATLAB实现基于概率路图法(PRM)进行无人机三维路径规划的详细项目实例(含模型描述及部分示例代码) 专栏近期有大量优惠 还请多多点一下关注 加油 谢谢 你的鼓励是我前行的动力 谢谢支持

MATLAB实现基于概率路图法(PRM)进行无人机三维路径规划的详细项目实例 更多详细内容可直接联系博主本人 或者访问对应标题的完整博客或者文档下载页面(含完整的程序,GUI设计和代码详解) 随着无人机技术的快速发展&…...

项目介绍 MATLAB实现基于栅格地图法(Grid Map)进行无人机三维路径规划的详细项目实例(含模型描述及部分示例代码) 专栏近期有大量优惠 还请多多点一下关注 加油 谢谢 你的鼓励是我前行的动力

MATLAB实现基于栅格地图法(Grid Map)进行无人机三维路径规划的详细项目实例 更多详细内容可直接联系博主本人 或者访问对应标题的完整博客或者文档下载页面(含完整的程序,GUI设计和代码详解) 随着无人机技术的迅速…...

IntelliJ IDEA 彻底AI化!2026.1 版重磅发布,太香了

备受期待的 IntelliJ IDEA 2026.1 版本现已正式发布!本次更新带来了多项重磅功能,从 AI 智能体深度集成到主流语言框架的一流支持,全方位提升开发效率。无论您是 Java、Kotlin 开发者,还是涉及 C/C、TypeScript 的多语言项目开发者…...

解锁Visual Studio中的图标编辑:.CUR文件的编辑指南

在软件开发中,图标是用户界面设计的重要组成部分。它们不仅能增强应用程序的美观度,还能提供直观的操作指引。然而,对于那些不熟悉Visual Studio环境的开发者来说,编辑图标文件可能遇到一些障碍。本文将详细介绍如何在Visual Studio中编辑.CUR文件,以及为什么默认情况下这…...

告别重复造轮子,用快马平台一键生成OpenClaw高效工具模块

最近在做一个机器人控制项目,需要集成OpenClaw机械爪模块。传统开发方式需要从零开始写大量重复代码,效率很低。后来尝试用InsCode(快马)平台生成核心模块,效果出乎意料的好。这里分享下具体实现思路和优化点: 安全初始化模块设计…...

别再为vLLM的max_model_len报错头疼了!手把手教你用Meta-Llama-3.1-8B-Instruct跑通第一个推理

从零突破vLLM 5.0.4实战:Meta-Llama-3.1-8B-Instruct推理全流程解析 当你第一次尝试用vLLM加载Llama 3.1这样的前沿大模型时,是否曾被突如其来的max_model_len报错打得措手不及?作为专为高性能推理设计的框架,vLLM在5.0.4版本中对…...

ABAQUS模拟CFRP约束型钢再生混凝土短柱复现:‘保姆级教程‘中的材料、相互作用设置与曲线...

ABAQUS,CFRP约束型钢再生混凝土短柱论文复现 CFRP材料 相互作用的设置 曲线的调试(前期刚度以及承载力) 保姆级教程打开ABAQUS第一件事先冲杯咖啡——这玩意儿的曲线调试能让你怀疑人生。今天咱们来折腾CFRP裹着型钢再生混凝土的短柱&#xf…...

SIM4LIFE Light保姆级教程:手把手搞定第一个人体SAR值仿真(附FDTD模块避坑指南)

SIM4LIFE Light保姆级教程:手把手搞定第一个人体SAR值仿真(附FDTD模块避坑指南) 电磁场仿真在生物医学工程领域扮演着越来越重要的角色,而SIM4LIFE Light作为一款专为人体组织电磁特性研究设计的仿真软件,凭借其内置的…...

刘教链|比特币税收漏洞即将关闭,稳定币却成最大赢家

一觉醒来,BTC小幅回升至67k一线。地区冲突阴云不散,加密市场始终承压。最近美国国会又出了个新草案,叫Digital Asset PARITY Act。名字听起来很公平,追求资产平等待遇,但仔细一看,这哪里是平等,…...

seo推广如何策划

SEO推广如何策划:全面指南 在当今数字化时代,搜索引擎优化(SEO)推广已成为企业提升网站流量、增加品牌曝光的关键手段。如何有效地策划一套适合自己业务的SEO推广方案却不是件容易的事。本文将从SEO推广的基础概念、问题分析、原…...

抖音批量下载助手:三步实现全自动视频采集

抖音批量下载助手:三步实现全自动视频采集 【免费下载链接】douyinhelper 抖音批量下载助手 项目地址: https://gitcode.com/gh_mirrors/do/douyinhelper 还在为手动保存抖音视频而烦恼吗?抖音批量下载助手为你提供了一套完整的自动化解决方案&am…...

如何快速搭建你的专属Galgame社区:TouchGal一站式解决方案完整指南

如何快速搭建你的专属Galgame社区:TouchGal一站式解决方案完整指南 【免费下载链接】kun-touchgal-next TouchGAL是立足于分享快乐的一站式Galgame文化社区, 为Gal爱好者提供一片净土! 项目地址: https://gitcode.com/gh_mirrors/ku/kun-touchgal-next 你是否…...

震惊!这几款 AI 论文生成器居然能自动匹配真实参考文献,导师都惊呆了!

还在为论文参考文献瞎编、格式错乱、找不到权威文献而熬夜秃头?普通 AI 论文工具动不动就 "文献幻觉",编出一堆查无此篇的假引用,被导师一眼戳穿,直接打回重写!2026 年实测精选,这几款真正能自动…...

“证死你,证伟我”——波普尔“证伪主义”是逻辑诈骗,1+1=2才是真正的科学

“证死你,证伟我”——波普尔“证伪主义”是逻辑诈骗,112才是真正的科学摘要本文作者以技术专家立场,将波普尔证伪主义定性为“逻辑原罪”与“学术诈骗”。核心指控为六个字:“证死你”——用“不可证伪”剥夺完美理论&#xff08…...

专治写作卡点!这几款 AI 续写软件,让论文写作像呼吸一样简单

写论文最怕卡壳?大纲想破头、续写没思路、降重改到哭,还怕 AI 痕迹露馅?2026 年这几款 AI 续写软件,直击本科生、研究生核心痛点,从选题到答辩一站式搞定,让写作效率翻倍!一、PaperRed&#xff…...

破局双系统文件壁垒:WinBtrfs驱动终极应用指南

破局双系统文件壁垒:WinBtrfs驱动终极应用指南 【免费下载链接】btrfs WinBtrfs - an open-source btrfs driver for Windows 项目地址: https://gitcode.com/gh_mirrors/bt/btrfs 在Windows与Linux双系统环境中,用户常常面临跨系统文件访问的难题…...

5个高效步骤:直链技术让网盘用户实现下载速度跃升

5个高效步骤:直链技术让网盘用户实现下载速度跃升 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天翼云盘…...

运维系列【仅供参考】:【Docker】容器生命周期管理:从优雅停止到高效清理的实战技巧

【Docker】容器生命周期管理:从优雅停止到高效清理的实战技巧 【Docker】容器生命周期管理:从优雅停止到高效清理的实战技巧 摘要 1. 为什么需要关注容器生命周期管理? 2. 停止容器的艺术:从温柔到强硬 2.1 优雅停止的正确姿势 2.2 何时该用强制终止 2.3 暂停与恢复的妙用 …...

SEO_为什么你的网站需要持续进行SEO优化?

SEO优化的重要性:为什么你的网站需要持续进行SEO优化 在当前竞争激烈的互联网市场中,网站的流量和用户参与度直接影响着企业的成功与否。为什么你的网站需要持续进行SEO优化呢?SEO(搜索引擎优化)不仅是提升网站在搜索…...

Comsol 单孔激光烧蚀:探索微观世界的烧蚀奥秘

comsol单孔激光烧蚀 在材料加工等众多领域,激光烧蚀技术凭借其高精度、非接触等优势备受瞩目。而 Comsol 作为一款强大的多物理场仿真软件,为我们深入研究激光烧蚀过程提供了有力工具。今天就来聊聊 Comsol 单孔激光烧蚀那些事儿。 Comsol 仿真原理 激…...

YimMenu:GTA V体验增强工具的全方位应用指南

YimMenu:GTA V体验增强工具的全方位应用指南 【免费下载链接】YimMenu YimMenu, a GTA V menu protecting against a wide ranges of the public crashes and improving the overall experience. 项目地址: https://gitcode.com/GitHub_Trending/yi/YimMenu …...

STM32F407实战:用CubeMX+FreeRTOS+SDIO+FatFs,5分钟搞定SD卡文件读写

STM32F407实战:5分钟极速实现SD卡文件系统全流程 拿到一块STM32F407开发板时,如何快速验证SD卡文件读写功能?这套组合方案或许能帮你省下大量调试时间——CubeMX生成基础框架、FreeRTOS管理任务调度、SDIO硬件接口驱动配合FatFs文件系统&…...