php - 什么会导致 checkdnsrr() 或 dns_get_record() 花费太长时间?

标签 php dns

$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>";

在我的开发系统(带有 AT&T 的住宅 DSL 上的 Win+XAMPP)上运行它时,我得到的时间大约为 60 毫秒

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

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

这可能是什么原因造成的?是不是 AT&T 的 DNS 服务器返回结果的速度比我的生产服务器指向的任何服务器都快?不过,20 秒似乎过长了。

更重要的是,如何修复它?

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

编辑:

我对此进行了更深入的研究。在需要 20 到 30 秒对无效域执行 DNS 检查的同一台服务器上,从控制台使用 dig 速度很快。这可能是一个重要的观点。使用 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(绝对域名规范)的请求记录。这可能需要重试几次。例如,如果您要查找 MX 记录但 FQDN 记录中不存在该记录,则可能存在 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 functions没有超时,而 dig 的默认超时是 5 seconds (尝试了几次)。

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

另请注意,如果您不想附加 resolv.conf/Windows 网络设置中的潜在搜索域,则应在域名中包含最后的 .(点),这将是如果他们有通配符,可能总是可以解析。

关于php - 什么会导致 checkdnsrr() 或 dns_get_record() 花费太长时间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14065946/

相关文章:

php - 使用它的 id 设置 Symfony2 实体表单字段

php - Guzzle 发布带有身份验证的请求

php - MySQL COUNT() + 半秒 COUNT

ssl - 在指向 EC2 实例的子域上使用 SSL

dns - 将 ".local"子域重定向到单播 DNS

ruby-on-rails - 无法从某些位置访问 Heroku 上的 Rails 服务器

php - 具有奇数日期 2012-12-10-1 错误的重复日期条目

php - 如何防止发布重复值?

java - 如何高效处理Spring Boot微服务?

dns - 如何将Kubernetes DNS用于Pod?