Java中的非阻塞(异步)DNS解析

时间:2012-08-14 15:11:36

标签: java asynchronous dns nonblocking event-driven

是否有一种干净的方法以非阻塞的方式异步解析Java中的DNS查询(通过主机名获取IP)(即状态机,而不是1个查询= 1个线程 - 我想运行数万个查询同时,但没有运行数万个线程)?

到目前为止我发现了什么:

  • 标准InetAddress.getByName()实现阻塞,看起来标准Java库缺少任何非阻塞实现。
  • Resolving DNS in bulk问题讨论了类似的问题,但找到的唯一解决方案是多线程方法(即一个线程在每个给定时刻只处理1个查询),这实际上不是可扩展的。
  • dnsjava库也只是阻止。
  • ancient non-blocking extensions to dnsjava可追溯到2006年,因此缺少任何现代Java并发内容,例如Future范例使用,唉,只有非常有限的队列实现。
  • dnsjnio项目也是dnsjava的扩展,但它也适用于线程模型(即1个查询= 1个线程)。
  • asyncorg似乎是我迄今为止针对此问题找到的最佳解决方案,但是:
    • 它也是从2007年开始,看起来已经放弃了
    • 几乎没有任何文档/ javadoc
    • 使用了许多非标准技术,例如Fun class

我错过了其他任何想法/实施?

澄清即可。我有一个相当大(每天几TB)的日志量。每个日志行都有一个主机名,可以来自互联网上的任何地方,我需要一个IP地址作为我的进一步统计计算的主机名。行的顺序并不重要,因此,基本上,我的想法是启动2个线程:首先迭代线:

  • 读一行,解析它,获取主机名
  • 向DNS服务器发送查询以解析给定的主机名,不要阻止接听
  • 将行和DNS查询套接字句柄存储在内存中的某个缓冲区中
  • 转到下一行

第二个线程将:

  • 等待DNS服务器回答任何查询(使用epoll / kqueue类似技术)
  • 阅读答案,找到缓冲区中的哪一行
  • 将已解析IP的行写入输出
  • 继续等待下一个答案

Perl中使用AnyEvent的简单模型实现向我展示了我的想法通常是正确的,我可以通过这种方式轻松实现每秒15-20K查询的速度(天真的阻塞实现每秒2-3次查询 - 只是为了比较 - 这就像4个数量级的差异)。现在我需要在Java中实现相同的功能 - 我想跳过我自己的DNS实现;)

6 个答案:

答案 0 :(得分:5)

可能是MINA顶部的Apache Directory Services implementation of DNS正是您所寻找的。 JavaDocs和其他有用的指南都在该页面的左侧边栏中。

答案 1 :(得分:5)

in netty中有一些关于非阻止DNS的工作,但它仍在进行中,可能只会在5.0中发布

答案 2 :(得分:3)

我认为,您必须使用基本套接字支持在原始UDP之上自己实现DNS客户端协议,或者使用NIO通道在TCP之上实现DNS客户端协议。

答案 3 :(得分:2)

我对你的问题没有答案(我不知道是否有一个可以在你想要的异步模式下运行的DNS库)这对评论来说太长了。

但是,您应该能够快速生成异步,而无需自己编写完整的DNS处理程序。警告,我没有这样做,所以我可能都错了。

从dnsjava代码开始,您应该能够实现自己的解析器,它将为您提供发送方和接收方方法。查看SimpleResolver并查看send方法。您应该能够将此方法分解为两种方法,一种方法是将您的请求运行到TCPClient或UDPClient的调用(此时您将处理实际的线路发送,如您所述,你的第一个线程)和一个接收,它将被你的第二个线程调用作为对套接字读取的响应,并处理解析响应。您可能必须复制SimpleResolver中的所有代码(许多您需要的私有方法和licensing allows for it),或者,您可以创建自己的版本,只需将其加载到您的jared之前。 classpath,或者,您可以反映您对相关方法的看法set them accessible

您可以使用nettymina快速构建网络客户端。我更喜欢netty用于文档。

如果你沿着这条路走下去并且想要开源,我可以留出一些时间来帮助你解决问题。

答案 4 :(得分:1)

Linux具有异步DNS查找功能:http://www.imperialviolet.org/2005/06/01/asynchronous-dns-lookups-with-glibc.html

如果您使用的是Linux,那么 需要将其包含在某些JNI中。

答案 5 :(得分:0)

您有多个选项

选项1:Java 5执行程序

  1. 固定线程池:Executors.newFixedThreadPool(int)
  2. Future:Future表示异步计算的结果。提供了检查计算是否完成,等待其完成以及检索计算结果的方法。
  3. 选项2:使用MessageListener的JMS

    1. 需要依赖JMS提供程序等。
    2. 选项2:基于演员的框架

      您可以使用此功能进行扩展。请查看Akka