3

Java で多数 (数十万) のドメインを IP アドレスに解決する必要があります。少数の場合は使用InetAddress.getByName()可能ですが、大量に使用するには遅くはありません (おそらく、一度に 1 つの要求を DNS サーバーに送信し、応答を待ってから次の要求に進むためです)。

多数のドメインを解決するために必要な時間を短縮する、より効率的な方法 (DNS サーバーに一括で送信するなど) はありますか?

fmucar のリクエストで、よりマルチスレッドのアプローチを試すために使用するコードを追加しています。

Set<String> ips = Collections.synchronizedSet(new HashSet<String>());
int i = 0;
List<Set<String>> sets = new ArrayList<Set<String>>();
for (String host : domains) {
    if (i++ % 5 == 0) {
        sets.add(new HashSet<String>());
    }
    Set<String> ipset = sets.get(sets.size()-1);
    ipset.add(host);
}
for (Set<String> ipset : sets) {
    Thread t = new Thread(new DomainResolver(ips, ipset));
    t.start();
}

スレッドあたり 250 で、1 分あたり約 700 の結果がピークに達しました。これは、以前よりは改善されましたが (<300)、何十万もの解決が必要な場合にはまだそれほど優れていませんでした。スレッドごとにわずか 5 に下げると、これが 1 分あたり数千まで大幅に高速化されます。ただし、これは明らかに非常識な量のスレッドを作成するため、現在、Cで解決してhttp://www.chiark.greenend.org.uk/~ian/adns/を利用することを調査しています

4

2 に答える 2

2

DNS 実装の RFC によると、以下に定義されているように、一度に 1 つの質問のみを行うことができます。

4.1.2. 質問セクションの形式

質問セクションは、ほとんどのクエリで「質問」を運ぶために使用されます。つまり、質問内容を定義するパラメーターです。このセクションには、QDCOUNT (通常は 1) のエントリが含まれており、それぞれ次の形式になっています。

                                1  1  1  1  1  1
  0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                                               |
/                     QNAME                     /
/                                               /
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                     QTYPE                     |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                     QCLASS                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

どこ:

QNAME 一連のラベルとして表されるドメイン名。各ラベルは、長さのオクテットとそれに続くその数のオクテットで構成されます。ドメイン名は、ルートのヌル ラベルの長さゼロのオクテットで終了します。このフィールドはオクテットの奇数である可能性があることに注意してください。パディングは使用されません。

QTYPE クエリのタイプを指定する 2 オクテット コード。このフィールドの値には、TYPE フィールドに有効なすべてのコードと、複数のタイプの RR に一致する可能性のあるより一般的なコードが含まれます。

Mockapetris [Page 28] RFC 1035 ドメインの実装と仕様
1987 年 11 月

QCLASS クエリのクラスを指定する 2 オクテット コード。たとえば、インターネットの QCLASS フィールドは IN です。....

ただし、独自のキャッシュを維持し、バルク転送をサポートするカスタム [非常にありそうもない] リゾルバーを取得する可能性があります。存在するかどうかはわかりませんが。多分あなたはそれを書くことができます:) ...リゾルバの詳細については、このRFCのセクション5を見てください

最も簡単な解決策は、前に提案したようにスレッドを使用することです。

編集: 私が推測する話の教訓は、DNS サーバーは一括要求を受け入れるように設計されていないということです。そうしないと、攻撃者が単一の DNS サーバーから過剰な情報を簡単に要求できる可能性があるため、これは理にかなっています。

于 2012-05-01T15:21:08.037 に答える
1

java.util.concurrent.* クラスを使用してマルチスレッド アプリを作成し、結果を待たずに複数のクエリを実行できます。

See ExecutorService, Runnable, Callable, Future, Thread ... classes.

チュートリアルが初めての場合は、チュートリアルを読むことをお勧めします。

eg. You can use a `BlockingQueue`, and producer-consumer pattern.

アプリの一部が Callable オブジェクトの作成を開始し、それらが利用可能になったときに結果を BlockingQueue に配置し、別の部分が BlockingQueue から結果を取得してファイルに書き込む可能性があります。

編集1:サンプル:

ExecutorService threadExecutor = Executors.newFixedThreadPool(50);
for(....){
  Runnable thread = new Thread(new DomainResolver(ips, ipset));
  threadExecutor.execute(thread);
}

一度に複数のスレッドを作成して開始する代わりに、いつでも最大で 50 のスレッドを受け入れるエグゼキューター (上記の編集を参照) サービスに実行タスクを委任します。最適なスレッド数を見つける必要があります。スレッドが多すぎると、ほとんどの CPU サイクルがスレッドの切り替えに使用されます。平均値が低すぎると、DNS サーバーが結果を返すのを待って CPU サイクルが浪費されます

于 2012-05-01T14:58:10.577 に答える