• Как правильно организовать роутинг на node?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    Чтобы сделать хорошо, нужно сделать без express, например, аналог Вашего кода:

    var http = require('http');
    
    var me = { name: 'jura', age: 22 };
    
    var routing = {
      '/': 'welcome to homepage',
      '/user': me,
      '/user/name': function() { return me.name; },
      '/user/age': function() { return me.age; }
    };
    
    var types = {
      object: function(o) { return JSON.stringify(o); },
      string: function(s) { return s; },
      undefined: function() { return 'not found'; },
      function: function(fn, req, res) { return fn(req, res) + ''; },
    };
    
    http.createServer(function (req, res) {
      var data = routing[req.url],
          result = types[typeof(data)](data, req, res);
      res.end(result);
    }).listen(80);


    И более универсальный вариант с параметрами:

    var http = require('http');
    
    var me = { name: 'jura', age: 22 };
    
    var routing = {
      '/': 'welcome to homepage',
      '/user': me,
      '/user/name': function() { return me.name; },
      '/user/age': function() { return me.age; },
      '/user/*': function(client, par) { return 'parameter=' + par[0]; }
    };
    
    var types = {
      object: function(o) { return JSON.stringify(o); },
      string: function(s) { return s; },
      number: function(n) { return n + ''; },
      undefined: function() { return 'not found'; },
      function: function(fn, par, client) { return fn(client, par); }
    };
    
    var matching = [];
    for (key in routing) {
      if (key.indexOf('*') !== -1) {
        var rx = new RegExp(key.replace('*', '(.*)'));
        matching.push([rx, routing[key]]);
        delete routing[key];
      }
    }
    
    function router(client) {
      var rx, par, route = routing[client.req.url];
      if (route === undefined) {
        for (var i = 0, len = matching.length; i < len; i++) {
          rx = matching[i];
          par = client.req.url.match(rx[0]);
          if (par) {
            par.shift();
            route = rx[1];
            break;
          }
        }
      }
      var renderer = types[typeof(route)];
      return renderer(route, par, client);
    }
    
    http.createServer(function (req, res) {
      res.end(router({ req: req, res: res }) + '');
    }).listen(80);
    Ответ написан
    3 комментария
  • Синхронный и асинхронный код, почему так называется?

    MarcusAurelius
    @MarcusAurelius
    автор Impress Application Server для Node.js
    А сам код синхронным не называется, это его по ошибке или для упрощения так называют. Синхронным и асинхронным называется только API ввода-вывода, т.е. операции, прерывающие исполнение кода и требующие от системы обратиться к внешнему устройству, работающему не синхронно с центральным процессором. Операции ввода-выдвода, каковые есть: работа с дисками, портами, контроллерами, периферийными устройствами, как клава, мыша, тачскрин, разные датчики, вебкамера, сетевые карты, блютузы и другие радиомодули, принтеры, видеокарты и прочее. Все они получают задание от программы, и исполняют его отдельно, своими мощностями. Потом внешние устройства присылают программе сигнал о статусе исполнения и, возможно, полученные данные. Программа все это время может ждать (если у нее синхронное API, т.е. блокирующее) или что-то делать (если асинхронное, т.е. не блокирующее). Если программа ждет, не переходит к выполнению следующего действия, то это синхронный ввод-вывод, потому, что осуществляется процесс синхронизации программы с внешним устройством. Внешне устройство посылает прерывание, которое обрабатывает операционная система и через несколько слоев драйверов оно попадает в программу, обычно в виде колбека или события. Если программа ждала, то вызов API не завершался, она все время слушала, когда придет событие о завершении операции ввода вывода, а получив его API отдает ответ и управление переходит к следующей команде, что и называется, синхронизацией с периферийным устройством. Если программа не ждала, то вызов API сразу завершается и не блокирует поток выполнения программ, это называется асинхронным API, потому, что процесс синхронизации не происходит явно, а ответы возвращаются через события.
    Ответ написан
    3 комментария
  • Как вы относитесь к короткоживущим процессам в NodeJS?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    Расскажу, какая ситуация с этим у меня в Impress и что меня в этом устраивает и не устраивает.

    Сейчас процессы для обработки запросов порождаются при старте, и повторно порождаются при падении. Утечки памяти или падения процессов - считаю ненормальным поведением, но в реальности не все используемые библиотеки пушу я и даже не весь код приложений пишу я, поэтому нужно как-то с утечками и падениями бороться. Конечно падения минимизированны, т.к. весь прикладной код выполняется в sandbox`ах, и при утечках можно просто создать новый sandbox в том же процессе, восстановить в нем все нужные структуры данных, потом заменить ссылку со старого (утекшего или испорченного при исключении sandbox`а) на новый и убить старый. Это быстрее, чем порождать новый процесс.

    Но иногда хочется ответвить обработку одного запроса в отдельный процесс, чтобы он не мешал другим. Сейчас у меня реализовано прозрачное для приложений порождение нового процесса для этих случаев, т.е. сделано нечто подобное воркерам. Но процессы запускаются относительно медленно. Кроме того, есть еще планировщик заданий, который должен выполнять часть бизнес-логики по расписанию.

    Как я хочу сделать. Кроме процессов обработки запросов иметь еще некоторый пул подготовленных запущенных процессов, которые уже и соединение к БД установили и развернули все что нужно в памяти. С родительским процессом они связаны TCP-сокетом, через который налажен RPC (полноценный вызов удаленных процедур с поддержкой колбэков, событий, асинхронного вызова нескольких запросов и т.д.) И когда возникает необходимость ответвить обработку или выполнить задание по расписанию, то вместо порождения процесса будет браться первый свободный процесс из пула и ему по RPC приходит заказ. Когда он все выполнил, то он по RPC возвращает колбэк или событие.

    Вот все у меня уже вроде готово для этого и сам RPC написан и отлажен, скоро реализую. А дальше по тому же RPC (но с транспортом через вебсокеты) собираюсь связать и клиентские приложения, чтобы они становились единым целым с серверными процессами и воркерами.
    Ответ написан
    2 комментария
  • Как создать приложение на поддоменах meteor?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    Только одним способом, нужно для каждого поддомена запускать отдельный серверный процесс, на отдельном порту. Потом все эти разные приложения собирать через nginx в один 80 порт. Но если Вам нужно динамически создавать доменные имена или таких поддоменов будет много, то Вы не сделаете это на таком стеке. Будет 500 поддоменов то будет 500 процессов ноды, это пожрет все ресурсы на преключение процессов.
    Ответ написан
  • Как объявить глобальную пременную внутри замыкания на node js?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    global.varName = 'value';
    Ответ написан
    Комментировать
  • Почему не все серверы пишутся на Node js?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    1. Потому, что он подходит не для всех задач Что можно написать на Node.js?
    2. Потому, что не для всех приемлем JavaScript, люди так привязаны к синтаксису
    Ответ написан
    2 комментария
  • Как сделать функцию более расширяемой в будущем?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    1. Как это Вы так быстро распарсили req.headers, там может быть такое, например:
    Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4
    Accept-Language: da, en-gb;q=0.8, en;q=0.7
    Accept-Language: cmn-Hans-CN
    Accept-Language: i-enochian
    Accept-Language: cel-gaulish
    Accept-Language: *

    или даже более сложное, см. спецификацию:
    https://tools.ietf.org/html/bcp47
    www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4

    Чтобы правильно распарсить есть библиотеки:
    https://github.com/gagle/node-bcp47
    https://github.com/tinganho/node-accept-language

    2. Делать require внутри обработчика это ужас. Это синхронная операция чтения из файла, которую нужно делать при старте сервера. Нужно положить все языки в один файл и прочитать его при старте, а потом обращаться к справочнику в памяти.

    3. Middleware detected, ну и конечно же не использовать next, если это конечно более-менее серьезный нагруженный проект в продакшене, а не прототип и не макет.
    Ответ написан
  • Как распарсить FormData запрос в nodejs?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    Когда парсать MIME, а это формат не простой, то не будет в том греха, есливозьмете модуль https://www.npmjs.com/package/multiparty и будете его применять, только если content-type точно содержит MIME
    var contentType = req.headers['content-type'];
    if (contentType && contentType.indexOf('multipart') === 0) {
      var form = multiparty.Form();
      form.parse(req, function(err, fields, files) {
        if (!err) {
          // тут имеем files
        }
      });
    }

    Благословенны пишущие без Expressa
    Ответ написан
    1 комментарий
  • JS API и REST API - это разные понятия?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    1. REST не имеет ни какого отношения к CURL.
    2. Устоявшегося понятия JS API не существует, оно сложилось исключительно у Вас в голове.
    3. Противоположностью REST (и STATEless) есть STATEful, т.е. связь без состояния и с состоянием. Без состояния каждый запрос отдельный и не переводит сервер в другое состояние, не переводит само соединение (или сессию) в состояние и не переводит клиента в другое состояние. На самом деле, практически все, что называется REST им не является, см. мою статью habrahabr.ru/post/204958
    4. Скорее всего Вы хотите спросить про противопоставление HTTP API и RPC API. В отличие от HTTP API (которое обычно называют по незнанию или запудрпенности мозгов REST API) удаленный вызов процедур (RPC API) для можно делать на базе TCP, UDP, TLS или эмулировать для веба на WebSocket или HTTP+SSE или других протоколах.
    Ответ написан
    2 комментария
  • [Node.JS] [node-mysql] Как возвращать значение функции?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    Не мучайтесь, а просто примите факт, что в node.js принято делать все функции, работающие с сетью, файлами и базами данных в асинхронном стиле, т.е. они возвращают значения не через return, а через callback. Перенесите свой if в callback, а лучше объявите функцию и передайте ее как callback параметр, чтобы вложенность не нарастала. Привыкнете...
    Ответ написан
    4 комментария
  • Шаблонизатор на основе node.js с хранилищем объектов в MySQL и постобработкой на webkit?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    Хотите переизобрести веб?
    1. Избавьтесь от DOM, замените его компонентами, как в Delphi и в .NET. Вообще, HTML и CSS это очень плохие технологии для приложений, которые отбросили нас на два десятилетия.
    2. Избавьтесь от HTTP, перейдите к RPC, это удобно для клиент-серверных приложений с установлением соединения, где взаимодействие через: вызов удаленных процедур и трансляцию событий.
    3. Избавьтесь от реляционных СУБД и храните объекты без декомпозиции, строя вокруг них индексы, для быстрого поиска в коллекциях.

    И да поможет Вам Аллах!
    Ответ написан
    3 комментария
  • Как вы строите архитектуру приложения?

    MarcusAurelius
    @MarcusAurelius
    автор Impress Application Server для Node.js
    Тут мой ответ по связанной теме: Как составить план проектирования проекта?
    А кроме того, хочу отметить, что начинать проект с дизайна (если Вы имеете в виду дизайн пользовательского интерфейса) это в большинстве случаев очень плохая практика. Проект нужно начинать с концепции, а потом переходить к информационной модели, потом к структурам данных (как в базе, так и в памяти) и уже потом только понятно, что на экране будет делаться. Исключение могут составлять игры, электронные книги, анимационные, интерактивные и подобные произведения, которые являются в большей степени произведением визуального искусства, чем программным продуктом. Из средств проектирования посмотрите разные реализации UML и RUP (Rational Unified Process), например Rational Rose. Вот, посмотрели, и понравилось - берите, а стало страшно - значит это Вам не нужно. Это для проектов крупных и очень крупных. Что точно нужно, так это уметь рисовать ER-диаграммы на бумажке карандашом, архитектуру модулей программной системы и железную инфраструктуру для развертывания. На большинство вопросов, которые Вы задаете, ответы можно дать только относительно конкретного проекта. Иногда нужны автоматизированные средства проектирования, иногда они не нужны и все можно сделать в уме и сэкономить время. Это очень зависит от задачи и опыта. Но что определенно, так не следует разводить лишней бюрократии,
    Ответ написан
    1 комментарий
  • Как понять что response.write закончен?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    // после res.on('data') вставляем еще обработчик:
    res.on('end', function() {
      response.end();
    });
    Ответ написан
    1 комментарий
  • Как организовать файловое хранилище пользователей (виртуальная фс или нативная)?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    А тут все зависит от количества и размера файлов, от количества пользователей и от распределения файлов по пользователям. Поясняю, если пользовтелей много (миллионы) а файлов у них мало (десятки) то у Вас будет много папок, а в них мало файлов, это не экономный расход файловой системы, будет много уходить на оглавление, и будет папка с медленным доступом (в которой лежат папки пользователей). Если пользователей мало, а файлов много, то так же, будут папки с очень большим оглавлением. Тут можно или выбрать файловую систему, которая решает эти проблемы или самому сбалансировать дерево папок, чтобы поиск был оптимальным. Как добиться оптимального поиска, сделать сбалансированную структуру папок, чтобы в каждой было не много и не мало файлов с очень различающимися названиями. Например, можно сделать 2х или 3х уровневую систему папок, в которой лежат файл переименованные в HEX, например /EA8D253F/2145AE32/F259C201 Нам нужно генерировать случайные имена папок и файлов, а потом в базу данных писать этот путь. это будет оптимально для любой файловой системы и любого кол-ва файлов, просто увеличте длину имен, алфавит и вложенность папок (в завистмости от особенности файловой системы и своих нужд, это нужно изучать). Кроме всего, это решает кучу проблем - файлы с одинаковыми именами и файлы со странными символами в именах (в том числе арабские, китайские и прочие UTF8 имена), исполняемые файлы и вообще вопрос безопасности, относительную деперсонализацию данных, и прочее... Про FTP лучше забудьте, ни какие пользователи по FTP ходить не должны, это архаичный протокол позднего проволочного века, применяемый сейчас только мной и прочими извращенцами. А если Вы еще будете вычислять для файлов хеши, несколько разных хешей на всякий случай, и хранить их вместе с именами и всеми метаданными, в базе, то можно избавиться от дублирования на диске (есть случаи, когда у разных пользователей большой процент одинаковых файлов). Вот тут кое-какие наброски: /lib/impress.files.js#L111-L174 даже файлы на винте сжимаются двумя ZIP и GZIP в зависмсти от размера. Берите, дарю методу...
    Ответ написан
  • Стоит ли писать frontend на Angular.js для проекта сложности примерно как CRM?

    MarcusAurelius
    @MarcusAurelius
    автор Impress Application Server для Node.js
    Вам нужен не фреймворк для байндинга, а библиотека контролов, типа DHTMLX dhtmlx.com или ExtJS https://www.sencha.com/
    Ответ написан
    5 комментариев
  • Repository или CQRS?

    MarcusAurelius
    @MarcusAurelius
    автор Impress Application Server для Node.js
    Вот так всегда, очаровались красивой идеей, где-то что-то понравилось, руки чешутся применить... А нужно оно или не нужно... Отталкивайтесь от того, что хотите сделать, а Вы об этом так и не рассказали, и уже потом можно переходить к тому, какую парадигму выбрать, потом выбирать паттерны, фреймворки, библиотеки (но лучше как можно меньше их конечно). Вот для чего Вам CQRS? Что он будет решать и почему без него не лучше? Вы не сможете ответить на эти вопросы если не будете идти от задачи. А потом так и выходит: "что не напишу - все контроллер выходит, это наверно потому, что я все время думаю о контроллерах" )))
    Ответ написан
    Комментировать
  • Какие библиотеки использовать для высоконагруженного приложения в Node.js?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    Общий совет, использовать как можно меньше сторонних библиотек и писать все на нодовских родных, чтобы проект не превратился в зоопарк всего чего только можно. Особенно советую не использовать принцип middleware и все, что на нем основано. Так же важно максимально использовать оперативную память, снизить необходимость ввода/вывода (минимизировать доступ к базе и файлам). И постараться писать все аккуратно и экономно, без утечек и лишних операций. Подробнее посоветовать невозможно, ведь Вы даже не намекнули, что хотите сделать, это будет высоконагруженное API или высоконагруженный сервер вебсокетов или высоконагруженный сервис для агрегации твитов, например, да что угодно.
    Ответ написан
  • Как настроить кластер на Node.js Express4 Socket.IO?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    Потоки в ноде нужно порождать при старте приложения, это можно делать при помощи require('child_process').fork а вот require('cluster').fork это просто обертка вокруг него, которая позволяет передавать сокеты из родительского процесса в дочерние, чтобы распылить нагрузку на потоки. Если Вы не хотите использовать cluster, то нужно будет самому передавать handle сокета в дочерние процессы, порожденные через require('child_process').fork, через IPC, и самостоятельно организовывать алгоритм распыления, например, простой Round Robin или взвешенный Round Robin или приклеивание по IP. Чем Вас не устраивает cluster? Еще год-два назад он работал нестабильно, согласен, сам делал к нему заплаты, но теперь то cluster работает отлично как в node.js, так и в io.js
    Ответ написан
  • Где взять хостинг для игры?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    Комментировать
  • MongoDB и NodeJs?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    function checkUserIdentity(lg, callback) {
      MongoClient.connect('mongodb://адрес', function (err, db) {
        if (err) throw err;
        db.collection('client').findOne({ login : lg }, function (err, docs) {
          if (docs) callback(null, docs._id);
          else callback(new Error("not exists"));
        });
      });
    }
    Ответ написан
    Комментировать