Одновременные запросы на выражение JS завершаются неудачно. Нужно объяснить, что происходит

#node.js #express #concurrency #axios #aws-fargate

Вопрос:

Привет, у меня есть сервер expressjs, работающий на AWS Fargate, который обрабатывает множество вызовов 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?

Ответ №1:

Для всех, кто сталкивается с такой же проблемой. Я все еще не знаю, что происходит, но я смог это исправить, превратив все мои циклы for в:

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