【问题标题】:Node concurrency / Express request lifecycle / Possible race condition?节点并发/快速请求生命周期/可能的竞争条件?
【发布时间】:2015-11-22 02:50:44
【问题描述】:

我正在构建一个多租户节点应用程序,其中租户是通过查询字符串标识的。

我还有一个 API 客户端,它根据站点发出经过身份验证的 (oauth) 请求。

我的问题是我是否可以将 API 客户端作为一个单例对象保留,并且只更新其中的会话 - 以及我是否会因为另一个请求同时进入而遇到竞争条件,而我' m 与客户端进行异步操作。

const session = new Session({ apiKey: 'xxx', secret: 'xxx' })

const client = new Client({ session })

app.use((req, res, next)=> {
  res.locals.client = client;
  next()
})

app.use((req, res, next)=> {
  let { client, db } = res.locals;
  if (req.query.tenant) {
    return db.Tenant.findOne({ tenant: req.query.tenant })
      .then((tenant)=> {
        client.updateSession({ 
          access_token: tenant ? tenant.access_token : null 
        })
        next()
      })
  }
  next();
})

app.get('/test/api', (req, res)=> {
  let { client } = res.locals;
  client.get('products').then((products)=> {
    // What if another request from another tenant comes in right here?
    // Is it possible for the session to be swapped out underneath me?
    return products.get(2).someAsyncFunc().then((product)=> {
      return res.json(product)
    })
  })
})

【问题讨论】:

  • 嗯...我确实看到client.updateSession 可能存在问题。我不知道它是做什么的,所以我不能确定。绝对看起来这将是一个问题。一种解决方案是为每个请求提供它自己的client
  • 是的,updateSession 只是在客户端实例上设置了一个道具。听起来我每个请求都需要一个新实例。

标签: node.js asynchronous express


【解决方案1】:

我的问题是我是否可以将 API 客户端保留为单例对象,并只更新其中的会话

不,为每个请求创建一个唯一的 Client 对象实例。绝对client.updateSession 看起来像是用非共享数据污染了共享对象。

只要改变这一行

res.locals.client = client;

到这里:

res.locals.client = new Client(new Session({apiKey: 'x', secret: 'x'}));

你现在应该安全了。

【讨论】:

  • 谢谢!我的怀疑是我过早地优化 - 但我只是担心在每个请求上创建新客户端的内存/效率。例如,这个客户端在它下面有大约 20 个子资源,这些子资源是在客户端运行时构建的。
猜你喜欢
  • 2021-03-26
  • 1970-01-01
  • 1970-01-01
  • 2013-04-13
  • 2022-11-18
  • 2023-01-30
  • 1970-01-01
  • 2015-08-01
  • 2013-12-31
相关资源
最近更新 更多