c#的每个HttpClient实例都有自己的ServicePoint

本文关键字:自己的 ServicePoint 实例 HttpClient | 更新日期: 2023-09-27 18:13:59

我有如下内容

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逻辑是长时间运行。

有人能解释一下为什么这个示例似乎超过了ServicePointManager。DefaultConnectionLimit = 2?我最好的猜测是,由于我每个请求创建一个新的HttpClient, ServicePointManager正在每个请求创建一个ServicePoint对象,但从我所读到的,我认为ServicePointManager应该只创建每个独特模式和域的ServicePoint的不同实例,所以我不确定。

注意:我确实计划重用我的HttpClient实例,但是这个结果满足了我的好奇心:)。

c#的每个HttpClient实例都有自己的ServicePoint

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

我认为你的解释是错误的。因为根据框架代码,ServicePoint的创建如下所示:

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

如果你看到这个,说明没有使用hashcode来支持你的语句