Пуленепробиваемый Node.js

в 10:13, , рубрики: javascript, node.js, отказоустойчивость, метки: , ,

Проблемы индейцев
Одним из остававшихся до недавнего времени недостатком Node.js, который отпугивал бекенд-разработчиков от использования Node.js был тот факт, что непойменное исключение в потоке рушила воркера и все клиенты, которые ждали от него ответа не получали ничего.

tl;dr Eсть новое API для асинхронного trycatch. Из статьи можно скопипастить пример и поиграться.

Рассмотрим ситуацию:
У нас есть запрос к веб серверу ноды, в процессе обработки данных, полученных из базе данных происходит какая-то проблема (неверные параметры, которые нельзя валидировать, отвалилась стойка с базой данных, или просто невнимательность) — возникает ошибка. До начала нашего запроса было 5 запросов от других клиентов и у них начала грузиться страница. После запроса поступало еще 10 запросов от других пользователей. И вот она ошибка, в недрах коллбеков одного из параллельно выполняющихся запросов. Отваливаются все 16 запросов. Страдают невинные.

Можно было бы создавать на каждый запрос отдельного воркера, но это очень накладно по ресурсам.
Можно оберунть опасный кусок в trycatch, но на сложных системах это просто невозможно.
Можно на свой страх и риск надеяться что все будет верно, а потери будут не велики.

Не канонично.

Да приидет Domain
Итак, в версии 0.8 появилась серебрянная пуля, мастер отлова ошибок, непревзайденный Domain. На данный момент API находиться в статусе unstable, но уже им можно пользоваться.

Простой пример:

var domain = require('domain'),
    server = require('http').createServer(function(req, res) {
        
        // Создаем домен
        var d = domain.create();

        // Вешаем обработчик ошибки, который вернет 500й статус и текст проблемы
        d.on('error', function(err) {
            console.error('error', err.stack);
            res.statusCode = 500;
            res.setHeader('content-type', 'text/plain');
            res.end('Houston, we have a problem!n');
        });

        // Добавляем наши переменные, которые тоже могут сгенерировать ошибки самостоятельно
        d.add(req);
        d.add(res);
        
        // Запускаем потенциально опасный код внутри домена
        d.run(function () {
          switch(req.url) {
          case '/error':
              setTimeout(function() {
                   // Вызываем ошибку - несущуетвующий метод необъявленной переменной
                   uncaught.error();
              });
              break;
          default:
              res.end('ok');
          }
        });
   });
server.listen(8080);

запустив этот простой скрипт, перейдя по корневому адресу у нас все ок, а вот если перейти по адресу /error вы увидите в консоле лог ошибки, а в браузере корректное сообщение, что что-то пошло не так и статус 500.

P.S. Простите за орфографию и пунктуцию, буду рад указанию на ошибки.

Автор: asci

Источник

Поделиться

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