• Java自定义DNS解析器三种实践


    最近终于用上了高性能的测试机(54C96G * 3),相较之前的单机性能提升了三倍,数量提升了三倍,更关键的宽带提单机升了30倍不止,总体讲提升了100多倍,这下再也不用担心单机压力机瓶颈,直接原地起飞。

    不过没高兴5分钟,我发现接口居然请求不通,经过一阵拨乱反正终于找到原因:域名无法解析,IP无法直接访问。

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

    经过同事指点、资料搜索和探索实践。终于锁定了两个核心类:org.apache.http.impl.conn.InMemoryDnsResolverorg.apache.http.impl.conn.SystemDefaultDnsResolver,下面我会演示一下这两个类的使用实践,其中主要区别还是在负载均衡的实现上,这个有空再分享。

    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上了,后面我会进行一个简单的测试。

    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);
                    }
                }
            };
        }
    
    

    自定义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);
                    }
                }
            };
        }
    
    

    仔细看不难发现,其实就是代码缝合怪。

    连接池管理器

    下面分享一下如何使用自定义的org.apache.http.conn.DnsResolver,就是在创建连接池管理器的时候设置一下就可以。

    测试

    首先我在本地起一个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
    

    三种实现方式控制台输出大同小异,都能满足我们的需求,当然仅仅是功能测试场景下。下期会结合源码分析如何实现负载均衡。

    Have Fun ~ Tester !

  • 相关阅读:
    自己动手搭建私有百度网盘
    JVM 基础、堆内存分析和垃圾回收算法
    基于 Solo 通过阿里云服务器+Docker+Nginx+MySQL搭建个人博客
    ES6新特性总结
    JavaIO流总结
    Linq查找最大值max最小值min效率比较
    c# 控制台console进度条
    在 dotnet core (C#)下的颜色渐变
    go笔记--几个例子理解context的作用
    go微服务框架kratos学习笔记六(kratos 服务发现 discovery)
  • 原文地址:https://www.cnblogs.com/FunTester/p/15842207.html
Copyright © 2020-2023  润新知