Доброго времени суток, %username%!
В некоторый момент своей жизни я понял, что нужно сделать что-то значимое. Да и подзаработать, если честно.
Тут ко мне пришел друг, который на продажу делал сборки разных игровых серверов и предложил сделать
Времени на тот момент было много, за плечами — два года кодинга на php фрилансером и было решено сделать этот проект.
PHP уже порядком поднадоел от нудной работы в стиле «подправь мне вот тут сайтик на Joomla», на хабре вовсю шло обсуждение нашумевшего NodeJS и в качестве инструмента для написания я выбрал именно его.
Что из этого вышло — читайте под катом.
Купили домен, разместили заглушку и принялись за разработку. Описывать свое знакомство с NodeJS не буду — про это и без меня написано тонны статей.
Архитектура
То есть, все запросы пользователя попадают на сайт, он решает, есть ли права на действие (например, запустить сервер) и отправляет на целевую машину.
Техническая сторона
На сайте запущено несколько процессов:
- Обрабатывает запросы
- Обновляет информацию о валютах и загружает информацию с группы вконтакте
- Собирает статистику по серверам пользователей
- Очередь команд для отправки на машины
Первый процесс — родитель, остальные — форки. Тут стоит отметить, что вызов 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