三種Java自定義DNS解析器方法與實踐
前言:
最近終於用上瞭高性能的測試機(54C96G * 3),相較之前的單機性能提升瞭三倍,數量提升瞭三倍,更關鍵的寬帶提單機升瞭30倍不止,總體講提升瞭100多倍,這下再也不用擔心單機壓力機瓶頸,直接原地起飛。
不過沒高興5分鐘,我發現接口居然請求不通,經過一陣撥亂反正終於找到原因:域名無法解析,IP無法直接訪問。
自然而然,解決方案呼之欲出:自定義Java DNS解析器。
經過同事指點、資料搜索和探索實踐。終於鎖定瞭兩個核心類:org.apache.http.impl.conn.InMemoryDnsResolver
和org.apache.http.impl.conn.SystemDefaultDnsResolver
,下面我會演示一下這兩個類的使用實踐,其中主要區別還是在負載均衡的實現上,這個有空再分享。
1.InMemoryDnsResolver
這個類使用比較簡單,先寫一個Demo,實現一個簡單的域名解析。
/** * 重寫Java自定義DNS解析器,非負載均衡 * * @return */ private static DnsResolver getDnsResolver2() { InMemoryDnsResolver dnsResolver = new InMemoryDnsResolver(); try { dnsResolver.add("fun.tester", InetAddress.getByName("127.0.0.1")); } catch (Exception e) { e.printStackTrace(); } return dnsResolver; }
這樣我們就可以把fun.tester解析到127.0.0.1上瞭,後面我會進行一個簡單的測試。
2.SystemDefaultDnsResolver
這個看名字是系統默認DNS解析器,但默認在哪,我也沒看出來,唯一可以查到的引用就是異步線程池管理器使用
org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager#PoolingNHttpClientConnectionManager(org.apache.http.nio.reactor.ConnectingIOReactor, org.apache.http.nio.conn.NHttpConnectionFactory<org.apache.http.nio.conn.ManagedNHttpClientConnection>, org.apache.http.config.Registry<org.apache.http.nio.conn.SchemeIOSessionStrategy>, org.apache.http.conn.SchemePortResolver, org.apache.http.conn.DnsResolver, long, java.util.concurrent.TimeUnit),
接下來我們看這個Demo
/** * 重寫Java自定義DNS解析器,負載均衡 * * @return */ private static DnsResolver getDnsResolver() { return new SystemDefaultDnsResolver() { @Override public InetAddress[] resolve(final String host) throws UnknownHostException { if (host.equalsIgnoreCase("fun.tester")) { return new InetAddress[]{InetAddress.getByName("127.0.0.1")}; } else { return super.resolve(host); } } }; }
3.自定義DnsResolver
通過源碼可以看出,兩個實現類都是通過實現org.apache.http.conn.DnsResolver
這個接口中org.apache.http.conn.DnsResolver#resolve
方法。我們自己可以完全自己實現。
/** * 自定義本地DNS解析器實現 * * @return */ private static DnsResolver getDnsResolver3() { return new DnsResolver() { @Override public InetAddress[] resolve(final String host) throws UnknownHostException { if (host.equalsIgnoreCase("fun.tester")) { return new InetAddress[]{InetAddress.getByName("127.0.0.1")}; } else { return InetAddress.getAllByName(host); } } }; }
仔細看不難發現,其實就是代碼縫合怪。
4.連接池管理器
下面分享一下如何使用自定義的org.apache.http.conn.DnsResolver
,就是在創建連接池管理器的時候設置一下就可以。
5.測試
首先我在本地起一個HTTP服務,端口12345,非常簡單。代碼如下:
static void main(String[] args) { def util = new ArgsUtil(args) def server = getServerNoLog(util.getIntOrdefault(0, 12345)) server.response("Have Fun ~ Tester !") def run = run(server) waitForKey("fan") run.stop() }
然後我準備一個測試腳本:
public static void main(String[] args) { String url = "http://fun.tester:12345/" def get = getHttpGet(url) def funtester = { fun { getHttpResponse(get) } } 10.times { funtester() } }
控制臺日志輸出:
INFO-> 27.214 F-1 請求uri:http://fun.tester:12345/ , 耗時:304 ms , HTTPcode: 200
INFO-> 27.214 F-4 請求uri:http://fun.tester:12345/ , 耗時:304 ms , HTTPcode: 200
INFO-> 27.214 F-10 請求uri:http://fun.tester:12345/ , 耗時:305 ms , HTTPcode: 200
INFO-> 27.214 F-5 請求uri:http://fun.tester:12345/ , 耗時:305 ms , HTTPcode: 200
INFO-> 27.214 F-2 請求uri:http://fun.tester:12345/ , 耗時:305 ms , HTTPcode: 200
INFO-> 27.214 F-8 請求uri:http://fun.tester:12345/ , 耗時:305 ms , HTTPcode: 200
INFO-> 27.214 F-3 請求uri:http://fun.tester:12345/ , 耗時:305 ms , HTTPcode: 200
INFO-> 27.214 F-7 請求uri:http://fun.tester:12345/ , 耗時:305 ms , HTTPcode: 200
INFO-> 27.214 F-6 請求uri:http://fun.tester:12345/ , 耗時:305 ms , HTTPcode: 200
INFO-> 27.214 F-9 請求uri:http://fun.tester:12345/ , 耗時:305 ms , HTTPcode: 200
三種實現方式控制臺輸出大同小異,都能滿足我們的需求,當然僅僅是功能測試場景下。下期會結合源碼分析如何實現負載均衡。
到此這篇關於三種Java自定義DNS解析器方法與實踐的文章就介紹到這瞭,更多相關Java自定義DNS解析器內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- 基於Java的Scoket編程
- Java基於TCP協議的Socket通信
- Java中Socket用法詳解
- 七牛雲的python sdk 批量刪除資源的操作方法
- java -D參數設置系統屬性無效問題及解決