Ответы пользователя по тегу Node.js
  • Node.js в качестве server-side для enterprise приложения?

    Stdit
    @Stdit
    По моему опыту, nodejs — удобная, стабильная и быстрая штука, имеющая отличное сообщество и много хороших библиотек в npm. Преимущества можно перечислять долго, лучше сразу перейти к проблемам.

    — Сложно найти готовых к работе толковых программистов, даже среди фронтендщиков. Но можно обучить. На обучение и понимание среды nodejs, API, асинхронности, замыканий, калбэков, событий, функционального подхода — уходит примерно месяц-два.
    — Библиотеки из форнтендов использовать можно, но только если они грамотно написаны и оптимизированы для перманентной работы. Иначе есть риск, что они сожрут всю память или повесятся.
    — Сервер nodejs обычно однопоточный, со всеми вытекающими. Имеется возможность форкать и открывать дочерные процессы, на это нужны дополнительные затраты труда. Но это требуется только в исключительных случаях.
    — Код пишется в основном легко, если следовать чёткому стандарту, который обычно навязывается используемым фреймворком. Однако javascript, ввиду своей нестрогости, неустойчив к коррозии, в спешке или по неопытности можно наделать рака и превратить жизнь своей команды в ад.
    — При сложной логике со множеством вызовов можно без злого умысла нагородить «лестниц» из калбеков. Однако, проблема решается разными вариантами библиотек управления задачами (async, Q, и т.д.). Вообще лучше делать максимальную декомпозицию кода, создавать бесчисленные функции внутри функций — не очень хорошая практика.

    По поводу камней:
    — Обычно, всякие руководства и мануалы типа «hello world» используют один сокет для соединения с БД. На практике оказалось, что если этот сокет зависает под тяжёлым запросом, то все остальные запросы прилежно ждут его освобождения. Поэтому первое, что нужно сделать в новом проекте — это подключить database connection pool.
    — Случилось так, что количество одновременных подключений к серверу перевалило за тысячу, и внезапно возникли необъяснимые аномалии и отказы. Как выяснилось, страшного ничего не произошло, и нужно было просто в операционной системе разрешить открывать на порядок больше файловых/сокетных дескрипторов.
    — Память для nodejs лучше ограничивать ключами запуска и отдавать больше для БД (если они на одной машине). В противном случае nodejs не спешит запусктать сборщик мусора (это ведь затратная операция) и разрастается.
    — Перезагрузки nodejs из-за внезапных падений от багов решаются специальными библиотеками, например forever.
    — Чтобы nodejs не вылетал из-за исключений, нужно ставить глобальный обработчик uncaughtException, который пишет их в лог или сразу шлёт на мыло ответственному лицу.
    — Нужно не забывать отвязыватсь обработчики от событий по окончании работы подписанного на событие объекта (removeListener()).

    По поводу фреймворков, используем express, потому что он красивый, простой и мы к нему привыкли.
    Ответ написан
    2 комментария
  • Логика работы с MongoDB в сервере на Node.JS?

    Stdit
    @Stdit
    При использовании одного соединения с БД есть серьёзный риск перегрузить сокет базы настолько, что именно он станет узким тормозящим местом всего проекта. Это довольно подлый нюанс, который не заметен на этапе тестирования и ввода в эксплуатацию (как и проблема гонок в mongo, но это отдельный разговор). У меня такое было, правда не на mongo, а на pg, но суть от этого не меняется: пока сокет базы занят перекачиванием больших объемов данных на специфических страницах, сайт будет заблокирован. Но и открывать соединение с базой на каждый запрос тоже не самая лучшая идея, так как на открытие, настройку и содержание соединения нужно несоразмерно много ресурсов (в том числе и на сервере БД). Поэтому должен быть пул соединений с БД. Драйверы mysql и pg такой пул имеют, насчет mongodb не уверен, так как не копал устройство драйверов mongo для nodejs.
    Ответ написан
    Комментировать
  • Как правильно соединяться с базой в нагруженных проектах?

    Stdit
    @Stdit
    Однажды ошибка в этом месте (делать одно глобальное соединение с БД) стоила мне целых выходных. Сразу оговорюсь, что использовался не mysql, а модуль node-postgres, но суть должна быть одинаковой. При большой нарузке длинные запросы блокировали сокет базы, и как следствие работу всего сервиса. Поэтому нужно было срочно переделывать модель на Connection Pool, который на этапе разработки как-то ушел из внимания, так как на одном коннекте с небольшой бд тестовых данных вроде бы все было хорошо. :)

    Пул может организовать несколько параллельных подключений, которые не будут мешать друг другу. По окончании запроса подключение освобождается и уходит в пул. При отсутсвии свободных слотов в пуле запрос ставится в очередь до освобождения одного из слотов. Что касается доступа в БД, я использовал простейший вариант — непосредственный доступ через модуль и его параметры подключения по умолчанию. В каждом файле, который нуждается в БД, делается require драйвера БД и через него происходит обращение в базу. При использовании пула надо обязательно следить за освобождением соединений (функция done). Количество соединений в пуле задается опцией настроек модуля.

    О том, как использовать пул в pg, можно почитать здесь.
    Ответ написан
    3 комментария
  • JavaScript меня в могилу сведет [Node.js]

    Stdit
    @Stdit
    // m1.js
    module.exports.Model = function() {
      this.test = function() {
        console.log("MODULE 1");
      };
    };
    
    // m2.js
    module.exports.Model = function() {
      this.test = function() {
        console.log("MODULE 2");
      };
    };
    
    //test.js
    var model1 = new (require('./lib/m1.js').Model);
    var model2 = new (require('./lib/m2.js').Model);
    
    model1.test();
    model2.test();
    
    //result
    MODULE 1
    MODULE 2
    
    Ответ написан
    Комментировать
  • Не всегда доходят данные от сервера на NodeJS клиенту?

    Stdit
    @Stdit
    Возможно, это связано с неправильной обработкой потока из сокета (сероятнее всего, на клиенте), поскольку вы не пользуетесь carrier или другой буферизацией/делением. Событие data не означает, что в нем содержится именно так строка, которую послала вторая сторона. Там может быть часть из неё, а может быть и несколько строк сразу (зависит от размера данных и размера буфера передачи). Таким образом, данные могут быть потеряны, если например две команды сервера попадают в одно событие «data», заваливая распознавание пакета (на клиенте, в частности, в зависимости от реализации). На этот камень я наступал, способ решения — carrier, какой-нибудь сокетный фреймворк или свой вариант протокола верхнего уровня. Вот пример демонстрирующих тестов:
    Скрытый текст
    // server.js
    var net = require('net');
    var server = new net.Server();
    
    process.on('uncaughtException', function (err) {
        console.log(err.stack);
    });
    
    server.listen(12345);
    server.on('connection', function (connection) {
        console.log('connection');
        connection.on('data', function (data) {
            console.log('server data', data.toString());
            connection.write(data);
        });
        connection.on('end', function () {
            console.log('server end');
        });
    });
    

    // client.js
    var net = require('net');
    var client = new net.Socket();
    
    process.on('uncaughtException', function (err) {
        console.log(err.stack);
    });
    
    client.connect(12345);
    client.on('connect', function (connection) {
        console.log('connect');
        client.on('data', function (data) {
            console.log('client data', data.toString());
        });
        client.on('end', function () {
            console.log('client end');
        });
    });
    
    setTimeout(function () {
        "use strict";
        client.write('string1');
        client.write('string2');
    }, 100);
    
    setTimeout(function () {
        "use strict";
        var i = 100000;
        var string = '';
        while (i--) {
            string += i;
        }
        client.write(string);
    }, 200);
    
    setTimeout(function () {
        "use strict";
        client.write('string3');
        client.end('string4');
    }, 300);
    


    Если моё предположение неверно и вы об этом позаботились, тогда нужно делать tcpdump с фильтром по порту, и смотреть, что и куда приходит и уходит.
    Ответ написан