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

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

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; 

正如你所看到的,我有一个单独的路由,用作中间件,执行以下操作:

  • 使用一些通用的公司数据( company和用户userFollows从两个asynchronous并行调用API接收)来丰富res.locals
  • 再次调用company.getCompanyOverview ,它使用async.parallel封装了更多API的async.parallel 。 接收到的数据存储在results
  • 使用results呈现Jade view company-overview

到现在为止还挺好。 当对http://localhost:3000/company/companyA进行一次调用时,将从API中提取所有数据,并通过呈现模板正确显示companyA的数据。

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

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

使用浏览器访问站点http://localhost:3000/company/companyA companyB将显示companyB的基础数据,而不是companyB

Express Docs明确指出res.locals的范围是一个请求的生命周期:

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

对我来说,它看起来像res.locals被ApacheBench的请求覆盖。 从另一台机器上运行AB也是这种情况!

我已经投入太多时间了,我还是不明白。 这是快递中的错误还是我做错了什么?

使用的版本

 $ 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 

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

 res.local.VALUE = req.VALUE. 

'='不会像你所期望的那样分配一个variables,而只会引用req.VALUE,这意味着当并发请求进来和req.VALUE更新时,可以交换值。

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

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

所以res.local.VALUE不再与req绑定,而是它自己的对象。