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
/kqueue
likeテクニックを使用) - 答えを読んで、それがバッファ内のどの行にあったかを見つけてください
- 解決されたIPを含む行を出力に書き込みます
- 次の答えを待つことに進みます
Perlでの単純なモデル実装はAnyEvent
、私の考えが一般的に正しく、この方法で1秒あたり15〜20Kクエリのような速度を簡単に達成できることを示しています(単純なブロッキング実装は、比較のために1秒あたり2〜3クエリのようになります)。これは4桁の違いのようなものです)。今、私はJavaで同じものを実装する必要があります-そして私は自分のDNS実装の展開をスキップしたいと思います;)