【问题标题】:How nodejs domains actually work behind the scenes for multiple requests?nodejs 域如何在幕后为多个请求实际工作?
【发布时间】:2016-01-18 17:06:41
【问题描述】:

我的用例需要 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 Domains Explicit Binding

控制器/服务 - process.domain 将为您提供上面创建的域 您可以轻松地将值绑定到该域。例如:

process.domain.obj = {};

这个解释足以理解域的使用。

问题

  1. 将域用于多个请求是否安全?

  2. 如何保证不同请求的process.domain不同而不相同?

我也想知道continuation local storage是如何处理此类问题的

【问题讨论】:

标签: javascript node.js express thread-local-storage node.js-domains


【解决方案1】:

警告

首先 - 域已被弃用,并将在即将发布的 NodeJS 中删除。我不会使用它们编写新代码。

域如何运作?

其次 - 重要的是要理解域不是魔法。它们真的是一个简单的概念。基本上,他们:

  • 包装平台中的每个异步调用(整个 NodeJS API)。
  • 在通话期间设置一个“全局”变量。
  • 如果在该调用期间进行了另一个异步调用 - 请注意在您输入全局变量时将其设置为相同的值。
  • 就是这样。

这是实现域的方法,为简单起见,我们只为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,然后请求中调用的所有方法都可以工作,因为它们都像上面的例子一样被包装(再次,它被烘焙到节点本身)。

听起来不错,为什么要删除它们?

它们被删除是因为它们增加了实现的复杂性,而且它们存在泄漏和错误恢复的事实,在某些极端情况下它不起作用。

那我该怎么办?

您有其他选择,例如 bluebird promises 有 .bind,它带来了承诺链上下文,这是一种泄漏较少的方法。

也就是说,我会完全避免隐式全局上下文。它使重构变得困难,它使依赖关系隐含,它使代码更难推理。我只是在创建对象时将相关上下文传递给对象(简而言之,依赖注入),而不是设置全局变量。

【讨论】:

  • 感谢您的精彩解释,我知道域将很快被弃用,但我的用例需要一些类似线程本地的结构。无论如何,我会尝试探索蓝鸟绑定以适应我的用例。希望在即将发布的 node.js 版本中看到更好的域替代方案
  • @keshav 100% 坦率地说,我真的不认为很快就会出现可行的替代方案。
  • 哦!那我还有什么选择。让我们使用蓝鸟绑定,谢谢
  • @AlexanderMills 请不要那样做 :)
  • @AlexanderMills 我不讨厌域,但它们巧妙地破坏了,可能会意外破坏您的代码。 Core 不保证 Node 从捕获的域错误中恢复(但我们保证它适用于 async/await 和 Promise)。这意味着您的代码可能会以微妙的方式中断,从而导致数据损坏、连接泄漏等。如果您这样做,那么就我们保证的内容而言,所有赌注都将落空——这就是我不建议这样做的原因。我还推荐阅读trevnorris 的优秀域名事后分析。
猜你喜欢
  • 1970-01-01
  • 2015-05-18
  • 2015-09-04
  • 2014-02-21
  • 2018-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-05
相关资源
最近更新 更多