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);
}
});
当我在提琴手中查看流量时:
行为符合预期.当请求和响应完成时,每个create和dispose都会强制建立一个连接.
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问题.
解决方法:
Fiddler将自己注册为代理.默认情况下,它侦听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的了解而言,这是预期的行为.
标签:testing,dotnet-httpclient,c 来源: https://codeday.me/bug/20191110/2014750.html