我们使用HttpClient
并行向远程 Web API 发送请求:
public async Task<HttpResponseMessage> PostAsync(HttpRequestInfo httpRequestInfo)
{
using (var httpClient = new HttpClient())
{
httpClient.BaseAddress = new Uri(httpRequestInfo.BaseUrl);
if (httpRequestInfo.RequestHeaders.Any())
{
foreach (var requestHeader in httpRequestInfo.RequestHeaders)
{
httpClient.DefaultRequestHeaders.Add(requestHeader.Key, requestHeader.Value);
}
}
return await httpClient.PostAsync(httpRequestInfo.RequestUrl, httpRequestInfo.RequestBody);
}
}
该 API 可以被多个线程同时调用。运行大约四个小时后,我们发现发生了内存泄漏问题,从 profiling 工具来看,似乎有两个ServicePoint
对象,其中一个相当大,大约 160 MB。
据我所知,我可以看到代码上面的一些问题:
HttpClient
我们应该尽可能地共享实例。在我们的例子中,请求地址和标头可能会有很大差异,那么这是我们可以做点什么还是不会损害太多性能?我只是想到我们可以准备一个字典来存储和查找HttpClient
实例。- 我们没有修改
DefaultConnectionLimit
ofServicePoint
,所以默认只能同时向同一个服务器发送两个请求。如果我们把这个值改大一点,内存泄漏问题就可以解决了吗? - 我们还抑制了 HTTPS 证书验证:
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
这与问题有关吗?
由于这个问题不容易重现(需要很多时间),我只需要一些想法,以便我可以优化我们的代码以长时间运行。