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

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

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

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

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

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

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

第二个线程将:

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

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

可能是在MINA之上的DNS目录服务实现是您正在寻找的。 JavaDocs和其他有用的指南位于该页面的左侧边栏中。

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

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

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

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

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

您可以使用netty或mina快速构建网络客户端。 我更喜欢netty for docs。

如果你沿着这条路走下去并且想要开源它,我可以留出一些时间来帮助你,如果你遇到麻烦。

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

如果你在Linux上,你需要在一些JNI中包装它。

你有多种选择

选项1:Java 5 Executors

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

选项2:使用MessageListener的JMS

  1. 需要依赖于JMS提供程序等。

选项2:基于Actor的框架

你可以用这个来扩展它。看看Akka 。