【问题标题】: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-1034RFC-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
相关资源
最近更新 更多