IsengardArmory сервер-парсер

IsengardArmory сервер-парсер

Ссылка на сервис - https://ezserver.codehandler.ru/

Рано или поздно приходится возвращаться к различным проектам которые вроде как и заброшены, но частенько не дают покоя =)

Это один из таких проектов. Разработанный мною пару лет назад аддон для ВоВки пользовался некоторым спросом. Но без обновления аддон практически бесполезен и утрачивает актуальность в течение месяца по естественным причинам - игроки приходят, уходят, ренеймятся. А обновления несколько затянулись, поскольку в игры я практически не играю, пропал интерес наглухо.

Наткнувшись на архив с аддоном при разборке мусора нахлынули приятные воспоминания =) Я решил кардинально переписать все.

До этого я просто парсил с оружейки данные с помощью DataCol, загонял их в ЛУА файл. Новая система позволяет автоматически делать это на стороне сервера, не отнимая времени и локальных ресурсов.

Для основы я выбрал так полюбившийся мне фреймворк MoleculerJS. Строго говоря, на нем пишут микросервисы. Паралелльно идет разработка большого, серьезного проекта на этом фреймворке и я решил его использовать и для парсинга, чтобы не терять хватки и не отвлекаться.

Алгоритм работы простой, как 5 копеек. Создается сервер АПИ, раз в несколько секунд запрашиваем страницу оружейки с заданным смещением. Парсим страницу, сохраняем записи в БД, увеличиваем смещение на 20. При достижении смещения 150к - по текущему состоянию оружейки сбрасываем его в 0 и повторяем предыдущие пункты.

Также добавляем поинт для генерации файла аддона на основе данных из БД.

Единственное неудобство - страницы оружейки доступны лишь залогиненным пользователям, то есть нельзя вот просто так взять и парсить инфу. Для решения этой проблемы я просто добавил в БД таблицу с кукисами. Каждый, кто способен скопировать кукисы и добавить в БД - продляет работоспособность парсера. Если кукисов в базе нет - парсер по прежнему пытается найти их в базе в заданные промежутки времени.

Строка с кукисами

Хотелось бы пометить, что кукисы довольно живучие. Вполне возможно, на 1 заправке сервер будет работать досточно длительное время для хотя бы 1 полного цикла обновления.

Страница сервиса

Сама страница сайта - простой HTML с Bootstrap. Несколько кнопочек - скачать LUA, скачать SQL, скачать архив с аддоном IsengardArmory, форма для отправки кукисов и ссылка для донатов, куда же без них.

К слову, дамп SQL создается кроном и ложится в корень сайта с именем dump.sql. Дамп LUA обновляется на основе данных БД 1 раз в 30 минут.

Осталось только дождаться, пока парсер на основе моих кукисов скачает и спарсит все данные, затем пойдет по второму кругу для обновления. После скачивания, я, пожалуй, поставлю интервал парсинга не 5 секунд, как сейчас, а секунд 30, чтобы минимизировать нагрузку.

Код завернут в контейнеры Docker, а HTML-страничка отдается Nginx.

Сам код аддона не был изменен, обновлена только база.

Проект опенсорсный, если кто-то захочет внезапно запулить коммит - милости прошу. Ссылка на гитхаб - https://github.com/slayerokk/ez-parse-server.

Надо сказать, пенсорсные проекты я практически не делаю, все эти бесплатные вливания мне чужды =) Впервые, в качестве эксперимента, оставил ссылки на донат. Мне очень интересно, выйдет ли сервер на окупаемость. Хотя, если честно, платить за него мне придется в любом случае, поскольку он нужен для работы.

Потребление ресурсов docker stats

По итогам сканирования БД: 135584 персонажа, загружено с сервера ezwow.org 40 гигабайт)) Надеюсь, Хаген не сильно обеднел по трафику =)

Ремарка

Код аддона на работоспособность я не проверял. На данный момент нет под рукой скачанного клиента WoW. Но вносил изменения очень аккуратно, есть большая вероятность, что он остался рабочим =)

UPD 30.07.2020

  • База готова, задержка парсера увеличена до 45с. Чтобы пройти все 150к записей необходимо 150000/20*45/3600/24 = 3,9 суток, т.е. за 4 дня парсится и обновляется вся информация сервера. Надеюсь, мне удастся избежать большой нагрузки. Также задержка выводится на публичной странице отдельным пунктом.
  • Некоторые мелкие усовершенствования кода.
  • Кеш LUA и кеш SQL увеличен до 2 часов, делать его меньше я не вижу смысла, только ловить пики нагрузки CPU.
  • Добавил архив с плагином и его актуальную базу на сайт, плюс кнопка для скачивания.
  • Теперь LUA генерируется с актуальной датой обновления
  • Неприятный баг - LUA по крону генерируется внутри контейнера Docker. Файловая система контейнера не сохраняется. Следовательно, после запуска сервера должно пройти 2 часа, прежде чем заработает скачивание LUA, т.е. сгенерируются актуальные данные. До тех пор - Nginx будет отдавать ошибку 502. Дождитесь очередной генерации через два часа и все будет ок...
  • Добавлена Яндекс Метрика на паблик страницу

UPD 30.07.2020 - 2

  • Пришлось срочно вносить изменения, поскольку при генерации LUA возникает солидная нагрузка и нужно увеличить сроки всех кешей. Теперь кеш статистики - 180с, LUA - 12 часов, SQL - 12 часов, задержка между парсингами - 60с. Полное обновление базы будет происходить примерно за 150000/20*60/3600/24=5,2 дня. Вполне достаточная ротация. Возможно, придется в дальнейшем еще больше увеличить. Пример нагрузки при генерации LUA каждые два часа:

Первая горка это ночной бекап, если что. А вот три горки правее меня совершенно не устраивают...Это слишком нагло для сервера с 4мя горшками. Чтож, посмотрим, что будет на дистанции 12 часов.

  • Переделан конфиг BabelJS
  • Передалана генерация докер-образа, итоговый образ похудел с 76,4 Мб до 58,8 Мб, мелочь, а приятно
  • Исключен пакет node-cron, добавлена реализация очередей на BullJS
  • При старте сервера с задержкой 30 секунд генерируется первый LUA (баг из прошлого апдейта)

В целом, работа сервера меня устраивает, думаю, при адекватной нагрузке его можно будет оставить в этом виде надолго.

UPD 31.07.2020

  • Пришлось снести всю базу и переделать с mysql на mariadb. Связано с тем, что контейнер mysql из композера был довольно прожорливым. Я заменил его на mariadb, который на сервере не создаю, а использую БД ISP Manager по удаленному подключению.
  • Исправил ошибку обновления данных. Я грешным делом перепутал опции onDuplicate в Sequelize.BulkCreate и в итоге записи ни разу не обновлялись.
  • Исправил ошибку определения расы персонажа. Это вообще позорище. Парсер определяет расу по названию файла рисунка. А если не определяет - записывает как 0 (Альянс). При этом я не обратил внимание, что рисунки у рас различаются еще в зависимости от пола. Поэтому полбазы было альянсом =)
  • Добавил расширенную статистику по расам и класам. Как база снова наберется, обновлю ее в теме.