30

JavaでDNSクエリ(ホスト名でIPを取得)を非ブロッキング方式で非同期に解決する(つまり、ステートマシン、1クエリ= 1スレッドではない)クリーンな方法はありますか?同時に数万のクエリを実行したいのですが、何万ものスレッドを実行しません)?

私がこれまでに見つけたもの:

  • 標準InetAddress.getByName()の実装はブロッキングであり、標準のJavaライブラリには非ブロッキングの実装がないように見えます。
  • DNSを一括して解決することで同様の問題が発生しますが、見つかった唯一の解決策はマルチスレッドアプローチ(つまり、1つのスレッドが特定の瞬間に1つのクエリのみを処理する)であり、実際にはスケーラブルではありません。
  • dnsjavaライブラリもブロックのみです。
  • 2006年にさかのぼるdnsjavaには古代の非ブロッキング拡張機能があり、したがって、Futureパラダイムの使用や、残念ながら、非常に限定されたキューのみの実装など、最新のJava同時実行機能が欠けています。
  • dnsjnioプロジェクトもdnsjavaの拡張機能ですが、スレッドモデル(つまり、1クエリ= 1スレッド)でも機能します。
  • asyncorgは、この問題を対象としてこれまでに見つけた最善の解決策のようですが、 次のようになります。
    • これも2007年のもので、見捨てられたように見えます
    • ほとんどすべてのドキュメント/javadocが不足しています
    • Funクラスなどの非標準的な手法をたくさん使用します

私が見逃した他のアイデア/実装はありますか?

明確化。かなり大量の(1日あたり数TB)ログがあります。すべてのログ行には、インターネット上のほぼどこからでも使用できるホスト名があります。さらに統計を計算するには、そのホスト名のIPアドレスが必要です。行の順序は実際には重要ではないので、基本的に、私の考えは2つのスレッドを開始することです。最初に行を反復処理します。

  • 行を読み取り、解析し、ホスト名を取得します
  • 指定されたホスト名を解決するためにDNSサーバーにクエリを送信し、回答をブロックしないでください
  • 行とDNSクエリソケットハンドルをメモリ内のバッファに保存します
  • 次の行に移動

そして、次の2番目のスレッド:

  • DNSサーバーがクエリに応答するのを待ちます(epoll/ kqueuelikeテクニックを使用)
  • 答えを読んで、それがバッファ内のどの行にあったかを見つけてください
  • 解決されたIPを含む行を出力に書き込みます
  • 次の答えを待つことに進みます

Perlでの単純なモデル実装はAnyEvent、私の考えが一般的に正しく、この方法で1秒あたり15〜20Kクエリのような速度を簡単に達成できることを示しています(単純なブロッキング実装は、比較のために1秒あたり2〜3クエリのようになります)。これは4桁の違いのようなものです)。今、私はJavaで同じものを実装する必要があります-そして私は自分のDNS実装の展開をスキップしたいと思います;)

4

6 に答える 6

5

MINA上にDNSを実装したApacheDirectoryServicesがあなたが探しているものかもしれません。JavaDocsおよびその他の便利なガイドは、そのページの左側のサイドバーにあります。

于 2012-08-18T00:49:51.887 に答える
5

nettyでノンブロッキングDNSに関する作業がいくつかありますが、まだ進行中の作業であり、おそらく5.0でのみリリースされる予定です。

于 2013-06-03T15:55:48.090 に答える
3

基本ソケットサポートを使用して生のUDPの上に、またはNIOチャネルを使用してTCPの上に、DNSクライアントプロトコルを自分で実装する必要があると思います。

于 2012-08-18T00:40:54.097 に答える
2

私はあなたの質問に対する答えを持っていません(あなたが望む非同期モードで動作するDNSライブラリがあるかどうかはわかりません)そしてこれはコメントするには長すぎます。

ただし、完全なDNSハンドラーを自分で作成しなくても、非同期のものをすばやく作成できるはずです。警告、私はこれを行っていないので、私はすべて間違っている可能性があります。

dnsjavaコードから始めて、送信側と受信側の両方のメソッドを提供する独自のリゾルバーを実装できるようにする必要があります。SimpleResolverをチェックして、sendメソッドを見てください。このメソッドを2つのメソッドに分割できる必要があります。1つは、TCPClientまたはUDPClientのいずれかに呼び出しまで実行されるリクエストを送信するためです(説明したように、この時点で実際のネットワーク送信を処理します。最初のスレッドで)、および受信する1つ。これは、ソケット読み取りへの応答として2番目のスレッドによって呼び出され、応答の解析を処理します。SimpleResolverからすべてのコードをコピーする必要がある場合があります(必要なプライベートメソッドがたくさんあり、ライセンスで許可されています)、または、独自のバージョンを作成して、クラスパスのjarファイルの前にロードするか、問題のメソッドへの道を反映してアクセス可能に設定することができます

nettyまたはminaを使用して、ネットワーククライアント側をすばやく構築できます。ドキュメントにはnettyが好きです。

もしあなたがこの道を進んで、それをオープンソースにすることができる/したいのなら、私はあなたがトラブルに巻き込まれた場合に助けるために少し時間を取っておくことができます。

于 2012-08-20T13:27:18.863 に答える
1

Linuxには非同期DNSルックアップ機能があります:http://www.imperialviolet.org/2005/06/01/asynchronous-dns-lookups-with-glibc.html

Linuxを使用している場合は、それをいくつかのJNIでラップする必要があります。

于 2012-08-23T10:44:30.943 に答える
-1

複数のオプションがあります

オプション1:Java5エグゼキュータ

  1. 固定スレッドプール:Executors.newFixedThreadPool(int)
  2. Future:Futureは、非同期計算の結果を表します。計算が完了したかどうかを確認し、その完了を待機し、計算結果を取得するためのメソッドが提供されています。

オプション2:MessageListenerを使用したJMS

  1. JMSプロバイダーなどへの依存が必要です。

オプション2:アクターベースのフレームワーク

これでこれをうまくスケーリングできます。Akkaを見てください

于 2012-08-15T22:44:38.517 に答える