Всем доброго времени!
Возникла задача реализовать некоторое подобие сканера портов по большому диапазону IP-адресов. Конечно, в один поток данная задача не решается, поэтому исследовал различные варианты многопоточности/асинхронности. Имею довольно большой опыт написания сетевых многопоточных приложений, однако с асинхронностью и зелеными потоками дела не имел. Задача сводится к попытке соединения на определнный порт каждого IP-адреса с заданным таймаутом (например, 1 секунда).
Насколько я понимаю, в питоне такую задачу можно решить двумя способами:
1. Создать пул нативных потоков (пробовал создавать 1000 штук) и в цикле обойти все IP.
2. Создать пул зеленых потоков (пробовал создавать 2000 штук, использовал eventlet) и в цикле обойти все IP.
Проблема решается и тем, и другим подходом, однако хочется наибольшую скорость при наименьших затратах ресурсов. Прошу просветить меня в следующих вопросах:
Вопрос №1: по-идее можно создать на каждый IP-адрес свой поток (зеленый или нет), но, насколько я понимаю, использование пула предпочтительнее, т. к. мы не тратим постоянно ресурсы на создание новых потоков + при большом количестве IP нативных потоков столько просто не создать вследствие ограниченности ресурсов. Правильно?
Вопрос №2: чем вообще зеленый поток отличается от обычного в контексте питона? Ну, то есть я понимаю, что threading создает поток ОС, а green thread - это просто событийная IO-модель (?), но по-сути, имея GIL, все операции будут выполняться одним ядром, то есть разницы в скорости зеленых потоков и обычных не будет? Или все дело в том, что зеленые потоки легче и быстрее переключается контекст? На самом деле все равно немного запутался тут
Вопрос №3: насколько вероятен вариант, что таймаут сокета в 1 сек при однопоточном приложении отличается от такового в многопоточном/асинхронном? Ну то есть не получится ли, грубо говоря, такой ситуации, что тысяча сокетов начали соединяться, к 0.99 сек все готовы получать данные, но пока очередь получения дошла до последнего, у него уже вывалился таймаут, хотя коннекшен был произведен за время < 1 сек. Ну и могут ли как-то еще потоки/зеленые потоки мешаться друг другу (не в смысле синхронизации, а именно в смысле недополучения данных и т.д.)?
Вопрос №4: какая модель наиболее хорошо способна решить данную задачу? Интересна стабильность работы, скорость, требовательность к ресурсам. Какую библиотеку стоит использовать из множества (gevent, eventlet, coroutines, etc.)? В чем разница между ними? Вопросы сложности написания кода под конкретную библиотеку не рассматриваются, задача сама-по-себе элементарная, так что тут проблем не будет.
Вопрос №5: вчера тестировал eventlet, вроде с ней все хорошо получается, однако не очень понял, почему на 2000 микропотоков и на 3000 прироста в скорости не ощущается? Трафик идет порядка 300 кб/сек, загрузка процессора порядка 30%, то есть вроде запасы есть большие, а не растет скорость почему-то.
Спасибо все большое за ответы, толковой информации мало где нашел по данной теме (именно по сравнению технологий). Везде видел только какие-то конкретные реализации конкретных программ, но вот так чтобы кто-то объяснил, чем технологии отличаются и что когда лучше использовать - не нашел. Прошу прощения за много текста
P. S.: насколько я понял, если такое приложение писать на Erlang, то все было бы супер-классно, но увы