Хостинг игровых серверов на NodeJS

в 1:59, , рубрики: javascript, just for fun, node.js, игровой хостинг, метки: ,

Доброго времени суток, %username%!
В некоторый момент своей жизни я понял, что нужно сделать что-то значимое. Да и подзаработать, если честно.
Тут ко мне пришел друг, который на продажу делал сборки разных игровых серверов и предложил сделать хостинг для игрушек.
Времени на тот момент было много, за плечами — два года кодинга на php фрилансером и было решено сделать этот проект.
PHP уже порядком поднадоел от нудной работы в стиле «подправь мне вот тут сайтик на Joomla», на хабре вовсю шло обсуждение нашумевшего NodeJS и в качестве инструмента для написания я выбрал именно его.
Что из этого вышло — читайте под катом.

Купили домен, разместили заглушку и принялись за разработку. Описывать свое знакомство с NodeJS не буду — про это и без меня написано тонны статей.

Архитектура

image
То есть, все запросы пользователя попадают на сайт, он решает, есть ли права на действие (например, запустить сервер) и отправляет на целевую машину.

Техническая сторона

На сайте запущено несколько процессов:

  1. Обрабатывает запросы
  2. Обновляет информацию о валютах и загружает информацию с группы вконтакте
  3. Собирает статистику по серверам пользователей
  4. Очередь команд для отправки на машины

Первый процесс — родитель, остальные — форки. Тут стоит отметить, что вызов fork() в NodeJS не создает новый процесс, который является копией родительского, а запускает строго говоря другую программу (скрипт) с разделяемой памятью (shared memory) с родительским процессом.

Строго говоря, на каждой машине стоит сервер-обработчик, на который сайт отправляет команды. Написан он тоже на NodeJS. Примерно вот так сервер исполняет команды:

require("child_process").exec(command, function(error){
	if(error){
		res.writeHead(202);
	}else{
		res.writeHead(200);
	}
	res.end();
});

Сама отправка команд сначала была написана с использованием встроенного модуля http, но потом была переписана для большей надежности на простое дерганье wget.
Исходный код:

require("child_process").exec("wget --post-data '"+command+"' http://"+machineip+"/ --quiet -O -", function(error){
	if(error){
		logger.error("Ошибка исполнения");
		callback(true);
	}else{
		logger.info("Задание исполнено");
		callback(false);
	}
});

Подводные камни

Первое, с чем я столкнулся — это невозможностью адекватно сообщить два сервера. Команды отправлялись с указанием пользователя, от имени которого нужно их исполнять. Были опробованы и ssh-клиенты, и сишные программы-обертки. И где-то через неделю поисков я наткнулся на такую прекрасную штуку, как sudo -u. Просто стартовал новый bash от имени конкретного пользователя с указанием ключа -c, который сразу исполнял функцию и закрывал сессию.

После накопления некоторой базы серверов каждые пару минут сайт начинал виснуть по секунд так 30. Я тогда ещё не совсем понял специфику работы NodeJS. Оказалось, все-таки не надо в основном потоке собирать статистику.

Заключение

Тяжела и неказиста жизнь IT-специалиста.
При разработке получил уйму положительных эмоций и очень понравился NodeJS. Если кого интересует судьба проекта, то скорее всего огорчу вас — наверное, закроемся. Профита никакого, клиентов почти нет. Такие дела :)

Обо всех ошибках, пожалуйста, сообщайте в ЛС.
И если интересует что-то ещё, спрашивайте. Расскажу.

Приятный бонус: реализация Valve Server Queries на NodeJS — репозиторий.

Автор: uSide

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js