web-dev-qa-db-ja.com

Javaで解決するノンブロッキング(非同期)DNS

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

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

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

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

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

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

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

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

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

29
GreyCat

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

5
andersoj

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

5
valodzka

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

3
Lawrence Dol

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

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

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

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

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

2
philwb

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

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

1
vladimir e.

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

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

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

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

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

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

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

0
Aravind Yarram