Неблокирующее (асинхронное) разрешение 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
- пул фиксированных потоков: исполнители.newFixedThreadPool (int)
- будущее: будущее представляет собой результат асинхронного вычисления. Предоставляются методы для проверки завершения вычисления, ожидания его завершения и получения результата вычисления.
Вариант 2: JMS с Элементом messagelistener
- требует зависимости от поставщика JMS и т. д.
Вариант 2: актер на основе framework
вы можете масштабировать это хорошо с этим.Посмотреть Акка.