【问题标题】:AWS Lambda function work on first run but not secondAWS Lambda 函数在第一次运行时工作,但不是第二次
【发布时间】:2017-09-09 01:45:43
【问题描述】:

我有一个 C# Lambda 函数,它在第一次执行时有效,但在第二次执行时失败。 我创建了一些日志来帮助我解决问题所在,但我很难弄清楚实际发生了什么。

第一个执行日志:

START RequestId: XXXXXXXXXXXXXXXXXXXXXXXXXXXXX Version: $LATEST

 1. Connecion to Database is Open
 2. Running Query: SELECT * FROM Employee3
 3. Returning Results
 4. Close connection
 5. Close reader
 6. Dispose cmd
 7. Configure encoding and string to stream
END RequestId: XXXXXXXXXXXXXXXXXXXXXXXX
REPORT RequestId: XXXXXXXXXXXXXXXXXXXXXXXX  Duration: 10097.73 ms   Billed Duration: 10100 ms   Memory Size: 128 MB Max Memory Used: 41 MB  

响应:(我知道这不是有效的 JSON,这是我最终的目标,但一旦我弄清楚了,这将是我处理的下一个项目

Connecion to Database is Open
Joe
Bob
Mary

第二次执行日志:

    START RequestId: XXXXXXXXXXXXXXXXXXXXXXXXXXXXX Version: $LATEST

     1. Connecion to Database is Open
     2. Running Query: SELECT * FROM Employee3
       Connection must be valid and open.: InvalidOperationException
       at MySql.Data.MySqlClient.MySqlCommand.Throw(Exception ex)
       at MySql.Data.MySqlClient.MySqlCommand.CheckState()
       at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior)
       at LambdaDBTest.Function.returnRows(MySqlConnection connection)
       at LambdaDBTest.Function.FunctionHandler(Stream input, ILambdaContext context)
       at lambda_method(Closure , Stream , Stream , ContextInfo )


    END RequestId: XXXXXXXXXXXXXXXXXXXXXXXX
    REPORT RequestId: XXXXXXXXXXXXXXXXXXXXXXXX  Duration: 1203.12 ms    Billed Duration: 1300 ms    Memory Size: 128 MB Max Memory Used: 47 MB

以下是我正在使用的代码:

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using MySql.Data.MySqlClient;
using Amazon.Lambda.Core;
using Amazon.Lambda.Serialization;
using System.Text;

// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializerAttribute(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]

namespace LambdaDBTest
{
    public class Function
    {
        /// <summary>
        /// A simple function that takes a string and does a ToUpper
        /// </summary>
        /// <param name="input"></param>
        /// <param name="context"></param>
        /// <returns></returns>

        public Stream FunctionHandler(Stream input, ILambdaContext context)
        {
            var dbCon = DBConnection.Instance();

            dbCon.Server = "AWS-URI";
            dbCon.DatabaseName = "DBNAME";
            dbCon.User = "DBUSER";
            dbCon.Password = "DBPASS";
            string textInput;
            if (dbCon.IsConnect())
            {
                textInput = "Connecion to Database is Open";
                LambdaLogger.Log("\n 1. " + textInput);
                textInput += returnRows(dbCon.Connection);
            }
            else
            {
                textInput = "\n Connecion to Database is NOT Open";
            }
            dbCon.Close();
            LambdaLogger.Log("\n 7. Configure encoding and string to stream\n");
            input = new System.IO.MemoryStream(System.Text.Encoding.UTF8.GetBytes(textInput));
            return input;
        }

        public static MemoryStream GenerateStreamFromString(string value)
        {
            return new MemoryStream(Encoding.UTF8.GetBytes(value ?? ""));
        }

        static string returnRows(MySqlConnection connection)
        {
            string output = null;
            string query = @"SELECT * FROM Employee3";
            LambdaLogger.Log("\n 2. Running Query: " + query);
            var cmd = new MySqlCommand(query, connection);
            var reader = cmd.ExecuteReader();
            LambdaLogger.Log("\n 3. Returning Results");
            while (reader.Read())
            {
                output += "\n" + (string)reader["Name"];
            }
                LambdaLogger.Log("\n 4. Close connection");
            connection.Close();


                LambdaLogger.Log("\n 5. Close reader");
            reader.Close();

                LambdaLogger.Log("\n 6. Dispose cmd");
            cmd.Dispose();
            return output + "\r";
        }
    }
}

所以代码非常基本,使用 MySql.Data 6.10.1-beta Nu-Get Package for MySQL 和 AWS Lambda 进行了一些剪切和粘贴工作。

我不明白为什么在第一次尝试而不是第二次执行时会出现问题。据我了解,Lambda 中的状态保存为零。

希望我在做一些愚蠢的事情或遗漏了一些显而易见的事情,我很乐意收到通知。如果您需要更多信息,请告诉我。

编辑代码:

所以找到了一个修复,如下所示:

public Stream FunctionHandler(Stream input, ILambdaContext context)
        {
            var dbCon = DBConnection.Instance();

            dbCon.Server = "######.rds.amazonaws.com";
            dbCon.DatabaseName = "#####";
            dbCon.User = "#####";
            dbCon.Password = "######";
            string textInput;
            if (dbCon.IsConnect())
            {
                textInput = "Connecion to Database is Open";
                LambdaLogger.Log("\n 1. " + textInput);
                textInput += returnRows(dbCon.Connection);
            }
            else
            {
                textInput = "\n Connecion to Database is NOT Open";
            }

            //    LambdaLogger.Log("\n 7. Close Database connection");
            //dbCon.Close();
            LambdaLogger.Log("\n 8. Configure encoding and string to stream\n");
            input = new System.IO.MemoryStream(System.Text.Encoding.UTF8.GetBytes(textInput));
            return input;
        }

        public static MemoryStream GenerateStreamFromString(string value)
        {
            return new MemoryStream(Encoding.UTF8.GetBytes(value ?? ""));
        }

        static string returnRows(MySqlConnection connection)
        {
            string output = null;
            string query = @"SELECT * FROM Employee3";
            LambdaLogger.Log("\n 2. Running Query: " + query);
            var cmd = new MySqlCommand(query, connection);
            var reader = cmd.ExecuteReader();
            LambdaLogger.Log("\n 3. Returning Results");
            while (reader.Read())
            {
                output += "\n" + (string)reader["Name"];
            }

            //    LambdaLogger.Log("\n 4. Close connection");
            //connection.Close();


                LambdaLogger.Log("\n 5. Close reader");
            reader.Close();

            //    LambdaLogger.Log("\n 6. Dispose cmd");
            //cmd.Dispose();
            return output + "\r";
        }

进程reader 被 Lambda 冻结,所以虽然由于 .net MySQL 驱动程序的连接池我不需要关闭 MySQL 连接,但实际上我确实需要调用 reader.Close(); 来终止冻结过程。谢谢你 Udo 举行:)

【问题讨论】:

  • 现在可能想更改您的用户名和密码

标签: c# mysql amazon-web-services aws-lambda


【解决方案1】:

我怀疑。 代码看起来就像您每次都在打开和关闭连接,这很好。但是,您的驱动程序可能不会真正关闭连接,而只是将其返回到池中。 AWS freezes 请求之间的实例。因此,如果池保持打开与数据库的连接,它实际上可能会由于您的代码被 AWS 冻结而断开连接。

查看.net MySQL driver documentation 它声明“The Connector/Net supports connection pooling for better performance and scalability with database-intensive applications. This is enabled by default.

您没有提供连接字符串,但您可能应该尝试禁用连接池,添加类似Pooling=false 的内容。 other options你也可以试试。

【讨论】:

  • 你很可能在正确的轨道上。该数据库托管在 RDS 实例中,因此我认为我无法访问。我刚刚更新了我的代码以删除所有连接关闭语句,然后收到以下错误"errorMessage": "There is already an open DataReader associated with this Connection which must be closed first....这绝对是一个线索:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多