对node.js的并行请求,connect-mongo,会话被覆盖 [英] parallel requests to node.js, connect-mongo, session overwritten

查看:166
本文介绍了对node.js的并行请求,connect-mongo,会话被覆盖的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在当前项目(一种店铺系统)中,我使用具有 expressJS connect-mongo 的node.js作为会话存储。在客户端,我在启动时使用单个请求创建一个新的会话,然后再发送多个并发请求到node.js服务器。
因为这些并行请求改变了会话,这些变化似乎是相互覆盖的,虽然它们改变了会话的不同对象,当然是这样。

In a current project (kind of a shop system), I use node.js with expressJS and connect-mongo as session store. On client side, I use a single request at startup to create a new session and send multiple parallel requests to the node.js server afterwards. Because these parallel requests change the session, those changes seem to overwrite each other, although they change different objects of the session, of course.

3请求同时开始):


  • 请求A将某些产品推送到数组 req.session.productHist ['abc']

  • 请求B将产品推送到 req.session.productHist ['def']

  • 请求C需要一些时间,但不会更改会话

因为请求C在请求A和B之后完成,但在完成之前启动,似乎用请求C启动时保持的值(null)覆盖 session.productHist

Because request C finishes after request A and B, but starts before they finished, it seems to overwrite session.productHist with the value it held when request C started (null).

如何解决这个问题?

更新:

一些带控制台输出的示例代码:

Some example code with console output:

var url = require('url'),
    express = require('express'),
    MongoStore = require('connect-mongo');

var aDay = 24*60*60*1000;

var app = express.createServer();

app.configure(function(){
  app.use(express.cookieParser());
  app.use(express.session({
    secret: "secret",
    store: new MongoStore({ db: 'lmsCache' }),
    maxAge: aDay
    })
  );
  app.use(express.methodOverride());    app.use(express.bodyParser());
  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
  app.use(app.router);
  app.use(express.logger());
});


function sendStringified(req, res, data) {
    data = JSON.stringify(data);
    if (req.url_query.callback) { data = req.url_query.callback + "(" + data + ");"; }
    res.send(data);
}

function parseParams(req,res,next) {
  req.url_query = url.parse(req.url,true).query;
  next();
}

function doExpensiveStuff(req,res,next) {
  console.log("######################### init start");
  [...]
}


app.get('/init', parseParams, doExpensiveStuff, function(req,res) {
  console.log("init: session.productHist: " + JSON.stringify(req.session.productHist));
  console.log("######################### init end");
  sendStringified(req,res,null);
});


app.get('/products', parseParams, function(req,res) {

  console.log("######################### products "+req.url_query.category+" start");

  if(!req.session.productHist[req.url_query.category])
    req.session.productHist[req.url_query.category] = [];

  for(var i=0;i<2;i++) {
      req.session.productHist[req.url_query.category].push({ "id": new Date().toGMTString() }); 
  } 

  console.log("products: session.productHist: " + JSON.stringify(req.session.productHist));
  console.log("######################### products "+req.url_query.category+" end");
  sendStringified(req,res,[]);
});

app.get('/newSession', parseParams, function(req,res) {
  console.log("######################### newSession");
  req.session.productHist = {};
  sendStringified(req,res,true);
});  

app.listen(8080);  

time = new Date().toGMTString();  

console.log('Server starting at: ' + time);  

控制台日志:


服务器从:Thu,2011年12月15日15:50:37 GMT

Server starting at: Thu, 15 Dec 2011 15:50:37 GMT

产品:session.productHist:{-1:[{id:Thu ,2011年12月15日15:50:40 GMT},{id:星期四,2011年12月15日15:50:40 GMT}]}

products: session.productHist: {"-1":[{"id":"Thu, 15 Dec 2011 15:50:40 GMT"},{"id":"Thu, 15 Dec 2011 15:50:40 GMT"}]}



init:session.productHist:{}


init: session.productHist: {}



[...]


[...]

产品:session.productHist:{-1:[{id:星期四,2011年12月15日15:50:53 GMT},{id:星期四,十二月十五日2011 15:50:53 GMT}]}

products: session.productHist: {"-1":[{"id":"Thu, 15 Dec 2011 15:50:53 GMT"},{"id":"Thu, 15 Dec 2011 15:50:53 GMT"}]}


推荐答案

我想我已经找到了thi的答案棘手的问题。

I think I have found the answer to this tricky problem.

Express。 js 文档:

req.session上的属性会自动保存在响应

简短版本

设置会话变量( req。 session.my_var = value ),但实际上并没有保存(在那个确切的时刻),但是稍后(当你发送响应时,在你的情况下,当你执行 res。发送)。这导致了你的问题。

When you set a session variable (req.session.my_var = value), it's not actually saved then (at that exact moment), but later (when you send the response, in your case it's when you do res.send). That caused your problem.

长版本

那么这是什么意思?


  1. 您提出请求,然后获取会话变量(位于状态A),然后执行该操作(需要某些时间)

  2. 您再次发出请求并获取会话变量(由于响应尚未发送,因此仍处于状态A),并将其中的某些内容更改为

  3. 现在会话处理等已经完成,所以你发送1)的响应,从而修改会话变量并使其进入状态B

  4. 从2)发送回复后,你会发现有趣的部分。现在您实际上并没有修改当前会话(已更新为B状态),因为响应已被延迟,所以您实际更改的是A状态的会话,使其进入状态C =>,这意味着所有国家B的修改丢失了!

  1. You make a request, then get the session variable (which is in state A) and after that do something with it (that requires some time)
  2. You make another request and get the session variable (which is still in state A because the response hasn't been sent yet) and change some stuff to it
  3. Now the session processing etc has been done so you send the response from 1), thus modifying the session variable and bringing it into state B
  4. Here comes the 'fun' part, after you sent the response from 2). Now you aren't actually modifying the current session (which has been updated into state B), because the response was delayed, so what you're actually changing is the session from state A, bringing it into state C => which means all the modifications from state B were lost!

这篇关于对node.js的并行请求,connect-mongo,会话被覆盖的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆