2012-05-01 81 views
3

我需要將大量(數十萬個)域解析爲Java中的IP地址。雖然使用InetAddress.getByName()對於小數字是可行的,但大量使用它的速度遠遠不夠(可能是因爲它只向DNS服務器發送一個請求並等待響應,然後才轉到下一個請求)。批量解析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元線,我們達到頂峯大約每分鐘700結果。其中,雖然比以前更好(< 300)仍然不是那麼好,當需要解決數十萬。將它降低到每個線程只有5個,這大大加速了每分鐘幾千個。這顯然創造了一個瘋狂的數量的線程雖然,所以目前正在調查做解決在C使用http://www.chiark.greenend.org.uk/~ian/adns/

+5

你最好不要發送他們到我的DNS服務器...... – Alnitak

+0

我們有我們自己的:-) – Exupery

+1

遞歸服務器?他們將在哪裏發送_their_查詢? – Alnitak

回答

1

您可以使用java.util.concurrent。*類創建一個多線程的應用程序來做幾個查詢,而無需等待結果。

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

如果這些對你來說是新的,那麼閱讀教程可能是個好主意。您的應用程序的

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

一部分將開始創建調用對象它變得可用,另外會從BlockingQueue的結果,並寫入到文件也許他們會將該結果放入BlockingQueue的。

編輯1: 樣品:

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

而不是創建並立即啓動幾個線程,委託執行任務指派給執行(見上文編輯),它在接受最多50線程隨時服務。您將需要找到最佳的線程數,太多的線程意味着,大多數cpu週期將用於切換線程。過低意味着,CPU週期將被浪費在等待DNS服務器返回結果

+0

用一個,四個和八個線程進行實驗,其收益實際上並不那麼棒。一個線程每分鐘處理大約275個線程,八個線程每分鐘處理大約330個線程......我們確實需要更接近每分鐘數千個線程(這可能是不可能的) – Exupery

+0

如果您的軟件處於最佳優化點,那麼您可能想升級硬件。但我認爲它應該比330per/min更好,如果它是275per/min之前。向我們展示一些代碼,你是如何實現的 – fmucar

+0

請參閱我的編輯代碼使用。我已經稍微重新考慮了它,現在每分鐘處理速度略高於700。 – Exupery

2

按照RFC for DNS Implementation你只能在一個時間問一個問題,定義如下:

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指定 查詢類型的兩個八位字節代碼。 該字段的值包括對 TYPE字段有效的所有代碼,以及 可以匹配多個類型的RR的一些更一般的代碼。

莫卡派喬斯[頁 28] RFC 1035域實現和規範
1987年11月

QCLASS兩個八位字節代碼,指定該類的 查詢。 例如,Internet的QCLASS字段爲IN。 ....

然而,你可能會得到自定義[higly不大可能]解析器是mainitain自己的高速緩存,並支持批量傳輸作爲其規範微張結束。我不知道是否有任何存在。也許你可以寫一個:) ...有關解析器的更多信息,請參閱此部分的第5部分RFC

最簡單的解決方案是使用前面建議的線程。

編輯: 我想這個故事的寓意是,DNS服務器不能接受批量請求。這是有道理的,否則攻擊者可能很容易從單個DNS服務器請求太多信息

+1

即使批量解析不可行,也可以通過使用配置良好的DNS服務器大大提高查找速度。使用Google的DNS,我們能夠每分鐘處理數千個DNS。 – Exupery