繁体   English   中英

来自 Amazon.DynamoDBv2.DocumentModel 的 Table.LoadTable 导致 .NET 代理 Lambda 函数超时

[英]Table.LoadTable from Amazon.DynamoDBv2.DocumentModel causing Times out in .NET proxy Lambda Function

我想在 Lambda 函数中读取 DynamoDB 表。 但是,该功能在 3 秒后保持超时。 Lambda 函数用于 Lambda 代理与 API 网关的集成。 通过日志记录进行故障排除,我已将问题缩小到 Table.LoadTable 方法。

这是控制器代码:

using Microsoft.AspNetCore.Mvc;
using MyWebsite.Quote;

namespace MyWebsite.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class QuoteController : ControllerBase
    {
        private readonly ILogger<QuoteController> _logger;

        public QuoteController(ILogger<QuoteController> logger)
        {
            _logger = logger;
        }

        [HttpGet]
        public ActionResult GetRandomQuote()
        {
            var quoteRetriever = new QuoteRetriever(_logger);
            var quoteData = quoteRetriever.GetRandomQuote();
            return Ok(quoteData);
        }
    }
}

这是调用 LoadTable 方法的类:

using Amazon;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DocumentModel;
using MyWebsite.Controllers;

namespace MyWebsite.Quote
{
    public class QuoteRetriever
    {
        private readonly ILogger<QuoteController> _logger;
        private static readonly AmazonDynamoDBClient DynamoDbClient = new AmazonDynamoDBClient();

        public QuoteRetriever(ILogger<QuoteController> logger)
        {
            _logger = logger;
        }

        public QuoteData GetRandomQuote()
        {
            // Get information about highest quoteNr
            // and missing Nrs
            const string tableInfo = "TableInfo";

            Document tableInfoItem;
            Table table;
            _logger.LogInformation("Reached GetRandomQuote.");
            try
            {
                _logger.LogInformation("About to set table.");
                // The problem has to be here.
                table = Table.LoadTable(DynamoDbClient, "QuotesTable");
                _logger.LogInformation("Set table.");

                tableInfoItem = table.GetItemAsync(tableInfo).Result;
                _logger.LogInformation("Retrieved tableInfoItem.");
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                _logger.LogInformation("Error Message: " + e.Message);
                _logger.LogInformation("Error Stacktrace: " + e.StackTrace);
                throw;
            }
            _logger.LogInformation("Successfully retrieved TableInfo!");

            var highestQuoteNr = tableInfoItem["HighestQuoteNumber"].AsInt();
            var missingQuoteNumbers = tableInfoItem["MissingQuoteNumbers"].AsListOfPrimitive();

            // Randomize Nr
            var random = new Random();
            var randomQuoteNumber = random.Next(0, highestQuoteNr);
            if (missingQuoteNumbers.Any())
            {
                while (missingQuoteNumbers.Contains(randomQuoteNumber))
                {
                    randomQuoteNumber = random.Next(0, highestQuoteNr + 1);
                }
            }

            var randomQuote = table.GetItemAsync(randomQuoteNumber.ToString()).Result;

            var quoteData = new QuoteData
            {
                QuoteNumber = randomQuoteNumber,
                Quote = randomQuote["Quote"].AsString(),
                Quotee = randomQuote["Quotee"].AsString()
            };

            return quoteData;
        }
    }
}

我已确保表和 Lambda 位于同一区域,并已通过 CDK 授予 Lambda 对表的完全访问权限:

quotesTable.grantFullAccess(handler);

Lambda 作为 .NET 6 最小 API 运行。 这是 Program.cs 文件:

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();

// Add AWS Lambda support. When application is run in Lambda Kestrel is swapped out as the web server with Amazon.Lambda.AspNetCoreServer. This
// package will act as the webserver translating request and responses between the Lambda event source and ASP.NET Core.
builder.Services.AddAWSLambdaHosting(LambdaEventSource.RestApi);

var app = builder.Build();


app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

app.MapGet("/", () => "Welcome to running ASP.NET Core Minimal API on AWS Lambda");

app.Run();

代码到达“About to set table”。 评论,但之后超时。 奇怪的是,当我在本地运行代码并将 BasicAWSCredentials("accessKey", "secretKey") 和区域显式传递给 AmazonDynamoDBClient 时,它起作用了。 但是当我将这些参数删除给客户端并部署到 AWS 时,它一直没有工作

尝试从运行 .NET 6 最小 API 的 Lambda 函数读取 DynamoDB 表,但该函数在 Table.LoadTable(DynamoDBClient, "TableName") 处 3 秒后超时。

Lambda 在超时之前运行您的代码一段时间,默认为 3 秒,这似乎是这里的罪魁祸首。 这也可以解释为什么您的代码在本地运行得非常好,因为它不会被限制为 3 秒超时,并且可以运行更长时间。

通过控制台/CLI/SDK/IaC 等,将函数的超时持续时间增加到更适合您的工作负载的时间,最多 15 分钟。

请注意:您不会为设置更高的超时值支付额外费用,但这自然意味着您的 Lambda 函数将被允许运行更长时间,如果他们愿意,即如果您的 Lambda 需要在 10 分钟内完成,您将支付更多费用,因为反对 25 秒。


我还建议用 async & await 语法替换.Result以获得更清晰的代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM