首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在并行发送HTTP请求几个小时后ServicePoint对象的大尺寸

在并行发送HTTP请求几个小时后ServicePoint对象的大尺寸
EN

Stack Overflow用户
提问于 2015-03-17 10:18:29
回答 1查看 1.7K关注 0票数 4

我们使用HttpClient并行地向远程Web发送请求:

代码语言:javascript
复制
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可以由多个线程并发调用。运行大约四个小时后,我们发现内存泄漏问题发生了,从分析工具来看,似乎有两个ServicePoint对象,其中一个相当大,大约160 MB。

据我所知,我可以看到以上代码中的一些问题:

  • 我们应该尽可能地共享HttpClient实例。在我们的例子中,请求地址和头可能会有很大的差异,所以这是我们可以做的,还是不影响太大的性能?我只想一想,我们可以准备一本字典来存储和查找HttpClient实例。
  • 我们没有修改DefaultConnectionLimit of ServicePoint,因此默认情况下,它只能同时向同一台服务器发送两个请求。如果我们将这个值改为较大的值,那么内存泄漏问题就能得到解决吗?
  • 我们还禁止HTTPS证书验证:ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };,这与问题有关吗?

由于这个问题不容易复制(需要大量的时间),我只需要一些想法,以便我可以优化我们的代码长时间运行。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-03-19 02:04:52

自己解释一下情况,以防万一别人以后也会遇到这个问题。

--首先,这不是内存泄漏,而是性能问题。

我们在虚拟机中测试我们的应用程序,我们在虚拟机上打开了代理。它通向互联网是相当缓慢的。因此,在我们的例子中,每个HTTP请求可能需要3-4秒。随着时间的推移,ServicePoint队列中将有很多连接。因此,这不是内存泄漏,这仅仅是因为前面的连接没有足够快地完成。

只需确保每个HTTP请求都不会太慢,一切都变得正常。

我们还尝试减少HttpClient 实例,以提高请求性能:

代码语言:javascript
复制
private readonly ConcurrentDictionary<HttpRequestInfo, HttpClient> _httpClients;

private HttpClient GetHttpClient(HttpRequestInfo httpRequestInfo)
{
    if (_httpClients.ContainsKey(httpRequestInfo))
    {
        HttpClient value;
        if (!_httpClients.TryGetValue(httpRequestInfo, out value))
        {
            throw new InvalidOperationException("It seems there is no related http client in the dictionary.");
        }

        return value;
    }

    var httpClient = new HttpClient { BaseAddress = new Uri(httpRequestInfo.BaseUrl) };
    if (httpRequestInfo.RequestHeaders.Any())
    {
        foreach (var requestHeader in httpRequestInfo.RequestHeaders)
        {
            httpClient.DefaultRequestHeaders.Add(requestHeader.Key, requestHeader.Value);
        }
    }

    httpClient.DefaultRequestHeaders.ExpectContinue = false;
    httpClient.DefaultRequestHeaders.ConnectionClose = true;
    httpClient.Timeout = TimeSpan.FromMinutes(2);

    if (!_httpClients.TryAdd(httpRequestInfo, httpClient))
    {
        throw new InvalidOperationException("Adding new http client thrown an exception.");
    }

    return httpClient;
}

在本例中,对于相同的服务器地址,只有请求体不同。我还重写了EqualsGetHashCode方法的HttpRequestInfo

同时,我们还设置了ServicePointManager.DefaultConnectionLimit = int.MaxValue;

希望这能帮到你。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29096513

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档