C#是否每个HttpClient实例都拥有它自己的ServicePoint

时间:2016-10-20 03:31:04

标签: c# .net http tcp httpclient

我有类似以下的内容

public async Task PostTest()
{
    using (var client = new HttpClient())
    {
        client.BaseAddress = new Uri("abc.com");
        var response = await client.PostAsync("/api/call", new StringContent("hello world"));
        //do something with response and dispose it.
        //NOTE: server is long running, so dispose is not getting called before sending other remaning requests.
    }
}

我反过来从循环中调用此方法,以便快速连续发送大量请求。

根据我读到的有关HttpClient的内容,它会将请求与特定ServicePoint对象相关联,该对象的默认ConnectionLimit值为2.由于我的所有请求都是相同的uri,只应创建一个ServicePoint对象,因此限制为两个最大并发请求(假设流水线已关闭)。

我在运行时实际看到的是,如果我在"同一时间调用我的PostTest()方法" n 次,我看到 n 在服务器的api逻辑长时间运行之前发送回任何响应之前到达服务器的请求数。

有人可以解释为什么这个示例似乎超过2的ServicePointManager.DefaultConnectionLimit?我最好的猜测是,由于我为每个请求创建了一个新的HttpClientServicePointManager每个请求都会生成一个ServicePoint个对象,但根据我的阅读,我认为ServicePointManager应该只为每个唯一的架构和域创建ServicePoint的不同实例,所以我不确定。

注意:我打算重新使用我的HttpClient实例,但这个结果使我的好奇心达到了顶峰:)。

2 个答案:

答案 0 :(得分:1)

为了防止其他人感到好奇,我稍微检查了HttpClient代码,看起来每个HttpClient实例化了HttpMessageHandler个实例。除了HttpMessageHandler定义的uri的模式和域之外,ServicePoint对象为每个实例创建一个哈希码,用于创建HttpClient个对象。

答案 1 :(得分:-1)

@ cjablonski76我相信你的解释是错误的。因为根据框架代码创建ServicePoint如下所示。

            sp = new ServicePoint(address)
            {
                ConnectionLimit = DefaultConnectionLimit,
                IdleSince = DateTime.Now,
                Expect100Continue = Expect100Continue,
                UseNagleAlgorithm = UseNagleAlgorithm
            };
            s_servicePointTable[tableKey] = new WeakReference<ServicePoint>(sp);

如果您看到这一点,则不会使用支持您的陈述的哈希码。