从 NodeJS AWS Lambda 函数查询 MySQL 数据库

Posted

技术标签:

【中文标题】从 NodeJS AWS Lambda 函数查询 MySQL 数据库【英文标题】:Querying a MySQL database from a NodeJS AWS Lambda Function 【发布时间】:2017-07-24 07:33:39 【问题描述】:

在我的 AWS Lambda 函数中查询我的 mysql 数据库(从 AWS 远程托管)时遇到问题。

这是我的代码,除了 Lambda 函数的其余部分(正在调用 Alexa 技能)所需的部分:

  var mysql = require('mysql');
  var connection = mysql.createConnection(
        host     : '<myserver>',
        user     : '<myusername>',
        password : '<mypw>',
        database : '<mydatabase>'
  );
  connection.connect(function(err)
        if(!err) 
              console.log("Database is connected ... nn");
        
        else 
              console.log("Error connecting database ... nn");
        
  );

  connection.query("INSERT INTO Users (user_id) VALUES ('TESTNAME')");
  connection.end();

当我在命令提示符下使用 node 运行它时效果很好:

node index.js

我正在使用通过 npm 在 index.js 目录中安装的“mysql”模块并将其压缩并上传到我的 Lambda 函数。

同样,这适用于我的开发机器,但在测试我的 Lambda 函数时没有提供任何指标来说明为什么它根本不影响我的数据库。

我的问题延伸到 Alexa 和 Lambda,就像正确使用 mysql Node.JS 模块一样。

这是我当前的 Lambda 代码,当然,这里的问题仍然是我的测试值 -> 一个名为“TESTNAME”的用户名没有添加到我的 MySQL 数据库中。

我按照第一条评论的建议将查询放入连接回调中,并且我将我的新代码而不是更新我的旧代码放在上面只是为了记录我认为代码应该如何转换到我的Alexa 的 Lambda 函数:

更新代码:

var mysql = require('mysql');
var connection = mysql.createConnection(
      host     : '<myserver>',
      user     : '<myusername>',
      password : '<mypw>',
      database : '<mydatabase>'
);
exports.handler = (event, context) => 
    try 

        if (event.session.new) 
            // New Session
            console.log("NEW SESSION");
        


        switch (event.request.type) 

            case "LaunchRequest":
                // Launch Request
                console.log(`LAUNCH REQUEST`);
                context.succeed(
                    generateResponse(,
                        buildSpeechletResponse("Welcome to an Alexa Skill, this is running on a deployed lamda function", true)
                    )
                );
                break;

            case "IntentRequest":
                // Intent Request
                console.log(`Intent Request`);
                console.log('Then run MySQL code:');
                connection.connect(function(err) 
                    console.log('Inside connection.connect() callback');
                    if (!err) 
                        console.log("Database is connected ... ");
                        connection.query("INSERT INTO Users (user_id) VALUES ('TESTNAME')",
                            function(err, result) 
                                console.log("Inside connection.query() callback")
                                if (!err) 
                                    console.log("Query Successful! Ending Connectection.");
                                    connection.end();
                                 else 
                                    console.log("Query error!");
                                
                            );
                     else 
                        console.log("Error connecting database ..." + err.message);
                    
                );
                context.succeed(
                    generateResponse(,
                        buildSpeechletResponse("Welcome to the incredible intelligent MySQLable Alexa!", true)
                    )
                );

                break;

            case "SessionEndedRequest":
                // Session Ended Request
                console.log(`SESSION ENDED REQUEST`);
                break;

            default:
                context.fail(`INVALID REQUEST TYPE: $event.request.type`);

        

     catch (error) 
        context.fail(`Exceptiodn: $error`)
    

;

//Helpers
buildSpeechletResponse = (outputText, shouldEndSession) => 

    return 
        outputSpeech: 
            type: "PlainText",
            text: outputText
        ,
        shouldEndSession: shouldEndSession
    ;
;

generateResponse = (sessionAttributes, speechletResponse) => 
    return 
        version: "1.0",
        sessionAttributes: sessionAttributes,
        response: speechletResponse
    ;
;

还有我的控制台输出:

START RequestId: 5d4d17a7-0272-11e7-951c-b3d6944457e1 Version: $LATEST
2017-03-06T13:39:47.561Z    5d4d17a7-0272-11e7-951c-b3d6944457e1    Intent Request
2017-03-06T13:39:47.562Z    5d4d17a7-0272-11e7-951c-b3d6944457e1    Then run MySQL code:
END RequestId: 5d4d17a7-0272-11e7-951c-b3d6944457e1
REPORT RequestId: 5d4d17a7-0272-11e7-951c-b3d6944457e1  Duration: 82.48 ms  Billed Duration: 100 ms     Memory Size: 128 MB Max Memory Used: 14 MB  

【问题讨论】:

您应该在连接回调中运行查询。在这里,您将connect() 视为以某种方式同步,但事实并非如此,因此当您运行query() 时,您可能会或可能尚未连接,这对您来说是偶然的。您还忽略了query() 可能会产生的任何错误。 我是否也应该在回调中结束连接? 我更新了我的问题,提供了有关我的问题的全部范围的更多信息,并通过将我的查询放入我的连接回调中添加了我认为您的意思。我会尽快处理我的函数的错误处理,因为我可以将它发布到我的 MySQL 数据库,因为据我所知,在测试 lambda 函数时我没有得到控制台输出,所以它会是在这一点上有点无益。 好吧,您对控制台的看法不正确。 Lambda 控制台输出记录到 CloudWatch Logs,因此非常有用。断开连接需要在来自query() 的(当前不存在的)回调中。 你是对的,整洁!好的,我已经在我的问题中更新了我的 lambda 代码。由于某种原因,它没有进入我的连接回调...... 【参考方案1】:

问题是我需要将 context.succeed 放入我的回调中。非常感谢 sqlbot,因为他谈到回调让我研究了事情实际上在哪里结束了它们的执行。

显然,在使用 AWS Lambda 时,如果“上下文”在您的回调被调用之前结束,您将不会收到回调。因此,即使我已经像这样放置了所有回调:connect -> query -> end,来自 connect 的链的第一个回调永远不会被调用,因为之后立即调用“context.succeed”,从而结束了执行。

这是我现在的代码(现在正在发生正确的查询):

var mysql = require('mysql');
var connection = mysql.createConnection(
    ...
);

exports.handler = (event, context) => 
    try 

        if (event.session.new) 
            // New Session
            console.log("NEW SESSION");
        


        switch (event.request.type) 

            case "LaunchRequest":
                // Launch Request
                console.log(`LAUNCH REQUEST`);
                context.succeed(
                    generateResponse(,
                        buildSpeechletResponse("Welcome to an Alexa Skill, this is running on a deployed lamda function", true)
                    )
                );
                break;

            case "IntentRequest":
                // Intent Request
                console.log(`Intent Request`);
                console.log('Then run MySQL code:');
                connection.connect(function(err) 
                    console.log('Inside connection.connect() callback');
                    if (!err) 
                        console.log("Database is connected ... ");
                        connection.query("INSERT INTO Users (user_id) VALUES ('TESTNAME')",
                            function(err, result) 
                                console.log("Inside connection.query() callback")
                                if (!err) 
                                    console.log("Query Successful! Ending Connection.");
                                    connection.end();
                                 else 
                                    console.log("Query error!");
                                
                            );
                     else 
                        console.log("Error connecting database ..." + err.message);
                    
                    context.succeed(
                        generateResponse(,
                            buildSpeechletResponse("Welcome to the incredible intelligent MySQLable Alexa!", true)
                        )
                    );
                );

                break;

            case "SessionEndedRequest":
                // Session Ended Request
                console.log(`SESSION ENDED REQUEST`);
                break;

            default:
                context.fail(`INVALID REQUEST TYPE: $event.request.type`);

        

     catch (error) 
        context.fail(`Exceptiodn: $error`)
    

;

//Helpers
buildSpeechletResponse = (outputText, shouldEndSession) => 

    return 
        outputSpeech: 
            type: "PlainText",
            text: outputText
        ,
        shouldEndSession: shouldEndSession
    ;
;

generateResponse = (sessionAttributes, speechletResponse) => 
    return 
        version: "1.0",
        sessionAttributes: sessionAttributes,
        response: speechletResponse
    ;
;

【讨论】:

您是如何从自定义插槽中获得价值的?尝试将值获取为“event.slots..value”时出现错误。我什至尝试过“event.request.type.slots.value”。

以上是关于从 NodeJS AWS Lambda 函数查询 MySQL 数据库的主要内容,如果未能解决你的问题,请参考以下文章

使用nodejs中的AWS Lambda函数上传音频文件

AWS Lambda nodejs 函数中的事件对象为空

使用 AWS Lambda (NodeJS) 创建 AWS AppSync

适用于 postgreSQL 的 AWS Lambda 函数 NodeJs - 超时错误

ReactJS - NodeJS - 在 AWS Lambda 上连接到 Graphql 的问题

AWS Lambda - Nodejs:分配失败 - JavaScript 堆内存不足