Подтвердить что ты не робот

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

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

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

  • Стандартная реализация InetAddress.getByName() блокируется и выглядит так, как стандартные библиотеки Java не имеют каких-либо неблокирующих реализаций.
  • Устранение DNS навалом обсуждает аналогичную проблему, но единственным найденным решением является многопоточный подход (т.е. один поток, работающий только с одним запросом за каждый данный момент время), что на самом деле не масштабируется.
  • dnsjava библиотека также блокируется.
  • древние неблокирующие расширения для dnsjava начиная с 2006 года, поэтому не хватает современных Java concurrency, таких как Future использование парадигмы и, увы, очень ограниченная реализация только в очереди.
  • dnsjnio project также является расширением для 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;)

4b9b3361

Ответ 1

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

Ответ 2

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

Ответ 3

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

Ответ 4

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

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

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

Вы можете быстро создать сетевую клиентскую сторону с помощью netty или mina. Я предпочитаю netty для документов.

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

Ответ 6

У вас есть несколько опций

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

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

Вариант 2: JMS с MessageListener

  • Требуется зависимость от поставщика JMS и т.д.

Вариант 2: Основанная на актерах структура

Вы можете масштабировать эту скважину с этим. Посмотрите на Akka.