Как домены nodejs на самом деле работают за кулисами для нескольких запросов?

Мой вариант использования требует, чтобы домены node.js обменивались информацией между файлами сервера на уровне запроса.

Пример реализации в express.js

domain = require('domain');

app.use(function(req, res, next) {
    var reqDomain = domain.create();
    reqDomain.add(req);
    reqDomain.add(res);
    reqDomain.run(next);
});

Более подробное объяснение на явной привязке доменов Nodejs

В контроллере / сервисе - process.domain предоставит вам созданный выше домен и вы сможете легко привязать значения к этому домену. Например:

process.domain.obj = {};

Это объяснение достаточно, чтобы понять использование доменов.

Вопросы

  1. Безопасно ли использовать домены для нескольких запросов?

  2. Как убедиться, что process.domain отличается для разных запросов и не одинаково?

Также хотелось бы узнать, как такие проблемы решаются при продолжении локального хранения

1 ответ

Решение

Предупреждение

Прежде всего - домены устарели и будут удалены в следующем выпуске NodeJS. Я бы не писал новый код используя их.

Как работают домены?

Во-вторых, важно понимать, что домены - это не волшебство. Они действительно простая концепция. В основном они:

  • Оберните каждый асинхронный вызов в платформе (все API-интерфейсы NodeJS).
  • Установите "глобальную" переменную на время разговора.
  • Если во время этого вызова был сделан другой асинхронный вызов - запомните, чтобы при вводе глобальной переменной было установлено то же значение.
  • Вот и все.

Вот как можно реализовать домены, давайте реализовывать их только для setTimeout для простоты.

const oldTimeout = setTimeout;
setTimeout = function(fn, ms) { // also ...args, but let's ignore that
    var trackedDomain = domain;
    oldTimeout(function() { 
      var oldDomain = domain; // preserve old context
      domain = trackedDomain; // restore context to "global" variable
      fn(); // call the function itself
      domain = oldDomain; // restore old context
    }, ms); // that's it!
};

Что-то вроде express можно просто сделать domain = new RequestContext в начале, а затем все методы, вызываемые в запросе, будут работать, поскольку все они обернуты, как в примере выше (так как он снова запекается в самом узле).

Это звучит зыбко, зачем убирать их?

Их удаляют из-за сложности реализации, которую они добавляют, а также из-за утечки и восстановления после ошибок в некоторых случаях, когда это не работает.

Так что мне делать?

У вас есть альтернативы, например, обещания синей птицы .bind который приносит контекст цепочки обещаний, который является менее протекающим способом сделать это.

Тем не менее, я бы просто избегал неявного глобального контекста. Это усложняет рефакторинг, делает неявными зависимости и затрудняет анализ кода. Я просто передаю релевантный контекст объектам, когда создаю их (внедрение зависимости, в двух словах), а не задаю глобальную переменную.

Другие вопросы по тегам