.Net HttpClient首次请求性能优化:如何让首请求速度追平后续请求?
如何让HttpClient首次请求速度与后续请求一致?
请求耗时日志
2023-03-30 20:48:52: 获取请求头耗时:501 2023-03-30 20:48:52: 获取请求头耗时:78 2023-03-30 20:48:52: 获取请求头耗时:68 2023-03-30 20:48:52: 获取请求头耗时:63 2023-03-30 20:48:52: 获取请求头耗时:63 2023-03-30 20:48:52: 获取请求头耗时:95
测试代码
test.Start(); headerResponse = await client.GetFromJsonAsync<ResponseHeaderViewModel>($"GenericSync/GetHeaders?tableName={tableName}&ProjectRef={projectRef}"); test.Stop(); logger.Log("The duration it took to get headers: " + test.ElapsedMilliseconds); test.Reset(); test.Start(); headerResponse = await client.GetFromJsonAsync<ResponseHeaderViewModel>($"GenericSync/GetHeaders?tableName={tableName}&ProjectRef={projectRef}"); test.Stop(); logger.Log("The duration it took to get headers: " + test.ElapsedMilliseconds); test.Reset(); test.Start(); headerResponse = await client.GetFromJsonAsync<ResponseHeaderViewModel>($"GenericSync/GetHeaders?tableName={tableName}&ProjectRef={projectRef}"); test.Stop(); logger.Log("The duration it took to get headers: " + test.ElapsedMilliseconds); test.Reset(); test.Start(); headerResponse = await client.GetFromJsonAsync<ResponseHeaderViewModel>($"GenericSync/GetHeaders?tableName={tableName}&ProjectRef={projectRef}"); test.Stop(); logger.Log("The duration it took to get headers: " + test.ElapsedMilliseconds); test.Reset(); test.Start(); headerResponse = await client.GetFromJsonAsync<ResponseHeaderViewModel>($"GenericSync/GetHeaders?tableName={tableName}&ProjectRef={projectRef}"); test.Stop(); logger.Log("The duration it took to get headers: " + test.ElapsedMilliseconds); test.Reset(); test.Start(); headerResponse = await client.GetFromJsonAsync<ResponseHeaderViewModel>($"GenericSync/GetHeaders?tableName={tableName}&ProjectRef={projectRef}"); test.Stop(); logger.Log("The duration it took to get headers: " + test.ElapsedMilliseconds); test.Reset();
问题描述
从日志可见,相同请求首次执行耗时超500ms,后续请求耗时大幅降低。由于程序对时间敏感度极高,想咨询:能否让首次请求速度与后续请求一致?当前HttpClient由IHttpClientFactory生成,调用的API部署在IIS上。
解决方案
1. 预热HttpClient连接池
首次请求慢主要是因为需要建立TCP连接、完成DNS解析,可在应用启动时主动发起预热请求,提前初始化连接:
// 在Program.cs或Startup.cs的服务配置完成后添加 var httpClient = app.Services.GetRequiredService<IHttpClientFactory>().CreateClient(); // 用HEAD请求(或轻量GET请求)触发连接初始化 await httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, "http://你的API地址/GenericSync/GetHeaders?tableName=占位符&ProjectRef=占位符"));
2. 优化HttpClient连接配置
调整HttpClientHandler的参数,减少首次连接开销:
builder.Services.AddHttpClient("YourApiClient") .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler { // 启用TCP连接复用 UseTcpPool = true, // 缩短连接超时时间(按需调整) ConnectTimeout = TimeSpan.FromSeconds(3), // 延长DNS缓存时长,避免重复解析 DnsRefreshTimeout = TimeSpan.FromHours(24), // 启用HTTP/2(若API服务器支持) SslProtocols = System.Security.Authentication.SslProtocols.Tls12 | System.Security.Authentication.SslProtocols.Tls13 });
3. 优化IIS服务器配置
从API部署端减少首次请求的初始化开销:
- 启用IIS应用程序预热功能,在应用池启动时提前初始化API服务,避免首次请求触发应用启动
- 调整IIS的连接保持设置,确保TCP连接可被复用
- 开启IIS的HTTP/2支持,提升连接传输效率
4. 缓存API请求结果(按需)
如果请求的头数据不频繁变更,可在客户端首次请求后缓存结果,后续直接使用缓存,彻底消除请求耗时:
// 用内存缓存存储请求结果 private readonly IMemoryCache _cache; private const string HeaderCacheKey = "GenericHeaders_{0}_{1}"; public async Task<ResponseHeaderViewModel> GetHeaders(string tableName, string projectRef) { var cacheKey = string.Format(HeaderCacheKey, tableName, projectRef); if (_cache.TryGetValue(cacheKey, out ResponseHeaderViewModel cachedResult)) { return cachedResult; } var result = await _httpClient.GetFromJsonAsync<ResponseHeaderViewModel>(...); _cache.Set(cacheKey, result, TimeSpan.FromMinutes(30)); // 按需设置缓存时长 return result; }
内容的提问来源于stack exchange,提问作者DemiGod
相关产品推荐
相关产品推荐

