从 Lambda 函数(SAM 应用程序)连接到 SQL 服务器 RDS 数据库?

Connect to an SQL Server RDS database from a Lambda function (SAM App)?

var sql = require("mssql");

const config = {
    user: 'username',
    password: 'password', 
    server: 'mssql-instance.cmujwb4lclgy.us-east-1.rds.amazonaws.com',
    database: 'mssql-instance',
    port: 1433
};

exports.clock = async(event) => {
    
    console.log('Connecting to the rds..')
    let message = "Not Connected"

    sql.connect(config, function (err) {
        if (err) console.log(err);

        let sqlRequest = new sql.Request();

        let sqlQuery = "SELECT * from InexistantTable where InexistantId = 0;"

        message = "Connected"

        sqlRequest.sqlQuery(sqlQuery, function(err, data) {
            if (err) console.log(err)

            console.table(data.recordset);
            message = "Connected, attempted query."

            sql.close();
        });
    });

    const response = {
        statusCode: 200,
        body: JSON.stringify("SQL Server: " + message)
    }

    return response;
}

我得到这个日志

2022-01-25T21:47:01.796Z    c3c94b7f-92a9-4b90-8cc4-fe208fff611a    INFO    ConnectionError: Failed to connect to mssql-instance.cmujwb4lclgy.us-east-1.rds.amazonaws.com:1433 in 15000ms
    at /var/task/node_modules/mssql/lib/tedious/connection-pool.js:71:17
    at Connection.onConnect (/var/task/node_modules/tedious/lib/connection.js:1043:9)
    at Object.onceWrapper (events.js:520:26)
    at Connection.emit (events.js:400:28)
    at Connection.emit (/var/task/node_modules/tedious/lib/connection.js:1071:18)
    at Connection.connectTimeout (/var/task/node_modules/tedious/lib/connection.js:1530:10)
    at Timeout._onTimeout (/var/task/node_modules/tedious/lib/connection.js:1475:12)
    at listOnTimeout (internal/timers.js:557:17)
    at processTimers (internal/timers.js:500:7) {
  code: 'ETIMEOUT',
  originalError: ConnectionError: Failed to connect to mssql-instance.cmujwb4lclgy.us-east-1.rds.amazonaws.com:1433 in 15000ms
      at ConnectionError (/var/task/node_modules/tedious/lib/errors.js:13:12)
      at Connection.connectTimeout (/var/task/node_modules/tedious/lib/connection.js:1530:54)
      at Timeout._onTimeout (/var/task/node_modules/tedious/lib/connection.js:1475:12)
      at listOnTimeout (internal/timers.js:557:17)
      at processTimers (internal/timers.js:500:7) {
    code: 'ETIMEOUT'
  }
}

它位于默认 VPC 中,因此我认为我不需要执行任何安全组或角色。研究这个也很混乱。

如果我必须设置它,我应该在哪里设置?在 VPC 仪表板中?直接在 Lambda 函数中还是在 RDS 实例本身?我是否将它与 RDS 或 Lambda 相关联?入站还是出站?

此外,我正在使用数据库实例名称进行连接。我使用另一个指南创建了一个 MySQL RDS 并且有一个地方我也给了它一个数据库名称,这是我用来连接的那个,但是对于 SQL Server RDS 我没有设置快速标准配置数据库时的此类选项。

您需要为 lambda 创建一个角色。转到(控制台)IAM->Roles->Create role->(select)Lambda->(in permissions)AWSLambdaVPCAccessExecutionRole->tags->name..etc.
您的 'Trust relationships'(在您创建角色后)应该类似于

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}

现在转到您的 lambda 并在 Configuration 选项卡中,编辑 Execution role 并提供您创建的角色的 arn。
编辑:现在在 Configuration 选项卡中,转到 VPC->Edit->select vpc (where your RDS is situated)->select subnet(where your RDS is situated)->select a security group(select any, maybe the one attached to the DB)*->Save。 如果我没记错的话,任何安全组都可以,Lambda 不需要白名单。
可以找到更多详细信息 here。我希望这能解决您的问题。

我最终成功了。问题不在于安全组或 VPC。这是异步部分。由于我在建立连接之前将响应返回给 Lambda,它从来不知道它成功了,所以它超时了

我必须先确保连接已建立,但我的代码感觉真的很乱。我想改进它

const sql = require('mssql');

exports.mssql = (event, context, callback) => {

    sql.connect({
        user: 'user',
        password: 'pass',
        server: 'host',
        database: 'testdb',
        port: 1433,
    },
    err => {
        if (err) {
            console.log("Fail")
            callback('connect failed', err);
        } else {
            let sqlRequest = new sql.Request();
            let sqlQuery = "SELECT * from TestTable;"

            sqlRequest.query(sqlQuery, function(err, data) {
                if (err) {
                    console.log(err)
                }
                console.table(data.recordset);
                sql.close();
            });
            
            callback(null, sqlRequest);

            response = {
                statusCode: 200,
                body: JSON.stringify({
                    message: "Query returned",
                })
            }
            return response;
        }
    })
}