Неблокирующее (асинхронное) разрешение DNS в Java

есть ли чистый способ разрешить DNS-запрос (получить IP по имени хоста) в Java асинхронно, неблокирующим способом (т. е. государственная машина, а не 1 запрос = 1 поток-я хотел бы запускать десятки тысяч запросов одновременно, но не запускать десятки тысяч потоков)?

что я нашел до сих пор:

  • стандартный InetAddress.getByName() реализация блокирует и выглядит так, как стандартные библиотеки Java не имеют каких-либо неблокирующих реализаций.
  • разрешения DNS в оптом вопрос обсуждает аналогичную проблему, но единственное найденное решение-многопоточный подход (т. е. один поток, работающий только на 1 запросе в каждый данный момент времени), который на самом деле не масштабируется.
  • dnsjava библиотека также блокирует только.
  • здесь древние неблокирующие расширения для dnsjava датировка с 2006 года, таким образом, отсутствует какой-либо современный Java-параллелизм, такой как Future использование парадигмы и, увы, очень ограниченная реализация только для очереди.
  • dnsjnio проект также является расширением dnsjava, но он также работает в потоковой модели (т. е. 1 запрос = 1 поток).
  • asyncorg кажется лучшим доступным решением, которое я нашел до сих пор, ориентируясь на эту проблему, но:
    • это еще с 2007 года, и выглядит заброшенным
    • не хватает почти любой документации / javadoc
    • использует много нестандартных методов, таких как Fun класс

любые другие идеи / реализации, которые я пропустил?

уточнение. У меня довольно большое (несколько ТБ в день) количество журналов. Каждая строка журнала имеет имя хоста, которое может быть практически из любой точки интернета, и мне нужен IP-адрес для этого имени хоста для моих дальнейших вычислений статистики. Порядок строк на самом деле не имеет значения, поэтому, в основном, моя идея-начать 2 потока: сначала перебрать строки:

  • прочитайте строку, проанализируйте ее, получите имя хоста
  • отправить запрос на DNS-сервер для разрешения данного имени хоста, не блокируйте для ответа
  • сохраните строку и дескриптор сокета запроса DNS в некотором буфере в памяти
  • перейти к следующей строке

и второй поток, который будет:

  • дождитесь ответа DNS-сервера на любой запрос (используя epoll / kqueue нравится техника)
  • читать ответьте, найдите, для какой строки это было в буфере
  • напишите строку с разрешенным IP-адресом на выход
  • перейти к ожиданию следующего ответа

простая реализация модели в Perl с использованием AnyEvent показывает мне, что моя идея, как правило, правильная, и я могу легко достичь скорости, как 15-20K запросов в секунду таким образом (наивная реализация блокировки получает как 2-3 запроса в секунду-просто ради сравнения-так что это похоже на 4 порядка величины разница.) Теперь мне нужно реализовать то же самое в Java - и я хотел бы пропустить развертывание моей собственной реализации DNS ;)

6 ответов


может быть,реализация служб каталогов Apache DNS поверх мины-это то, что вы ищете. JavaDocs и другие полезные руководства находятся на этой странице, в левой боковой панели.


есть некоторые работы по неблокирующему DNS в в netty, но он все еще работает в процессе, вероятно, будет выпущен только в 5.0


Я думаю, вам придется реализовать протокол DNS-клиента самостоятельно поверх raw UDP с помощью поддержки базовых сокетов или поверх TCP с использованием каналов NIO.


У меня нет ответа на ваш вопрос (я не знаю, есть ли библиотека DNS, которая будет работать в асинхронном режиме, который вы хотите), и это слишком долго для комментария.

но вы должны быть в состоянии быстро создать асинхронный без необходимости писать полный обработчик DNS самостоятельно. Предупреждаю, я сделал это не для того, чтобы ошибаться.

начиная с кода dnsjava, вы должны иметь возможность реализовать свой собственный распознаватель, который предоставит вам обоих отправителей и метод приемника. Проверьте SimpleResolver и посмотрите на send метод. Вы должны иметь возможность разбить этот метод на два метода: один для отправки Вашего запроса, который выполняется до вызова либо TCPClient, либо UDPClient (вы бы обрабатывали фактическую отправку на проводе в этот момент, как вы описали, с вашим первым потоком), и один для получения, который будет вызван вашим вторым потоком в ответ на чтение сокета, и обработайте разбор ответа. Вы можете нужно либо скопировать весь код из SimpleResolver (много частных методов, которые вам понадобятся и лицензирование позволяет это), или вы можете создать свою собственную версию и просто загрузить ее перед Джаредом в своем пути к классам, или вы можете отразить свой путь к рассматриваемым методам и установить их можно.

вы можете быстро построить сеть на стороне клиента с Нетти или мины. Я предпочитаю Нетти для доктора.

Если вы идете по этому пути и можете/хотите открыть исходный код, я могу выделить некоторое время, чтобы помочь, если вы попадете в беду.


Linux имеет асинхронную функцию поиска DNS: http://www.imperialviolet.org/2005/06/01/asynchronous-dns-lookups-with-glibc.html

Если вы находитесь на Linux, вы просто нужно завернуть это в какой-то JNI.


У вас есть несколько вариантов

Вариант 1: Исполнители Java 5

  1. пул фиксированных потоков: исполнители.newFixedThreadPool (int)
  2. будущее: будущее представляет собой результат асинхронного вычисления. Предоставляются методы для проверки завершения вычисления, ожидания его завершения и получения результата вычисления.

Вариант 2: JMS с Элементом messagelistener

  1. требует зависимости от поставщика JMS и т. д.

Вариант 2: актер на основе framework

вы можете масштабировать это хорошо с этим.Посмотреть Акка.