【问题标题】:How do I clear System.Net client DNS cache?如何清除 System.Net 客户端 DNS 缓存?
【发布时间】:2011-11-08 19:21:16
【问题描述】:

我在更改 HOSTS 文件时使用 .NET WebRequest。我观察到 System.Net 不尊重这些更改 - 我怎样才能做到这一点?

我有多个服务器负载平衡在一个主机名后面,比如说“example.com”。我想分别针对其中的几个,所以我的程序将在向 example.com 发送请求之前在我的 HOSTS 文件中硬编码机器特定的 IP 地址:

163.56.0.34  example.com

对于第一个服务器和第一个请求,这工作正常。然后我的程序再次更改 HOSTS 文件:

163.56.0.48  example.com

然后我创建了一个新的 HttpWebRequest。当我发送这个时,我可以在 NETMON 中观察到它转到第一个 IP 地址 (163.56.0.34) 而不是预期的第二个。

使用断点和调试跟踪,我验证了每次都将正确的值写入 HOSTS 文件。当我尝试从浏览器或其他程序访问 example.com 时,它确实尊重 HOSTS 文件并转到第二个 IP 地址。

使用 NETMON,我已经验证请求会直接发送到所示的 IP 地址;没有 HTTP 代理。

由于其他所有内容都遵循更改后的 HOSTS 文件,因此我强烈怀疑 System.Net 基础架构已经缓存了 example.com 的 DNS 主机 IP 关联。但是,我找不到对此缓存的引用,并且不知道没有办法刷新或关闭它。

我欢迎有关处理缓存的说明、有关可能导致这些症状的其他原因的建议或其他可能有用的建议诊断步骤。

【问题讨论】:

    标签: c# .net dns system.net hosts-file


    【解决方案1】:

    我终于从 MSDN 中找到了修复此问题的晦涩命令:

    ServicePointManager.DnsRefreshTimeout = 0;
    

    当我解开我之前尝试过的所有奇怪的事情时,我发现了另一个我需要的设置以及上面的设置;在请求对象上,关闭 keep-alive:

    request.KeepAlive = false;
    

    【讨论】:

    • 将 KeepAlive 设置为 false 将导致对每个请求进行 TCP 握手。您可以通过管理 ServicePoint.ConnectionLeaseTimeout 来实现中间立场,这样您就可以重用一些连接,同时仍然检查 DNS 以了解重新连接时可能发生的变化。
    • 对于使用 WCF ClientBase 而不是 HttpWebRequest 或 WebClient stackoverflow.com/a/6535452/836376 使用肥皂服务的人@
    【解决方案2】:

    可以肯定的是一个迟到的答案,但我发现这个解决方案比接受的答案更好。在我的场景中,我正在测试 SQL 连接,但我无法应用现有答案,因为我没有要设置的 request.KeepAlive

    This page by Brian Mancini(“derp turkey”)详细介绍了他清除 DNS 缓存的冒险经历。给他完整的道具,我只是在这里添加他的解决方案:

    public class DnsUtils  
    {        
        [DllImport("dnsapi.dll", EntryPoint="DnsFlushResolverCache")]
        static extern UInt32 DnsFlushResolverCache();
    
        [DllImport("dnsapi.dll", EntryPoint = "DnsFlushResolverCacheEntry_A")]
        public static extern int DnsFlushResolverCacheEntry(string hostName);
    
        public static void FlushCache()
        {
            DnsFlushResolverCache();
        }
    
        public static void FlushCache(string hostName)
        {
            DnsFlushResolverCacheEntry(hostName);
        }
    }
    

    【讨论】:

    • 非常感谢伙计!
    【解决方案3】:

    如果你想保持 DnsRefreshTimeout > 0,那么你可以通过调用来更新缓存:

    System.Net.Dns.GetHostEntry("example.com");
    

    【讨论】:

    • 基于 Ian's answer 中引用的 Brian Mancini(“derp turkey”)博客页面,GetHostEntry() 使用缓存。因此,这不是确保为该主机名清除缓存条目的方法。
    【解决方案4】:

    您可以使用 System.Diagnostics.Process 启动 ipconfig /flushdns

    【讨论】:

    • 我试过了,但没有用 - 它刷新了机器的 DNS 缓存,但没有刷新 System.Net 的进程级缓存。
    • 类似“你可以重新启动服务器”的建议。
    • 哈哈——重装windows!
    猜你喜欢
    • 2011-07-12
    • 1970-01-01
    • 1970-01-01
    • 2014-07-02
    • 2020-09-07
    • 1970-01-01
    • 2012-01-10
    • 1970-01-01
    • 2023-03-13
    相关资源
    最近更新 更多