NodeJS / Express:访问res.locals时的并发问题

时间:2016-08-05 09:03:52

标签: node.js express

我有一个基于NodeJS,Express和Jade 4.13.4的Web应用程序。在index.js我设置了如下路线:

index.js

var express = require('express')
  , app = express()
  , companyroutes = require('./routes/company')
(...)
app.use('/company/', companyroutes)

路由/ company.js

var express = require('express')
  , router = express.Router()

router.all('/:id*', function(req, res, next) {
  res.locals.companyUri = '/company/' + req.params.id;

  async.parallel([
    // company data
    function(done){
      api.getCompany(req.params.id, req.user, done)
    },
    // user follows data
    function(done){
      api.follows(req.params.id, req.user, 'company', done))
    }
  ],
  function(err, result){
    if (err){
      return next(err)
    }

    res.locals.company = result[0]
    res.locals.userFollows = result[1]

    company.getCompanyOverview(res.locals.company, function(err, results){
      if (err) {
        return next(err)
      }
      debug('render company overview')
      res.render('company-overview', results)
    })

  })

});

module.exports = router;

正如您所看到的,我有一条路由用作中间件,执行以下操作:

  • 使用从API的两次异步并行调用收到的一般公司数据(res.localscompany来丰富userFollows
  • 再次调用company.getCompanyOverview,使用async.parallel包含对API的更多调用。收到的数据存储在results
  • 使用company-overview渲染玉视图results

到目前为止一切顺利。当对http://localhost:3000/company/companyA进行一次调用时,会从API中获取所有数据,并通过呈现模板正确显示companyA的数据。

但是,对于并发请求,行为是不同的。我在OSX下使用ApacheBench通过请求另一家公司来对服务器施加一些负担:

brew install parallel
echo /company/companyB | parallel 'ab -c 10 -n 5000 http://localhost:3000{}'

使用浏览器访问网站http://localhost:3000/company/companyA时,会显示companyB的基本数据,而不是companyA

Express Docs明确指出res.locals的范围限定为单个请求的生命周期:

  

包含作用域的响应局部变量的对象   请求,因此仅适用于在期间呈现的视图   请求/响应周期(如果有的话)。

但是对我而言,似乎res.locals被ApacheBench的请求覆盖了。从另一台机器运行AB时也是如此!

我已经在这方面投入了太多时间,但我仍然没有得到它。这是Express中的错误还是我做错了什么?

使用的版本

$ node -v
v4.2.2

$ npm list express
moneyhouse@1.1.1-dev.2 /Users/dani/Documents/mh-web
├─┬ browser-sync@2.13.0
│ └─┬ browser-sync-ui@0.6.0
│   └─┬ weinre@2.0.0-pre-I0Z7U9OV
│     └── express@2.5.11 
└── express@4.13.4 

$ npm list jade
moneyhouse@1.1.1-dev.2 /Users/dani/Documents/mh-web
├── jade@1.11.0 
└─┬ jade-glob-include@1.0.1
  └── jade@1.3.1 

1 个答案:

答案 0 :(得分:1)

我遇到了同样的错误。最终看起来它是由我首先设置res.local的原因引起的。 我有一个简单的=运算符

res.local.VALUE = req.VALUE.

' ='不会像您期望的那样分配变量,而是仅引用req.VALUE,这意味着当并发请求进入并且req.VALUE更新时,该值可能会被交换。

我通过克隆对象来解决这个问题:

res.local.VALUE = _.clone(req.VALUE) //using underscore

所以res.local.VALUE不再依赖于req,而是它自己的对象。