三種Java自定義DNS解析器方法與實踐

前言:

最近終於用上瞭高性能的測試機(54C96G * 3),相較之前的單機性能提升瞭三倍,數量提升瞭三倍,更關鍵的寬帶提單機升瞭30倍不止,總體講提升瞭100多倍,這下再也不用擔心單機壓力機瓶頸,直接原地起飛。

不過沒高興5分鐘,我發現接口居然請求不通,經過一陣撥亂反正終於找到原因:域名無法解析,IP無法直接訪問。

自然而然,解決方案呼之欲出:自定義Java DNS解析器。

經過同事指點、資料搜索和探索實踐。終於鎖定瞭兩個核心類:org.apache.http.impl.conn.InMemoryDnsResolverorg.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!

推薦閱讀: