【问题标题】:Frequent timeout with app using Serverless Framework (AWS Lambda/Gateway), Express, Mongoose/MongoDB Atlas使用无服务器框架(AWS Lambda/Gateway)、Express、Mongoose/MongoDB Atlas 的应用程序频繁超时
【发布时间】:2020-06-20 14:50:05
【问题描述】:

触发警告:初学者问题。

我使用 Express 和 Mongoose 以及 MongoDB Atlas DB 构建了一个 api。

大多数时候,它可以正常工作,但我经常遇到超时错误。这似乎是非常随机发生的,并且涉及所有路线等......确切地说,我得到:

`502 Internal server error via POSTMAN`

在无服务器仪表板中,我得到:

invocation
time invoked 1 day ago, mar 08 at 1:38pm
fatal error Function execution duration going to exceeded configured timeout limit.
cold start
duration 48.9 s
memory used na

request
endpoint /{proxy+}
method POST
status 502
message Internal server error
latency 27 ms

以及跨度和日志:

我使用本教程来包装我的 express 应用程序以使用无服务器框架进行部署:https://dev.to/adnanrahic/a-crash-course-on-serverless-apis-with-express-and-mongodb-193k

Serverless.yml 文件:

service: serviceName
app: appName
org: orgName

provider:
  name: aws
  runtime: nodejs12.x
  stage: ${env:NODE_ENV}
  region: eu-central-1
  environment:
    NODE_ENV: ${env:NODE_ENV}
    DB: ${env:DB}

functions:
  app:
    handler: server.run
    events:
      - http:
          path: /
          method: ANY
          cors: true
      - http:
          path: /{proxy+}
          method: ANY
          cors: true

plugins:
  - serverless-offline # Utiliser pour tester localement
  - serverless-dotenv-plugin

server.js 文件:

const sls = require('serverless-http')
const app = require('./app')
module.exports.run = sls(app)

app.js 文件:

const express = require('express')
const cors = require('cors')
const bodyParser = require('body-parser')

const newRoutes = require('./routes/file')

const app = express()

app.use(bodyParser.json())
const helmet = require('helmet')
app.use(helmet())

app.options('*', cors())
app.use(cors({ allowedHeaders: 'Content-Type, Authorization' }))

app.use('/new-route', newRoutes)

app.use((error, req, res, next) => {
  console.log(error)
  const status = error.status || 500
  const message = error.message
  res.status(status).json({
    status: status,
    message: message
  })
})

// Gère la connexion à la base de donnée :
require('./db')

module.exports = app

最后是 db.js 文件:

const mongoose = require('mongoose')

mongoose
  .connect(
    process.env.DB, {
      useNewUrlParser: true,
      useUnifiedTopology: true
    })
  .then(() => {
    console.log('connected')
  })
  .catch(err => console.log(err))

根据我的阅读,这与 Lambda 中的冷启动和 API Gateway 处理超时的方式有关(!?)。我已经在 mongoose 文档 (https://mongoosejs.com/docs/lambda.html) 上阅读了此内容,还阅读了其他教程,但我不知道我应该如何将其适应我的情况。

感谢您的帮助

【问题讨论】:

  • 我会看看如何管理数据库连接,也许这可能会有所帮助:github.com/dougmoscrop/serverless-http/issues/…
  • 嗯,这很有趣 - 看起来您链接到的调用只运行了几个 MS: 持续时间:4.60 毫秒 您能否在无服务器仪表板上发布此调用的屏幕截图,包括日志和跨度报告?
  • 我按照@AaronStuyvenberg 的要求,用屏幕截图和更多信息更新了帖子。
  • @noetix,我读过“ctx.callbackWaitsForEmptyEventLoop = false”,但我不明白它是如何工作的以及我应该如何将它应用到我的情况。如果您有更准确的想法,请告诉我。

标签: express mongoose aws-lambda aws-api-gateway serverless-framework


【解决方案1】:

问题可能是由于您打开的数据库连接造成的。建立此连接后,任何对 callback 的调用都不会返回给客户端,并且您的函数将超时。

您需要将context.callbackWaitsForEmptyEventLoop 设置为false

这里是docs的解释:

callbackWaitsForEmptyEventLoop – 设置为 false 以在回调执行时立即发送响应,而不是等待 Node.js 事件循环为空。如果为 false,则任何未完成的事件将在下一次调用期间继续运行。

使用serverless-http,您可以在server.js 文件中轻松设置此option

const sls = require('serverless-http')
const app = require('./app')

module.exports.run = sls(app, { callbackWaitsForEmptyEventLoop: false })

【讨论】:

  • 这似乎解决了问题。我(几乎)没有更多的超时。如果我有更多消息,我会继续关注这个问题并回来。谢谢
【解决方案2】:

根据您的提供程序添加超时,lambda 中的超时最大值为 900 秒,根据你的执行时间放置,比如 30 秒 看看会发生什么

provider:
  timeout: 30

错误很明显是执行超时,因为你没有配置超时,所以它使用了默认的 3 秒超时,希望它能解决问题

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-04
    • 2020-03-12
    • 2021-10-07
    • 2019-10-12
    • 2017-02-17
    • 1970-01-01
    • 2022-10-13
    • 2017-11-16
    相关资源
    最近更新 更多