繁体   English   中英

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

[英]Non-blocking (async) DNS resolving in Java

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

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

  • 标准InetAddress.getByName()实现是阻塞的,看起来标准 Java 库缺少任何非阻塞实现。
  • Resolving DNS in bulk question讨论了类似的问题,但找到的唯一解决方案是多线程方法(即一个线程在每个给定时刻只处理 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的 DNSApache 目录服务实现 JavaDocs 和其他有用的指南位于该页面的左侧边栏中。

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

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

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

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

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

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

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

Linux 有异步 DNS 查找功能: 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 Provider 等。

选项 2:基于 Actor 的框架

你可以用 this 很好地扩展这个。看看Akka

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM