Частый тайм-аут с приложением с использованием Serverless Framework (AWS Lambda / Gateway), Express, Mongoose / MongoDB Atlas - PullRequest
3 голосов
/ 08 марта 2020

Предупреждение о триггере: вопрос для начинающего.

Я построил API, используя Express и Пн goose с базой данных MongoDB Atlas.

В большинстве случаев он работает нормально, но часто я получаю ошибки тайм-аута. Кажется, что это происходит очень случайно и касается всех маршрутов и т. Д. c ... Точно, я получаю:

`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

и span & log:

span and log in Serverless Dashboard

Я использовал это руководство, чтобы обернуть свое приложение 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

сервер. js файл:

const sls = require('serverless-http')
const app = require('./app')
module.exports.run = sls(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 file:

const mongoose = require('mongoose')

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

Из того, что я прочитал, это связано с холодным запуском в Lambda и тем, как API-шлюз обрабатывает тайм-ауты (!?). Я прочитал это в документации по goose (https://mongoosejs.com/docs/lambda.html), а также прочел и другие учебные пособия, но я не знаю, насколько точно я должен адаптировать его к своей ситуации.

Спасибо вы за вашу помощь

Ответы [ 2 ]

1 голос
/ 10 марта 2020

Возможно, проблема связана с вашим открытым подключением к базе данных. Пока это соединение установлено, любые вызовы callback не будут возвращены клиенту, и ваша функция будет отключена.

Вам необходимо установить context.callbackWaitsForEmptyEventLoop на false.

Здесь является объяснением из docs :

callbackWaitsForEmptyEventL oop - Устанавливается в false, чтобы сразу отправлять ответ при выполнении обратного вызова вместо ожидания события Node.js l oop чтобы быть пустым. Если это ложь, любые ожидающие события продолжают выполняться во время следующего вызова.

С помощью serverless-http вы можете довольно легко установить эту опцию в вашем файле server.js:

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

module.exports.run = sls(app, { callbackWaitsForEmptyEventLoop: false })
0 голосов
/ 09 марта 2020

Под вашим провайдером добавьте тайм-аут, максимальное значение тайм-аута в лямбде составляет 900 секунд, поместите его в соответствии с вашим временем выполнения, например, 30 секунд, и посмотрите, что произойдет

provider:
  timeout: 30

Ошибка ясно говорит, что превышено время ожидания выполнения, так как вы не настроили время ожидания, поэтому он использовал таймаут по умолчанию в 3 секунды, надеюсь, это решит проблему

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...