【问题标题】:Concurrent request handling in NodejsNodejs 中的并发请求处理
【发布时间】:2016-05-25 09:39:11
【问题描述】:

我有一个并发请求的问题,它修改了 db。

我在做什么。 一个请求为 user-1 获取数据,然后为 user-1 计算数据,修改记录中的字段 1,并保存。

下一个请求获取 user-1 的数据,然后计算 user-1 修改记录中的 field-1 的数据,并保存。

两个请求同时运行。所以最后一个请求更新了错误的数据。

function calculate() {
  var needUpdate = false;
  user = new UserLib(user_id);
  var old_config = user.config;
  if (old_config[req.id]) {
    old_config[req.id].value = 0;
    needUpdate = true;
  }
  if (req.delete == void(0) || req.delete == false) {
    delete req.delete;
    old_config[req.id].value = old_config[req.id].value + 1;
    needUpdate = true;
  }
  if (needUpdate) {
    return user.save();
  }
  return true;
}

我们同时收到两个请求。

  var express = require('express');
var app = express();

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

  res.writeHead(200, {
    'Content-Type': 'text/html'
  });


  calculate(req);

  function calculate(req) {

    var needUpdate = false;

    user = new UserLib(user_id);
    var old_config = user.config;

    if (old_config[req.id]) {
      old_config[req.id].value = 0;
      needUpdate = true;
    }

    if (req.delete == void(0) || req.delete == false) {
      delete req.delete;
      old_config[req.id].value = old_config[req.id].value + 1;
      needUpdate = true;
    }

    if (needUpdate) {
      user.save();
    }
  }

  res.end('Done');
});
first reuest with following parameter {
  user_id: 1,
  id: 1,
  value: 5,
  delete: false
}

Anothere request with follwing parmter {
  user_id: 1,
  id: 1,
  delete: true
}

【问题讨论】:

  • 您使用什么库来控制流?承诺或async?
  • 我们使用的是蓝鸟
  • 实际上,我认为这是无法通过承诺来处理的。如果您对此有任何解决方案,将不胜感激。
  • 错了,一切都可以通过promisification来处理。你能给我一段代码吗?我现在正在写一个一般性的答案。
  • 函数计算(){ var需要更新=假;用户 = 新用户库(user_id); var old_config = user.config; if(old_config[req.id]) { old_config[req.id].value = 0;需要更新=真; } if(req.delete == void(0) || req.delete == false){ 删除 req.delete; old_config[req.id].value = old_config[req.id].value + 1;需要更新=真; } if(needUpdate) { return user.save(); } 返回真; }

标签: node.js concurrency


【解决方案1】:

如果您想同时对每个请求进行操作,我建议您使用Bluebird.map,您可以根据需要处理每个请求,并具有并发性和最终结果。

例如:

let users = ['foo', 'bar']; //fetching users you want

Bluebird.map(users, (user) => {
   return user.calculate()
   .then((res) => res.shouldUpdate ? user.save() : Promise.resolve())
}, {concurrency: 2})
.then((results) => {
  //results is an array with both resolved promises from below
})

您可能还对Bluebird.join 感兴趣,您可以在其中计算并加入结果数据以获得多个承诺。

第二个例子,你在同一个 promise 中获取同一个用户两次:

//both are promises
Bluebird.all([fetchUser1, fetchUser2])
.spread(function(user1, user2) {
   //check if should update
   return user1.delete !== user2.delete ? user.delete() : null
})
.then(() => {})

Bluebird.spread documentation

【讨论】:

  • 其实作用是根据之前的状态更新用户的数据。假设一切都发生了,首先获取然后更新然后返回。但关键是两个服务器请求都是独立的,与承诺无关。
  • 我不明白您的请求如何不能基于承诺。 fetchUser1 不一定是承诺,它可以是您的老用户。其中fetchUser2 是请求。
猜你喜欢
  • 2018-10-15
  • 1970-01-01
  • 2018-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-16
相关资源
最近更新 更多