首页 > 解决方案 > 对 Express JS 的并发请求失败。需要解释发生了什么

问题描述

嗨,我有一个在 AWS Fargate 上运行的 expressjs 服务器,它处理对不同服务的许多 API 调用,并将它们聚合成一个单一的响应返回给客户端。

我的问题是,我发现当我在同一时间收到对同一端点的请求时,这些请求中至少有一个会失败。这种行为非常奇怪,所以我需要一些帮助来解释正在发生的事情,并希望如何解决这个问题。

首先,这是我的路线设置方式的伪代码:

router.post( '/endpoint', async function (req, res, next) {
  try {
    let uId = req.body.uId
    let logId = req.body.logId

    let user = await axios(uId) //call to database to retrieve user information (appsync)
    console.log(logId, user)

    let data = []

    for (i = 0, i<user.accounts.length, i++) {
      if (user.accounts[i].provider === 'google') {
        let googleInfo = await axios(user.accounts[i]) // calls google API 
        console.log(logId, user.accounts[i], i , googleInfo)
        data.push(googleInfo)

      } else if (user.accounts[i].provider === 'microsoft') {
        let microsoftInfo = await axios(user.accounts[i]) // calls microsoft graph API
        console.log(logId, user.accounts[i], i , microsoftInfo)
        data.push(microsoftInfo)

      }
    }

    let response = processDataFunction(data) // some function that processes the data

    res.json(response)
  } catch (e) {
    next(e)
  }
})

当只有一个请求时,这一切都正常工作。但是,当 2 个或更多同时访问我们的端点时,服务器会响应 500 服务器错误,这就是我在 cloudwatch 日志中看到的内容。

dateTime1: request1, user: {}
dateTime2: request1, user.accounts[0], 0, googleInfo: {user.accounts[0]}
dateTime3: request1, user.accounts[1], 1, microsoftInfo: {user.accounts[1]}
dateTime4: request1, user.accounts[2], 2, googleInfo: {user.accounts[3]}
dateTime5: error ......
dateTime6: request2, user.accounts[0], 0, googleInfo: {user.accounts[0]}
dateTime7: request2, user.accounts[1], 1, microsoftInfo: {user.accounts[1]}
dateTime8: request2, user.accounts[2], 2, googleInfo: {user.accounts[2]}
dateTime9: request2, user.accounts[3], 3, googleInfo: {user.accounts[3]}

该错误是由 microsoft/google 服务器出错引起的,因为我正在为 请求资源user.accounts[3],此时循环和访问令牌仍在user.accounts[2](请参阅 dateTime4)

通过增加 ECS 中正在运行的任务数量,我能够部分解决此问题。我最终能够同时处理更多并发请求。然而,在某一点上,同样的错误仍然会发生。

任何解释为什么会发生这种情况,是我增加 ECS 任务数量的唯一解决方法吗?

标签: node.jsexpressconcurrencyaxiosaws-fargate

解决方案


对于遇到同样问题的任何人。我仍然不知道发生了什么,但我能够通过将所有 for 循环转换为:

Promise.all(arr.map( async(item) => { 
  return await axios( // request )
}))

推荐阅读