当我查询 MySQL 并尝试通过 AWS SES 发送电子邮件时,节点 Lambda 超时

Node Lambda times out when I query MySQL and try to send an email via AWS SES

我有以下节点代码

'use strict';
var aws = require('aws-sdk');
var async = require('async');
const mysql = require('mysql');

var ses = new aws.SES({
  region: 'eu-west-1'
});

module.exports.helloWorld = function(event, context, callback) {
  //context.callbackWaitsForEmptyEventLoop = false; //Updated on @dashmug recommendation
  console.log("Hit here 1");
  let connection = mysql.createConnection({
    host: "xxx",
    user: "xxx",
    password: "xxx",
    database: "xxx"
  });
  connection.connect(); //Updated on @dashmug recommendation
  console.log("Hit here 2");
  connection.query(`SELECT * FROM User U WHERE id = 1`, function(error, row) {

    console.log("Hit here 3");
    console.log(row);
    let eParams = {
      Destination: {
        ToAddresses: [row[0].email]
      },
      Message: {
        Body: {
          Html: {
            Data: "Test"
          },
          Text: {
            Data: "Test"
          }
        },
        Subject: {
          Data: "Test Email"
        }
      },
      Source: "team@hello.com"
    };
    console.log("Hit here 4");
    connection.end(); //Updated on @dashmug recommendation
    console.log('===SENDING EMAIL===');
    var email = ses.sendEmail(eParams, function(err, data) {
      if(err) {
        console.log(err);
        //context.fail(err);
        callback(err); //Updated on @dashmug recommendation
      } else {
        console.log("===EMAIL SENT===");
        console.log("EMAIL CODE END");
        console.log('EMAIL: ', email);
        console.log(data);
        callback(null, event); //Updated on @dashmug recommendation
      }
    });
  });
}

Note: My SES default limits are removed. Also I did try to move connection.end() inside the results callback. I get the same result.

此代码总是超时。我的云看日志

{
  "errorMessage": "2018-01-19T11:58:16.794Z cc9e6998-fd0f-11e7-ae0a-xxxx Task timed out after 100.06 seconds"
}

    START RequestId: e60d142a-01c2-11e8-99da-fb3cb3a59816 Version: $LATEST
2018-01-25T11:28:43.928Z    e60d142a-01c2-11e8-99da-fb3cb3a59816    Hit here 1
2018-01-25T11:28:44.163Z    e60d142a-01c2-11e8-99da-fb3cb3a59816    Hit here 2
2018-01-25T11:28:44.207Z    e60d142a-01c2-11e8-99da-fb3cb3a59816    Hit here 3
2018-01-25T11:28:44.164Z    e60d142a-01c2-11e8-99da-fb3cb3a59816    Hit here 4
2018-01-25T11:28:44.209Z    e60d142a-01c2-11e8-99da-fb3cb3a59816    [ RowDataPacket {
    id: 1,
    name: 'Karthik',
    email: 'xxx@xxx.com' } ]
2018-01-25T11:28:44.223Z    e60d142a-01c2-11e8-99da-fb3cb3a59816    ===SENDING EMAIL===
END RequestId: e60d142a-01c2-11e8-99da-fb3cb3a59816
REPORT RequestId: e60d142a-01c2-11e8-99da-fb3cb3a59816  Duration: 100038.81 ms  Billed Duration: 100000 ms  Memory Size: 512 MB Max Memory Used: 54 MB  
2018-01-25T11:30:23.965Z e60d142a-01c2-11e8-99da-fb3cb3a59816 Task timed out after 100.04 seconds

我的无服务器配置。

service: test
provider:
  name: aws
  runtime: nodejs6.10
  stage: dev
  region: eu-west-1
  memorySize: 512
  timeout: 100
  iamRoleStatements:
    - Effect: Allow
      Action:
        - s3:*
        - SNS:Publish
        - SES:SendRawEmail
        - SES:SendEmail
        - lambda:InvokeFunction
      Resource: "*"
  environment:
    NODE_ENV: live
  vpc:
    securityGroupIds:
      - sg-xxx
      - sg-xxx
      - sg-xxx
      - sg-xxx
    subnetIds:
      - subnet-xxx
      - subnet-xxx
      - subnet-xxx
functions:
  emailEmailFeedback:
    handler: handler.helloWorld
    events:
      - http:
          path: user-feedback
          method: get
          cors: true

Note: The VPC config is for my MySQL connection. I only have one VPC and all my services are within it.

当我取出 MySQL 查询和 运行 我的 SES 测试电子邮件时,函数 运行s 成功。

此外,当我取出 SES 并 运行 MySQL 时,我成功地得到了结果。

但他们不能一起工作。

我还尝试将 SES 移动到另一个函数,并尝试从我的 MySQL 查询回调中调用 sendEmail 函数,它没有用,我得到了同样的超时错误。

lambda.invoke({
            FunctionName: 'sendEmail',
            Payload: JSON.stringify(rows, null, 2) // pass params
        }, function(error, data) {
            if (error) {
                context.fail({"hello": "world"});
            }
            if(data.Payload){
                context.succeed({"hello": "world"});
            }
        });

如有任何帮助,我们将不胜感激。

使用 callback() 而不是 context.succeed()context.fail()。这些上下文方法已弃用。

根据https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-using-old-runtime.html#transition-to-new-nodejs-runtime,

Node.js runtime v0.10.42 does not support the callback parameter for your Lambda function that runtimes v4.3 and v6.10 support. When using runtime v0.10.42, you use the following context object methods to properly terminate your Lambda function. The context object supports the done(), succeed(), and fail() methods that you can use to terminate your Lambda function. These methods are also present in runtimes v4.3 and v6.10 for backward compatibility.

因此,在您对 sendMail() 的回调中,它变成了...

if(err) {
    console.log(err);
    callback(err);
} else {
    console.log("===EMAIL SENT===");
    console.log("EMAIL CODE END");
    console.log('EMAIL: ', email);
    console.log(data);
    callback(null, event);
}

另一件事,你不需要context.callbackWaitsForEmptyEventLoop = false;

此外,由于您连接到数据库 inside 您的处理程序,您还需要在获得结果后断开与它的连接。