checkdnsrr()またはdns_get_record()に時間がかかる原因は何ですか?

$domain = 'abasdfasdfac.comlkjljkl'; //Yes, an ugly invalid domain

$start_time = microtime(true);
echo "
MX "; var_dump(checkdnsrr($domain, 'MX')); echo "

"; $end_time = microtime(true); echo "
run time: " . ($end_time - $start_time) . "

";

I am getting times in the order of 60 milliseconds when running this on my development system (Win+XAMPP on residential DSL w/AT&T).

しかし、ライブサーバーにアップロードしてそこから実行すると、実行時間は20秒のの範囲に上がります。

代わりに @dns_get_record($ domain、DNS_MX)を使用した場合の結果は同じです。

What could be causing this? Is is a matter of AT&T's DNS servers returning with a result faster than whatever my production server is pointing to? Still, twenty seconds seems excessive.

もっと重要なのは、それをどうやって修正するのか?

私は電子メールの検証の最終段階としてこれを使用しています。しかし、DNSルックアップが返っている間、私はユーザーに20秒間待たせることはできません。

編集:

私はこれをもう少し見てきました。コンソールからの dig の使用は、無効なドメインのDNSチェックを行うのに20〜30秒かかっている同じサーバー上で高速です。それは重要なポイントかもしれません。有効なドメインは、 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 "
" . $lookup . "
"; //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サーバーの構成設定だと確信しています。

遅延のテストに興味がある場合は、ここにいくつかのテストがあるページがあります(フォームにはこの遅れがあります。実際に申し込みをしない限り、フォームが混乱しないようにしてください)。

編集: link removed as it is no longer relevant and page will be deleted

テストの提案:

apple.com
apple.commmmmmmmmmm
example.com
asdfasdfasdf

NB

AndreKRの答えでは、これらの関数を後続の期間でテストすることができ、それだけで応答時間が数十秒から数ミリ秒に短縮されました。

これは問題を解決しましたが、新しい質問には本当に答えませんでした。なぜですか?完全性のために私はこの Nota Bene を追加し、私の研究に基づいてその質問に答えることが重要です。

私はソースに戻って、ほとんどの RFC-1034 および RFC-1035 をご覧ください。

DNSに関する限り、完全修飾ドメイン名(FQDN)は実際には期間で終わることが判明しています。 DNSが絶対相対というドメイン名の概念を持っていることは、FQDNのほとんどの記述では説明されていません。 DNSがそれらを区別する方法は、正確にこの末尾の期間によって行われます。

DNSリゾルバがDNSスタイルのFQDN(末尾にピリオドを含む)を見た場合、DNSリゾルバはそのDNS FQDN(絶対ドメイン名の指定)の要求されたレコードを探し出します。これには数回の再試行が必要な場合があります。たとえば、MXレコードを探していて、FQDNレコードに存在しない場合は、代わりにCNAMEが存在する可能性があります。 DNSリゾルバはCNAMEを取得し、新しいDNS問い合わせを開始してMXレコードを検索します。

DNSリゾルバが相対的なドメイン名の指定に遭遇すればどうなるでしょうか?言い換えれば、後の期間がないもの。たとえば、 "testing"とします。 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);

これらのそれぞれは失敗する可能性があり、プロセス全体が永遠にかかる。

プロセス全体が実際にはRFCの中で、セキュリティ問題と広範囲に配備されたDNSソフトウェアの提案された修正をご覧ください。それは読む価値がある。

9
nl ru de
@マーティン:あなたはいつも結果を後で電子メールで送ることができます;)真剣には、電子メールの確認リンクを送る方がいいでしょう。ドメインが有効であっても、電子メールアドレスまたはユーザーがアクセスできることを意味するものではありません。
追加された 著者 Wesley Murch,
@マイケル:ちょうどいくつかのテストを実行完了しました。 dig はすぐに適切な結果を返します。ここからどこに行くのかわからない。何かが乱暴になった場合に備えてPHPを再インストールしました。変化なし。ライブサーバーでPHP 5.4.10を実行し、テストサーバー(XAMPP)で5.4.7を実行しています。
追加された 著者 martin's,
テストページまたはそれ以上の一般的な声明を参照していますか?ユーザーに、無効な可能性のあるメールアドレスを入力した場合は、編集の機会を与えるために、すぐにその旨を伝える必要があります。たとえば、他の人の本物のサインアップを誤って .comm と入力すると、バックグラウンドで @dns_get_record()を使用する方法がわかりませんが、返される関数が20〜30秒かかると、良いフィードバックが得られます。
追加された 著者 martin's,
今、面白かったです。ありがとう。
追加された 著者 martin's,
私はPOSTやGETリクエストを処理している間、この種の重要ではないネットワークの処理をしません。ファイルやデータベースにすぐに何かを保存し、ユーザーに応答を与え、後でバックグラウンドで処理します。
追加された 著者 mvds,
PHPの外でDNS検索を試みましたか? dig を使用していますか?それは遅いですか?
追加された 著者 Michael,

1 答え

明らかに PHPのDNS機能にはタイムアウトはありませんが、 dig code>は 5秒です(複数試行)。

さらに、開発サーバーとプロダクションサーバーは、名前を解決するためにおそらく異なるDNSサーバーを使用します。いくつかのDNSサーバは、無効なドメインと djbdns のような空の回答を送信します。これは仕様上問題ありません)。

resolv.conf/Windowsのネットワーク設定から潜在的な検索ドメインを追加したくない場合は、最後の(ドット)をドメイン名に含める必要があることにも注意してください。ワイルドカードがある場合

10
追加された
少なくともそれはおそらくこの質問の範囲外ですが、ネットワークダンプを提供していることを知らずにこのような質問に答えられるとは思いません。
追加された 著者 AndreKR,
ワオ。あなたは頭の上でそれを打つ。私は、PHPのDNS機能のタイムアウトの欠如について知っていた。実際には、今日の私はPHPソースコードを掘り下げて、タイムアウトのあるバージョンを実行するのに何が必要かを見ていました。私はあなたがこのように意図しているかどうかは確かではありませんが、ドメイン名に最後のピリオドを追加することをお勧めします(テストページを見てください)。 "abcdabcd"のような迷惑なドメイン名でも、 28秒から3ミリ秒に短縮されました!理由を理解したいと思います。私はそのトピックについて別の質問を投稿すべきですか?
追加された 著者 martin's,
この問題を理解するための研究を反映するために、質問の終わりを編集しました。私はそれが他の人が髪を引っ張る日を避けるのに役立つことを願っています。
追加された 著者 martin's,
PHP - 日本のコミュニティ [ja]
PHP - 日本のコミュニティ [ja]
4 参加者の

このグループではPHPについて話します。 パートナー:kotaeta.com