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 viewcompany-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绑定,而是它自己的对象。