Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将不同URL的HTTP请求名称解析缓存到同一主机。可能的_C#_Networking_.net Core_Dns_.net 5 - Fatal编程技术网

C# 将不同URL的HTTP请求名称解析缓存到同一主机。可能的

C# 将不同URL的HTTP请求名称解析缓存到同一主机。可能的,c#,networking,.net-core,dns,.net-5,C#,Networking,.net Core,Dns,.net 5,问题摘要:我需要调用HTTP资源A,同时使用同一主机上对资源B的上一个HTTP请求的名称解析 案例1。对同一资源的连续调用在第一次调用后产生更快的结果。 探查器告诉我,第一次调用和第二次调用之间的区别在于DNS名称解析(GetHostAddresses) 案例2。对同一主机上不同资源的连续调用会产生相同的延迟。 探查器告诉我,它们都会调用DNS名称解析 var request = (HttpWebRequest)WebRequest.Create("https://www.someh

问题摘要:我需要调用HTTP资源A,同时使用同一主机上对资源B的上一个HTTP请求的名称解析

案例1。对同一资源的连续调用在第一次调用后产生更快的结果。
探查器告诉我,第一次调用和第二次调用之间的区别在于DNS名称解析(GetHostAddresses)

案例2。对同一主机上不同资源的连续调用会产生相同的延迟。 探查器告诉我,它们都会调用DNS名称解析

var request = (HttpWebRequest)WebRequest.Create("https://www.somehost.com/resources/a.txt");
using (var response = (HttpWebResponse)request.GetResponse()) {}

var request = (HttpWebRequest)WebRequest.Create("https://www.somehost.com/resources/b.txt");
using (var response = (HttpWebResponse)request.GetResponse()) {}
我想知道为什么第二次呼叫不能从第一次呼叫开始使用DNS缓存?它是同一个主机

主要问题是——如何改变这一点


编辑上述行为也涵盖了HttpClient类的使用。这似乎是我使用的少数Web服务器所特有的,而且这个问题不会发生在其他服务器上。我不知道具体发生了什么,但我怀疑有问题的Web服务器(Amazon CloudFront和Akamai)会在服务完成后强制关闭连接,而忽略我的请求保持活动标题。我现在要结束这个问题,因为不可能有意识地提出一个问题。

您的问题对于
System.Net.Http.HttpClient
不存在,请尝试一下。它可以重用现有连接(此类调用不需要DNS缓存)。看起来这正是你想要实现的。作为奖励,它支持HTTP/2(可以通过
HttpClient
实例创建中的属性分配启用)

WebRequest
是一个古老的概念,微软不推荐它进行新的开发。在.NET5中,HttpClient的速度相当快(两倍?)

为每个应用程序创建一次
HttpClient
实例()

private static readonly HttpClient=new HttpClient();
模拟你的要求。注意
await
仅在标记为
async
的方法中可用

string text = await client.GetStringAsync("https://www.somehost.com/resources/b.txt");
您还可以一次执行多个请求,而不产生并发线程

string[]url=新字符串[]
{ 
"https://www.somehost.com/resources/a.txt",
"https://www.somehost.com/resources/b.txt"
};
列表任务=新列表();
foreach(url中的字符串url)
{
添加(client.GetStringAsync(url));
}
string[]results=等待任务.WhenAll(任务);
如果您不熟悉异步编程,例如
async/await
,请从开始

您还可以设置一次处理请求的数量限制。让我们执行相同的请求1000次,一次最多10个请求

static async Task Main(字符串[]args)
{
秒表sw=新秒表();
字符串url=”https://www.somehost.com/resources/a.txt";
使用信号量slim信号量=新信号量slim(10);
列表任务=新列表();
sw.Start();
对于(int i=0;i<1000;i++)
{
wait semaphore.WaitAsync();
添加(GetPageAsync(url,信号量));
}
string[]results=等待任务.WhenAll(任务);
sw.Stop();
WriteLine($“经过:{sw.elapsemiliseconds}ms”);
}
专用静态异步任务GetPageAsync(字符串url、信号量LIM信号量)
{
尝试
{
返回wait client.GetStringAsync(url);
}
最后
{
semaphore.Release();
}
}

您可以测量时间。

DNS应该被缓存。如果可能的话,在不同的HttpWebRequests之间,连接甚至保持打开状态并重复使用。您是否为您的用户帐户设置了web代理?如果您有一个公司代理,它实际上可能会为每个地址执行一些javascript,以检查它是否应该通过代理。我不确定计算是否被缓存。没有代理。我认为问题在于http请求池。到资源A的连接在第二次请求到资源A时被重用。因此第二次没有名称解析。我错误地认为连接“自动”被重用。但是关于DNS缓存我是对的。当我在同一台主机上创建两个对不同文件的httpwebrequests时,一个接一个,只执行一个DNS查找。您可以自己验证这一点,方法是为System.Net.Sockets启用详细跟踪并查找“Entering DNS::TryInternalResolve”。否。。不可能是真的。你是在.NET5中做的吗?如果您查看图片上的调用堆栈-有
HttpConnectionPool
class-这个类将套接字保持打开15秒(通过试用发现)。因此,如果您调用host/a和host/a,则第二次调用的速度要快得多,因为它不需要名称解析(因为从第一次调用开始,套接字仍处于打开状态)。。相反,如果您调用主机/a和主机/b—都调用DNS名称解析—那么DNS调用在任何情况下都不会被缓存!如果你确定我错了,请用剪掉的代码发布答案,我会测试它。对不起,我是在4.8中做的。让我想一想我到底是如何在5:)中追踪东西的:谢谢。非常慷慨的回答。我尝试了三种方式——httpwebrequest、webclient和httpclient(每个应用一个实例是)。所有人都表现出同样的问题。让我试着编写一个可用的代码,这样您就可以自己查看了。我认为http请求池缓存的方式与sql连接池缓存的方式相同,即缓存完全相同的字符串。所以a.txt和b.txt将被缓存为两个不同的连接。我将接受你的答案,即使它在我的特殊情况下没有帮助(参见编辑)。看起来你是对的——有些Web服务器的行为和你描述的一样(和我预期的一样)。但是我需要的服务器——它们没有。HttpClient与否…@BoppityBop谢谢。jfyi,
HttpWebRequest
WebClient
使用相同的底层旧HTTP引擎
HttpClient
由modern
SocketsHttpHandler
@BoppityBop提供动力
HttpWebRequest
为每个实例创建新的
HttpClient
。这意味着每个请求都有一个新的
HttpClientHandler
,这意味着不能重用连接。@BoppityBop顺便说一句,试试HTTP/2,它可以修复关闭的连接
string text = await client.GetStringAsync("https://www.somehost.com/resources/b.txt");