HttpClient - DNS changes are NOT honoured(HttpClient-不支持对DNS的更改)
问题描述
我已经阅读了一些文章以及使用静态HttpClient的陷阱和解决方案。其中一篇文章是-http://byterot.blogspot.ca/2016/07/singleton-httpclient-dns.html
我已经实现了解决方案,并希望进行测试以确保本文提出的内容能够实际工作。
以下是我们试图避免的代码:
Task.Run(async () =>
{
using (var httpClient = new HttpClient(new ApiHandler()))
{
var httpResponse = await httpClient.GetAsync("https://test.com/api/Tiers");
var result = await httpResponse.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}).ContinueWith(async task =>
{
await Task.Delay(5000);
using (var httpClient = new HttpClient(new ApiHandler()))
{
var httpResponse = await httpClient.GetAsync("https://test.com/api/Tiers");
var result = await httpResponse.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}).ContinueWith(async task =>
{
await Task.Delay(10000);
using (var httpClient = new HttpClient(new ApiHandler()))
{
var httpResponse = await httpClient.GetAsync("https://test.com/api/Tiers");
var result = await httpResponse.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
});
当我在fiddler中查看流量时:
行为与预期一致。每次创建和处置都会强制在请求和响应完成时建立连接。
正确和建议使用HttpClient的方法是将其设置为静态:
private static readonly HttpClient HttpClient = new HttpClient(new ApiHandler());
static void Main()
{
ServicePointManager
.FindServicePoint(new Uri("https://test.com"))
.ConnectionLeaseTimeout = 1000; // 1 second
ServicePointManager.DnsRefreshTimeout = 1000; // 1 second
Task.Run(async () =>
{
var httpResponse = await HttpClient.GetAsync("https://test.com/api/Tiers");
var result = await httpResponse.Content.ReadAsStringAsync();
Console.WriteLine(result);
}).ContinueWith(async task =>
{
await Task.Delay(5000); // delay 5 seconds
var httpResponse = await HttpClient.GetAsync("https://test.com/api/Tiers");
var result = await httpResponse.Content.ReadAsStringAsync();
Console.WriteLine(result);
}).ContinueWith(async task =>
{
await Task.Delay(10000); // delay 10 seconds
var httpResponse = await HttpClient.GetAsync("https://test.com/api/Tiers");
var result = await httpResponse.Content.ReadAsStringAsync();
Console.WriteLine(result);
});
Console.ReadKey();
}
我预计其行为与上图相同,但它看起来如下所示:
如果我随后添加HttpClient.DefaultRequestHeaders.ConnectionClose = true;
,我会得到所需的结果,但这是我们要避免的-对于创建连接的每个请求响应。
那么在Fiddler中我想要的结果是正确的吗?或者我在设置ConnectionLeaseTimeout
和/或DnsRefreshTimeout
时遗漏了什么?我真的很想测试这个行为,并确保在ServicePointManager
上设置这些属性可以解决HttpClient静态实例的已知DNS问题。
推荐答案
将自身注册为代理。默认情况下,它监听127.0.0.1、端口8888。因此,要为您的案例获取正确的服务点对象,您必须执行以下操作:
ServicePointManager.FindServicePoint(
new Uri("https://test.com"),
new WebProxy(new Uri("http://127.0.0.1:8888")))
.ConnectionLeaseTimeout = 1000; // 1 second
现在您将看到正确的结果。请注意,它不会完全像您预期的那样。第一个请求将打开新连接。即使已过5秒,第二个请求也不会打开新连接。相反,它将在请求时设置Connection: close
头,指示应该关闭连接。然后,下一个请求(第三个)最终将发起新的连接。据我所知,这是ConnectionLeaseTimeout
的预期行为。
这篇关于HttpClient-不支持对DNS的更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:HttpClient-不支持对DNS的更改
- C# 通过连接字符串检索正确的 DbConnection 对象 2022-01-01
- 使用 rss + c# 2022-01-01
- 带问号的 nvarchar 列结果 2022-01-01
- 是否可以在 .Net 3.5 中进行通用控件? 2022-01-01
- CanBeNull和ReSharper-将其用于异步任务? 2022-01-01
- Azure Active Directory 与 MVC,客户端和资源标识同一 2022-01-01
- 在 C# 中异步处理项目队列 2022-01-01
- Windows 喜欢在 LINUX 中使用 MONO 进行服务开发? 2022-01-01
- 为什么 C# 中的堆栈大小正好是 1 MB? 2022-01-01
- 在 LINQ to SQL 中使用 contains() 2022-01-01