三种Java自定义DNS解析器方法与实践
作者:FunTester 发布时间:2022-01-13 10:12:11
前言:
最近终于用上了高性能的测试机(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
三种实现方式控制台输出大同小异,都能满足我们的需求,当然仅仅是功能测试场景下。下期会结合源码分析如何实现负载均衡。
来源:https://blog.51cto.com/FunTester/4969045


猜你喜欢
- 传感器简单的介绍一下传感器: 就是设备用来感知周边环境变化的硬件。Android中的传感器包含在传感器框架中,属于android.hardw
- Double显示转换int static void Main(string[] args) { Console.WriteLine(&quo
- 本文实例讲述了C#创建windows系统用户的方法。分享给大家供大家参考。具体如下:下面的代码可以通过c#创建一个windows的本地系统账
- 初次接触spring-boot的时候,我们经常会看到这样的文章:“
- Q1: Object类型包含哪些方法?A1: Object类型共包含6个方法,Equals, GetHashCode, ToString,
- 引言: 最近公司在做一个教育培训学习及在线考试的项目,本人主要从事网络课程模块,主要做课程分类,课程,课件的创建及
- 1.Open IDEA,choose "New-->Project"2.Choose "Spring I
- 一:获取根目录的方法取得控制台应用程序的根目录方法方法1、Environment.CurrentDirectory 取得或设置当前工作目录的
- 一般很多项目不是在springcloud的环境中使用的,但是需要用到分布式配置中心来管理一些外部或者项目的配置,这个时候我们可以使用spri
- AutoCompleteTextView是一个具有自动补全功能的EditView,当用户输入数据后,AutoCompleteTextView
- 混乱的URI编码 JavaScript中编码有三种方法:escape、encodeURI、encodeURIComponent C#中编码主
- Java 中的线程有以下状态:新建状态(New):新创建的线程,还未执行。就绪状态(Runnable):执行了 start() 方法,等待运
- 开发 Web 应用的思路实现一个简单的 JSP/Servlet。搭建创建 Web 应用工程的环境。创建 Web 应用工程。Web 应用工程的
- 右击有main方法的类===> Run as===> Run Configurations ===>双击java
- Android现在实现Tab类型的界面方式越来越多,今天就把常见的实现方式给大家来个总结。目前写了:1、传统的ViewPager实现2、Fr
- 在Android项目中经常有碰到这样的问题,在子线程中完成耗时操作之后要更新UI,下面就自己经历的一些项目总结一下更新的方法:在
- 本文实例讲述了C#中static静态变量的用法。分享给大家供大家参考。具体如下:使用 static 修饰符声明属于类型本身而不是属于特定对象
- Android客户端请求服务器端的详细解释1. Android客户端与服务器端通信方式: Android与服务器通信通常采用HTTP通信方式
- 1 简介先来一张效果图TIM图片.gif上图中灰色的一块是ImageView控件,ImageView中的图片进行左右上下移动,以及双指缩放。
- 题目要求java实现字符串中的字母排序并输出排序后的结果分析1、创建一个字符串,赋值并将字符逐个存进数组中。String str = &qu