Какое оптимальное решение для быстрого парсинга 600 серверов на слабой VDS?
Задача: Поиск юзера (BF4) на игровых серверах, получение id сервера и запрос статистики раунда.
Требуется: обойти каждый url, получить json со списком игроков, поиск игрока в этом списке, вернуть id сервера если найден.
Дано: json c 600 id серверов и никнейм игрока.
Что пробовал: multicurl в 100 запросов - результат от 3 до 30 секунд, но на локальной машине. На DO дроплете с 1 ядром и 512Гб RAM грузит до зависания.
А если синхронным методом, то результат можно ждать до 3 минут даже на локальной машине.
Какие есть варианты для PHP, NODE.JS? Или других языков?
Требуется как можно быстрее получить результат поиска, но при этом не тратиться на покупку больших ресурсов виртуалки.
Хранить и обновлять всех игроков в БД тоже кажется сомнительным решением.
Варианты с pthreads и альтернативными вариантами для PHP я так понимаю тоже потребует увеличения ресурсов.
Если VDS слабый, то, на мой взгляд, выгоднее всего в плане производительности и потребления памяти это писать на go. Пхп и питон памяти больше выжрут, да и обработают такое количество урлов медленнее.
Насколько большой общий список игроков? Как характеризуется игрок: по 32-битному целому id, или текстовое имя пользователя? Может ли игрок быть на нескольких серверах одновременно?
Сергей Соколов, 603 сервера, на каждом макисмально возможное количество 66 игроков - 39798 игроков это потолок.
У некоторых серверов может быть статус error, но запрос по ним всё равно осуществляется. Игрока ищу по числовому id. Игрок всегда только на одном сервере.
но это логика была: ждать завершения цикла mcurl при котором формируется массив всех игроков со всех серверов - вот наверное я получал скачок. Сейчас делаю exit если игрок найден внутри цикла mcurl и результат из первой 100 (85 по счёту) серверов получаю через 2-6 секунд, а потребление памяти не выходит за рамки 512Мб
devalone, это и происходит - по конкретному id сервера получаю список игроков и в этом списке ищу игрока. Обратное же действие - получение сервера по id конкретного игрока работает не со всеми юзерами (Есть "скрыть моё присутствие" и тогда игрок отображается как оффлайн и никаких данных не даёт)
Виталий Балахнин, я имел ввиду по ID пользователя, т.е. "getUserById(serverId, userId)" или никнейму, не суть. Если только список, то твой метод решения единственно верный, просто надо оптимизировать, не хранить лишнее, использовать все потоки, т.е. создать N event loop'ов(в Go такой функционал будет из коробки например). Какого размера данные приходят? Я имею ввиду ответ сервера, сколько в этом массиве пользователей и сколько данных на каждого пользователя отдаёт сервер? Есть ли возможность в апи выбрать только нужные тебе поля? А установить limit и offset в запросе?
Виталий Балахнин, и кст, если запросы на обновление происходят часто, то я бы для этого пользователя хранил список из N серверов, где он был и в первую очередь опрашивал эти сервера.
devalone, да, про список часто посещаемых серверов я уже думал.
API для юзеров нет, обращаюсь к тому что нарыл через консоль браузера на самом сайте battlelog. Ответ в json 2 команды по 32 игрока максимум.
Виталий Балахнин, ну, это очень мало, 64 игрока, каждый допустим даже по 1 КБайту, получается 64 КБайт на сервер и даже если ты будешь опрашивать все одновременно, уложишься в 50МБайт и перебирать 64 сущности за запрос и так 600 раз - это вообще не много. Надо смотреть, что не так с твоим решением, ты где-то используешь слишком много лишней памяти. Пробовал использовать memory profiler?
Дмитрий Свиридов, Начинаю знакомится с Go, почти реализовал то что хотел. На Go такой парсинг (отдельная горутина под каждый запрос, ресурсы вроде сильно не жрёт) занимает максимум 2 секунды. Не совсем пока понимаю как работать с json и массивами, хочется привычных и простых альтернатив json_decode($array, true) и вперёд, а с Marshal/Unmarshal, картами, срезами, интерфейсами, структурами всё на данный момент кажется весьма запутаным))
Но пока попробовал только на локальном ПК. Спасибо за совет.
Конечно чем быстрее тем лучше. 5 секунд это ещё приемлемо. Увеличение количества запросов приведёт только к зависанию VDS или к бану по ip минут на 20 от battlelog
Виталий Балахнин, Тогда сложно, что либо сказать.
Надо смотреть что за сервера, как они работают и тд.
А user-agent у тебя меняется на каждый запрос, прокси, чтобы не попасть под бан?
А дают ли возможность сервера просто список игроков или там нужно опрашивать по очереди по каждому id пользователя у каждого сервера?
Просто если отдают список, не проще ли выгрузить их к себе и у себя искать, ты же сам себя не забанишь))) Ну это как вариант.
Прокси пока не делал так как сейчас упираюсь в ресурсы виртуалки. Каждый сервер отдаёт мне json со списком игроков, далее запись каждого списка в массив (на этом MULTICURL завершает цикл), а далее прохожу по массиву с поиском игрока ... О сам нашёл косяк в логике. Надо прервать все запросы не дожидаясь формирования общего массива игроков. То есть искать игрока внутри цикла запросов. А поджирает ресурсы наверное ещё и этот массив с игроками. Но это не сильно ускорит процесс наверное?
> Виталий Балахнин, Я бы сначала весь список записал к себе в БД.
> А потом в этой базе и искал игроков, там мне кажется будет намного эффективнее, раз тебе отдают весь список игроков))
нет, на задаче найти одного пользователя не будет, только лишняя трата памяти и тактов процессора
Для этой задачи, всеже, лучне Node.js подойдет. Ну, или пробуйте ReactPHP или что-то подобное.
Для Node.js никаких проблем не вижуб цифры не выглядят большими.
Можете скинуть (почта в профайле или тут напишите) детальное описание задания (я имею ввид адрес куда стучатся и т.п. если не секрет :)) я на выходных попробую это сделать.