我们的 dnscache 服务出现了一个问题,一两周后它的内存使用量就会变得过大(~6GB)。
重新启动服务会释放该内存,但执行 ipconfig /flushdns 却不行,ipconfig /displaydns 显示缓存中大约有 15-20 个条目。
我们已经检查过,每秒大约有 150 个 DNS 查询发生,但我认为这不会导致这个内存问题。
我曾尝试在 MSDN 上搜索修补程序或错误报告,但我只能找到对 Windows 2003 中内存泄漏的引用。有人可以建议如何继续吗?
答案1
鉴于您已经搜索过修补程序,我假设您的服务器已经更新了最新的 Windows Service Pack 并且所有更新都是最新的?这始终是最好的起点。
缓存大小为 6 GB,我们谈论的是数千万个唯一的 DNS 结果(这太荒谬了)。您的客户端不太可能进行那么多唯一的 DNS 查询。在问题的评论中,您指出应用程序每次客户端向服务器发送数据时都会执行查找。我不知道服务器上的应用程序(我假设是 Web 应用程序)是如何工作的,但我想知道是否有某个事件在每次客户端请求时创建唯一的 DNS 查询,这些查询会作为不存在的域返回。我猜想,如果 DNS 查询命中带有通配符的域,它们可能会返回有效的响应。无论哪种方式,这都可以解释巨大的缓存大小。
Ipconfig /displaydns 并不总是返回整个缓存,这可以解释为什么您只看到 15-20 个条目。
您可以(至少我可以)通过执行以下操作来确认这一点...
从 Powershell 提示符:
> ipconfig /flushdns
> [System.Net.Dns]::GetHostAddresses(“google.com”)
检查 DNS 缓存
> ipconfig /displaydns
您可能会看到 Google.com 条目。使用任务管理器记下缓存大小(在任务管理器中,找到 dnscache 服务,右键单击它,选择转到进程)。
现在运行以下命令,其中 ### 是一个很大的数字(我使用了 10,000)。请注意,我将本地 DNS 服务器设置为使用通配符响应所有 .test 子域,这样我就不会在短时间内 10,000 次访问 ISP 的 DNS 服务器。
> $i = 0
> do {[System.Net.Dns]::GetHostAddresses(“blahblahfakedomain” + $i++ + “.test”)} while ($i –lt ###)
在命令执行过程中,在任务管理器中观察缓存进程的内存使用率增长。完成后,检查缓存。您可能看不到我们刚刚生成的###查询,但DNS缓存进程尚未释放内存。
在我的实验中,我能够通过刷新 DNS 缓存来恢复内存(10,000 个查询大约为 2 MB)。我不知道为什么这对你不起作用。可能是因为缓存太大了……?
无论如何,我建议采取以下解决方法:
修改最大缓存时间和最大负缓存时间下的注册表值HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Dnscache\参数密钥每(http://support.microsoft.com/kb/318803):
修改或创建 DWord 值最大缓存时间,将其设置为较低的值,例如 3600 秒(十六进制为 0xE10)。所有值均以秒为单位指定。默认值为 1 天(86,400 秒)。
修改或创建 DWord 值最大负缓存时间,将其设置为 0。
这将导致所有记录在添加后最多一小时内从缓存中清除。负面结果(不存在的域)将根本不存储在缓存中(我已经在我的 Windows 7 桌面上确认了这一点)。
我称其为一种解决方法,因为我认为问题在于创建大量请求的任何进程。如果可以,请尝试从源头抑制大量请求。
答案2
我们运行了 Wireshark 捕获来查看正在运行的 DNS 查询,结果发现,当每个客户端向服务器发送数据时,它都会连接到另一台计算机上的 MSSQL 服务器并执行 DNS 查询以获取此 SQL 服务器的 IP 地址。
作为一种解决方法,我们已经使用 SQL 服务器 IP 地址配置了应用程序服务器,因此应用程序服务器无需查询 DNS 缓存。
然而问题仍然存在,为什么看似正常的 DNS 查询会导致 DNS 缓存中出现如此大的内存使用量。
我在这里附上了 Wire Shark 跟踪信息,以便人们能够帮助诊断问题
答案3
关于 Windows 2008 R2 上 DNS 高内存利用率的讨论很多。其中很多都指出禁用 EDNS 不会降低内存使用率。真正的问题实际上是由于 DNS 开放的端口:2500 UDP IPv4 和 2500 UDP IPv6。对于繁忙的生产 DNS 服务器来说,这是一个不错的整数,但是对于小型办公室中的内部 DNS 来说,这个数字太多了。
要减少开放端口的数量,请运行以下命令。对于内部 DNS,办公室里大约有 20 个人,100 个端口就足够了:
Dnscmd /Config /SocketPoolSize 100
命令执行后,重新启动 DNS 服务;内存消耗应该会减少。
您还可以查看已打开的端口数:
Dnscmd /Info /SocketPoolSize
答案4
不确定这是否太晚了,但我在调查一个完全不同的问题时偶然发现了这一点 - 我认为.uk 域名是导致该问题的原因。
他们继续描述说,一个简单的 regkey 修复就能解决这个问题。
http://support.microsoft.com/kb/968372
当名称解析由根提示提供时,Windows Server 2008 DNS 和 Windows Server 2008 R2 DNS 服务器可能无法解析某些顶级域中的名称查询。发生这种情况时,问题将持续存在,直到清除 DNS 服务器缓存或重新启动 DNS 服务器服务。此问题可能出现在 .co.uk、.cn 和 .br 等域中,但不限于这些域。
问题发生时,针对受影响的名称发出的 nslookup 命令将返回错误“服务器失败”。网络跟踪将显示 DNS 服务器不会向 Internet 发送此类请求的任何流量。DNS 事件日志中未报告与问题相关的任何事件。
如果将 DNS 服务器配置为使用转发器而不是根提示进行 Internet 名称解析,则不会发生此问题。