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

mar*_*n's 9 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>";
Run Code Online (Sandbox Code Playgroud)

在我的开发系统(在住宅DSL上使用AT + T的Win + XAMPP)运行时,我的时间大约是60 毫秒.

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

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

可能是什么导致了这个?问题是AT&T的DNS服务器返回的结果是否比我的生产服务器指向的更快?不过,二十秒似乎过度了.

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

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

编辑:

我进一步研究了这个.使用dig从控制台是服用20到30秒钟做无效域的DNS检查在同一台服务器上快速.这可能是一个重点.有效域可以使用checkdnsrr()或快速返回@dns_get_record.

作为一项临时措施,我正在寻找用@dns_get_recorddig基于函数的电子邮件有效性检查代替我写的:

// 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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

测试建议:

apple.com
apple.commmmmmmmmmm
example.com
asdfasdfasdf
Run Code Online (Sandbox Code Playgroud)

NB

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
Run Code Online (Sandbox Code Playgroud)

如果在主机上运行,​​比如说,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);
Run Code Online (Sandbox Code Playgroud)

这些中的每一个都可能失败,整个过程需要永远.

事实证明,在安全问题和广泛部署的DNS软件的建议更正下,RFC实际上涵盖了整个过程.值得一读.

And*_*eKR 10

显然,PHP DNS功能没有超时而默认的超时时间dig5秒(有几次尝试).

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

另请注意,.如果您不希望附加resolv.conf/Windows网络设置中的潜在搜索域,则应在域名中包含final (dot),如果它们具有通配符,则可能始终可解析.

  • 哇.你正好击中头部.我知道PHP DNS功能缺少超时.事实上,今天早些时候我正在挖掘PHP源代码,试图看看用超时版本做什么.我不确定你是这么想的,但你建议在域名中添加最后一段时间会产生很大的不同(参见我提出的测试页).即使像"abcdabcd"这样的垃圾域名也从**28秒变为3毫秒!**现在我想了解原因.我应该就该主题发表一个单独的问题吗? (2认同)