BlackHole开发日记-尝试NIO和ehcache

今天上班的路上在对比Tomcat和Jety的连接模型。Tomcat使用多线程处理请求,一个请求一个线程;Jetty则采用NIO。有文章说,对于逻辑复杂、处理时间较长的连接,Tomcat有优势,但是对于处理时间较短的连接,Jetty有优势。毫无疑问DNS的处理时间是很短的,看来把之前connector部分多线程的处理模型换成NIO的,应该性能会有一些提升。以后几天一个大的开发计划,就是调研Java NIO和Jetty里的实现,写一个完整的NIO connector。Cache机制开发延后。

上午在网上找了点资料,磕磕碰碰把基于NIO的服务器模型搭出来了。因为DNS使用的是UDP协议,同时数据量很小,所以NIO并没有起到理想中的效果。

主要服务器部分代码在https://github.com/flashsword20/blackhole/blob/nio/src/main/java/us/codecraft/blackhole/connector/UDPSocketMonitor.java。测试之后的效果让人失望,NIO效率比多线程+BIO更低,只有24000~28000qps,并且因为代码不熟悉,系统变得很不稳定。所以暂时保留到NIO分支了。

结论是这样的:

一个DNS query的包大小大约是几十byte,而response也不超过100 byte,如此小的传输量,同时因为UDP包也不涉及连接建立等东西,发送速度也很快,所以NIO发挥不了效率。

晚上回家,尝试加入cache机制:

使用了ehcache,但是死活都存在UDP包乱序的问题。后来发现

对于同一key,ehcache获取出来的对象总是同一个,这也是进程内缓存的特殊之处,不妨将其想想为一个Map

而我会尝试改变其ID值,结果就导致看起来ID变了,其实也改变了其他线程获取到的值,出现了不确定性!

后来改进了数据结构,尝试写一个CopyOnWriteMessage(Message是dnsjava中DNS报文的抽象类),结果因为其很多方法都是私有,所以失败了。后来构建了一个UDPPackage的对象,尝试将byte[]用CopyOnWrite和访问锁的方式解决并发问题,测试结果CopyOnWrite性能会好一点,这也是因为数据量较小,而且Arrays.copyOf是本地方法吧。

后来测试,值得高兴的是有缓存的情况下,转发模式效率达到了40000qps,可喜可贺!

家里连公司,benchmark里,UDP丢包率大概在10%,效果相当差,所以说网络才是第一要素!

你可能感兴趣的:(dns,BlackHole)