【问题标题】:What would cause checkdnsrr() or dns_get_record() to take too long?什么会导致 checkdnsrr() 或 dns_get_record() 花费太长时间?
【发布时间】:2012-12-13 12:12:12
【问题描述】:
$domain = 'abasdfasdfac.comlkjljkl';  // Yes, an ugly invalid domain

$start_time = microtime(true);
echo "<p>MX "; 
var_dump(checkdnsrr($domain, 'MX'));
echo "</p>";
$end_time = microtime(true);
echo "<p>run time: " . ($end_time - $start_time) . "</p>";

在我的开发系统上运行此程序时,我的时间大约为 60 毫秒(Win+XAMPP 在住宅 DSL 上 w/AT&T)。

但是,当上传到实时服务器并从那里运行时,运行时间会上升到 20 秒 范围内。

如果我改用@dns_get_record($domain, DNS_MX),结果是一样的。

这可能是什么原因造成的? AT&T 的 DNS 服务器返回结果是否比我的生产服务器指向的更快?不过,二十秒似乎有些过分了。

更重要的是,如何解决?

我将其用作电子邮件验证的最后阶段。但是,我不能让用户在 DNS 查找返回时等待 20 秒。

编辑:

我对此进行了更深入的研究。在同一台服务器上使用控制台中的dig 速度很快,需要 20 到 30 秒才能对无效域进行 DNS 检查。这可能是很重要的一点。使用checkdnsrr() 或@dns_get_record 快速返回有效域。

作为一项临时措施,我正在考虑用我写的基于dig 的函数替换@dns_get_record 在我的电子邮件有效性检查中:

// Use "dig" command to get DNS record data
// $type    ANY = Complete record
//          A   = Address Record
//          MX  = Mail Exchange Record
//          CNAME = Canonical Name Record  (http://en.wikipedia.org/wiki/Canonical_name_record)
//
//          more types: http://en.wikipedia.org/wiki/List_of_DNS_record_types
//
// $host    Domain to investigate
//
function dig_get_dns_record($type, $host) 
{ 
    $cleaned_host = escapeshellcmd($host);
    ob_start(); 
        // Note: for this to work on Windows/XAMPP "dig" has to be installed and the search path
        passthru("dig $type $cleaned_host"); 
        $lookup = ob_get_contents(); 
    ob_end_clean(); 
    //echo "<pre>" . $lookup . "</pre>";  // Remove comment to see dig output
    return $lookup; 
}   


// For the purposes of deciding if a domain is real, this checks, the MX, A and CNAME
// and returns FALSE if none are found.  If only one of the three exists we give it
// the benefit of the doubt.
//
// $host    Domain to investigate
//
function has_valid_dns($host)
{
    $result  = dig_get_dns_record("MX", $host);
    $result .= dig_get_dns_record("A", $host);
    $result .= dig_get_dns_record("CNAME", $host);
    return strpos($result, "ANSWER SECTION:") > 0;
}

虽然这会让我走出困境,但这并不是一个答案。我确信真正的问题是 Linux 服务器上的配置设置。

如果您有兴趣测试延迟,这里有一个包含一些测试的页面(网站中的表单现在受到这种延迟的影响——请不要乱用表单,除非您真的只是想注册):

编辑:链接已删除,因为它不再相关,页面将被删除

测试建议:

apple.com
apple.commmmmmmmmmm
example.com
asdfasdfasdf

注意

AndreKR 的回答让我用一个尾随周期测试这些函数,仅此一项就将响应时间从几十秒缩短到毫秒。

这解决了问题,但并没有真正回答新问题:为什么?为了完整起见,我认为添加此 Nota Bene 并根据我的研究回答该问题很重要。

我回到源头阅读了大部分RFC-1034和RFC-1035。

事实证明,就 DNS 而言,完全限定域名 (FQDN) 实际上以句点结尾。大多数对 FQDN 的引用并未解释 DNS 具有 绝对 和 相对 域名的概念。 DNS 区分它们的方式正是通过这个尾随句点。

如果 DNS 解析器看到 DNS 样式的 FQDN(带有尾随句点),它会出去并查找该 DNS FQDN(绝对域名规范)的请求记录。这可能需要重试几次。例如,如果您正在查找 FQDN 记录中不存在的 MX 记录,则可能存在 CNAME。 DNS 解析器获取 CNAME 并启动新的 DNS 查询以尝试查找 MX 记录。

如果 DNS 解析器遇到相对域名规范会怎样?换句话说,任何没有尾随句点的东西。例如:“测试”。 DNS 解析器实际上会尝试通过将一系列 DNS 后缀附加到提供的相对域名来将其转换为绝对 FQDN。例如:

@dns_get_record("abceabce.gov", DNS_MX);  // No trailing period === relative

如果在主机上运行,​​例如,www.example.com 将至少生成以下一组查询:

@dns_get_record("abceabce.gov.www.example.com", DNS_MX);
@dns_get_record("abceabce.gov.example.com", DNS_MX);
@dns_get_record("abceabce.gov.com", DNS_MX);

每一个都可能失败,整个过程需要很长时间。

事实证明,整个过程实际上都包含在A Security Problem and Proposed Correction With Widely Deployed DNS Software 下的 RFC 中。值得一读。

【问题讨论】:

  • 你试过在 php 之外进行 dns-lookup 吗?使用dig?这么慢吗?
  • @Michael:刚刚完成了一些测试。 dig 几乎可以立即返回并获得正确的结果。不知道从这里去哪里。我重新安装了 PHP,以防万一出现问题。不用找了。在实时服务器上运行 PHP 5.4.10,在测试服务器 (XAMPP) 上运行 5.4.7。
  • 在处理 POST 或 GET 请求时,我不会做这种不重要的网络工作。最好将任何内容立即存储在文件或数据库中,给用户一个响应,然后在后台处理。
  • 你指的是测试页还是更多的一般性陈述?如果他们输入了可能无效的电子邮件地址,我需要立即告诉用户,以便他们有机会编辑它。例如,有人可能会在其他真实注册时错误地键入.comm。我不知道如何在后台使用 @dns_get_record() 并且在函数需要 20 到 30 秒才能返回时仍然提供良好的反馈。
  • @martin's:您可以稍后通过电子邮件向用户发送结果;)说真的,最好发送电子邮件验证链接。即使域是有效的,也并不意味着该电子邮件地址是有效的或用户可以访问它。

标签: php dns


【解决方案1】:

显然PHP DNS functions 没有超时,而dig 的默认超时是5 seconds(多次尝试)。

此外,您的开发和生产服务器可能使用不同的 DNS 服务器来解析名称。现在一些 DNS 服务器为无效域发送一个空的答案,而一些 - 比如djbdns - 根本不发送任何答案(这很好,根据规范)。

另外请注意,如果您不希望附加来自 resolv.conf/Windows 网络设置的潜在搜索域,则应在域名中包含最后的 .(点),如果它们可能总是可解析的有一个通配符。

【讨论】:

  • 哇。你直接击中了它的头。我知道 PHP DNS 函数没有超时。事实上,今天早些时候,我正在研究 PHP 源代码,试图了解如何使用超时版本。我不确定您是否打算这样做,但是您在域名中添加最后一个句点的建议产生了巨大的差异(请参阅我放置的测试页面)。即使对于像“abcdabcd”这样的垃圾域名,时间也从 28 秒变为 3 毫秒! 现在我想了解原因。我应该就该主题发布一个单独的问题吗?
  • 至少它可能超出了这个问题的范围,但我认为在不知道您的设置/您提供网络转储的情况下无法回答这样的问题。
  • 我编辑了我的问题的结尾,以反映我在理解这个问题方面的研究。我希望它可以帮助其他人避免一天的头发拉扯。
猜你喜欢
  • 2020-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-21
  • 1970-01-01
  • 1970-01-01
  • 2014-02-16
  • 2011-12-06
相关资源
最近更新 更多