Как управлять списком хостов, регулярно обновлять их статус, чтобы обеспечить доступ ко всем хостам в списке
Я недавно внедрил протокол DHT Kademila с Python. http://www.bittorrent.org/beps/bep_0005.html
Но я не знаю, как реализовать это высокоэффективным способом:
- Хороший узел - это узел, который ответил на один из наших запросов в течение последних 15 минут. Узел также хорош, если он когда-либо ответил на один из наших запросов и отправил нам запрос в течение последних 15 минут. После 15 минут бездействия узел становится сомнительным. Узлы становятся плохими, когда они не отвечают на несколько запросов подряд. Узлы, которые мы знаем как хорошие, получают приоритет над узлами с неизвестным статусом.
- Когда корзина полна хороших узлов, новый узел просто отбрасывается. Если известно, что какие-либо узлы в корзине стали неисправными, то один из них заменяется новым узлом. Если какие-либо сомнительные узлы в корзине не были видны в течение последних 15 минут, проверяется наименее недавно просмотренный узел. Если проверенный узел отвечает, тогда следующий наименее замеченный недавно сомнительный узел проверяется, пока один из них не отвечает, или все узлы в корзине, как известно, исправны. Если узел в сегменте не отвечает на эхо-запрос, рекомендуется повторить попытку, прежде чем выбросить узел и заменить его новым исправным узлом. Таким образом, таблица заполняется стабильными долго работающими узлами.
Это правило показывает, как обновить узлы в сегментах: узел будет проверен, если не получит от него ответ в течение 15 минут, чтобы определить, является ли он по-прежнему хорошим узлом.
Как я могу реализовать правило выше? Должен ли я установить таймер для каждого узла? Если я услышу от него через 15 минут, таймер для этого узла будет сброшен. Если время истекло, узел будет добавлен в очередь пинга, ожидающую оценки.
Но у меня нет хорошей идеи реализовать это в Python. Может ли кто-нибудь дать какое-то руководство? Спасибо за внимание.
1 ответ
BEP5 довольно лаконичен, пропуская много деталей, рекомендуется также прочитать оригинальную статью Kademlia
Что касается сохранения состояния: для каждой записи таблицы маршрутизации вы можете сохранить время, когда она последний раз отвечала на запрос (последнее увиденное сообщение недостаточно из-за асимметричной достижимости, вызванной NAT).
Вы можете просто запустить таймер, который перечисляет вашу таблицу маршрутизации, скажем, каждые 10 секунд, ища сомнительные записи для записей ping/bad для удаления, если замены доступны. Вы также можете инициировать пинг в попытках диссертации в список замены корзины.
То, как именно вы выполняете обслуживание (управляемое событиями, основанное на таймере, упреждающее эхо-тестирование или в основном пассивное выполнение операций, связанное с поддержкой удаленных запросов), не так уж важно для алгоритма Kademlia. Цель состоит в том, чтобы не обслуживать недоступные записи из таблицы маршрутизации и регулярно обновлять регион домашнего сегмента, чтобы компенсировать его отток.
Поскольку вы пометили это как многопоточность: дерево таблицы маршрутизации и списки основных сегментов должны быть достаточно стабильными. Таким образом, вы можете использовать структуры данных копирования при записи (чтение снимка без блокировки, изменение под блокировкой). Списки замены изменяются чаще, поэтому параллельная очередь может быть более полезной.
Но нормальные узлы DHT в любом случае не испытывают большого трафика. 100 пакетов в секунду уже были бы необычным пиком. Все это может быть обработано в одном потоке. Вам действительно нужно несколько потоков для многодомных узлов серверного класса с низкой задержкой и высокой надежностью, которые со временем могут оказаться во множестве таблиц маршрутизации других узлов.
Вы также можете посмотреть на существующие реализации: