Распределенная и/или многопоточная работа с сетью?
Доброго времени суток.
Никак не могу придумать решение для следующей задачи:
Есть, к примеру, 1 000 000 доменов.
Требуется многопоточно (а в идеале - еще и распределенно) получить главную страницу с каждого домена.
Проблема заключается в том, что при использовании самописных desktop-решений скорость упирается в DNS-сервера как провайдера, так и альтернативные.
Да и канал у среднестатистического провайдера домашнего интернета не способствует.
В какую сторону смотреть?
1. Использовать много разных DNS для ресолвинга имен.
2. Использовать многопоточный парсер, который будет создавать 100000 потоков для парсинга + 1000 для определения доменного имени + увязать это все одно целое. Как вариант использовать для этого дела Erlang ;)
2. Как вариант ознакомьтесь с паттерном Disruptor и способами ассинхронной обработки событий, ну вот c epoll() и kqueue() к примеру, и не давайте дурных советов.
Не думаю что поставить кэширующий локальный DNS так сложно.
Ставить много разных DNS для резолвинга просто дурацкая идея...
В первую очередь для такой "многопоточной" загрузки страниц нужна ассинхронная обработка.
Идея в том что бы не вызывать 1 000 000 потоков на 1 000 000 доменов, всего лишь 8-16.
Я бы просто взял netty и не заморачивался бы...
Можно попробывать на С++ epoll() libcurl и pthread'ах завести, но можно и на Python Twisted.
В общем хватает барахла, главное это использование epoll() kqueue() ядерных поллеров, язык и библиотеки не имеют большего значения...
А причем тут кеширующий DNS ? По определению 1е+6 доменов вы не посещали, следовательно все запросы к одному DNS будут его нагружать, и это будет такой своеобразный bottle neck. Чтобы увеличить пропускную способность, надо использовать несколько DNS-серверов. И да, а где я говорил что их надо ставить ? Их надо просто использовать из интернета.
Вы популяризируюете кэширующий DNS нужными доменами и при последующих вызовах сборщика страниц экономите кучу времени.
В сам кэширующий DNS можно загрузить сколь угодно дочерних, и мониторить их отзывчивость - он сам будет расспределять нагрузки в зависимости от задержек. Нельзя просто взять и положить в /etc/resolv.conf кучу серверов и надеяться что нагрузка будет равномерно расспределяться.
> Идея в том что бы не вызывать 1 000 000 потоков на 1 000 000 доменов, всего лишь 8-16.
А такой идеи и не было ни у кого.
А вот давайте подсчитаем насколько сильно вы утилизируете ресурсы системы:
Принимаем:
1. Время отклика сайта - 1 сек.
2. Ваши 8-16 потоков.
3. Размер страницы (чистый HTML) - 100 кб.
И так что получаем:
в секунду мы опрашиваем 16 сайтов.
в секунду у нас трафик 16*100 = 1,6 Мбайт\с
время сканирования 1млн сайтов = 17 часов. ( а можно и быстрее).
с учетом того что скорости домашнего интернета кое-где побольше (а если взять серверное решение, то еще больше) - то утилизируете вы всего 1\10 полосы пропускания канала. Т.е. могли бы поднять и кол-во потоков до 160 как минимум.
Почему я посоветовал Erlang ?
да все дело в том, что в нем вы можете создать и 10,и 10000 процессов, которые будут обслуживать ваши задачи, и утилизировать ресурсы на все 100%.
Конечно цифры 100000 потоков на парсинг + 1000 потоков на днс - утрированы, но ничего не будет мешать сделать и такое кол-во процессов + прозрачно распределить все это дело на несколько машин.
1) Рассуждайте здраво: поток в Erlang, это не поток операционной системы, а актёр.
2) Нельзя просто взять и посчитать сколько сайтов можно опросить в секунду.
3) Разберитесь с моделями ассинхронной обработки событий
4) Я говорю про банальный disruptor и Future/Promise которые не требуют создания тонны потоков.
C использованием future/promise поток не блокируется во время ожидания ответа от сервера, а пошлёт ещё один запрос на другой сервер; когда прийдет ответ от первого, он будет обработан любым свободным потоком...
И это называется ассинхронной неблокирующей обработкой. Количество потоков которые нужны для обработки можно вычислить по скорости роста очереди отложенных задач.
Кеширующий DNS поможет в том, что он будет ходить за доменами прямо на авторитарные NS (те, на которые домен делегирован) - так что оно не будет упираться в чьи-то DNS серверы.. Само собой, никаких форвардеров в нём прописано быть не должно и он должен быть единственным в resolv.conf в системе. На убунте-дебиане оно "настраивается" так:
apt-get install bind9
Конфиг по умолчанию делает искомое. Останется только системе объяснить, что нужно использовать именно его. А отрезолвить тысяч 10 доменов за секунду в одно ядро он легко сможет.
Поставил bind для windows, никак не могу разобраться - как настроить его так, "что он будет ходить за доменами прямо на авторитарные NS". Пока удалось настроить только для работы через forwarders - но это не решает проблемы.
Лучше даже не пытаться подымать Bind под винду...
Можете реализовать задачу ресолвинга имён в рамках самого приложения "загрузчика". Собственно винда не очень хорошо подходит для подобных задач.
@misterkustwww.reaper-x.com/2008/07/10/set-up-caching-nameser... только строчки про forwarders и forward убрать нужно, емнип. Но вообще на винде такого действительно делать не стоит (тем более на десктопной) - у неё сетевой стек не предназначен для подобного.