почему мой лямбда-.net api не работает с DynamoDB?

#.net #amazon-web-services #.net-core #aws-lambda #amazon-dynamodb

Вопрос:

у меня проблема, когда я запускаю api в своем локальном, он работает нормально и все делает в базе данных Dynamo, но когда я публикую в своем AWS lambda, он не работает, чего-то не хватает (статус возврата api 500)?

дело в том, что код отлично работает в моих помещениях, данные вставлены правильно, но когда я публикую его в aws lambda, crud не работает и просто ничего не делает (возвращает состояние 500), будет ли отсутствовать какое-либо разрешение?

код зависает в этой строке:

         Table table = Table.LoadTable(client_, "TblUsers_");
 

код находится здесь:

 using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Threading.Tasks;
using System.Linq;
using System.Transactions;
using UserCrudApiChallenge.Infraestructure.Interface;
using UserCrudApiChallenge.CrossCutting.User;
using UserCrudApiChallenge.Domain.Entity;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;
using Amazon.DynamoDBv2.DocumentModel;
using Amazon.DynamoDBv2.Model;
using Amazon.Runtime;
using Amazon;
using Amazon.S3;

namespace UserCrudApiChallenge.Infraestructure.Repository
{
    public class UserRepository : IUserRepository
    {
        private readonly BasicAWSCredentials _connection;

        public UserRepository()
        {
            _connection =  new  BasicAWSCredentials(Environment.GetEnvironmentVariable("DYNAMODB_ACCESS_KEY"),
                Environment.GetEnvironmentVariable("DYNAMODB_SECRET_KEY"));    
        }

        public async Task<User> AddUserAsync(User user)
        {
            try
            {
                AmazonDynamoDBClient client_ = new AmazonDynamoDBClient(_connection, RegionEndpoint.USEast2);
                Table table = Table.LoadTable(client_, "TblUsers_");
                DynamoDBContext context = new DynamoDBContext(client_);
                Document result = await table.PutItemAsync(context.ToDocument(user));

                return user;
            }
            catch (Exception ex)
            {
                Console.WriteLine("FAILED to write the new user, because:n       {0}.", ex.Message);
                throw;
            }            
        }

        public async Task<bool> UpdateUserAsync(User user)
        {
            try
            {
                AmazonDynamoDBClient client = new AmazonDynamoDBClient(_connection, RegionEndpoint.USEast2);
                UpdateItemRequest updateRequest = new UpdateItemRequest()
                {
                    TableName = "TblUsers_",
                    Key = new Dictionary<string, AttributeValue>
                {
                    {"Id", new AttributeValue {S = user.Id } }
                },
                    AttributeUpdates = new Dictionary<string, AttributeValueUpdate>
                {
                        {"Name", new AttributeValueUpdate
                        {
                            Value = new AttributeValue{ S =  user.Name },
                            Action = AttributeAction.PUT
                        }
                    },
                    {"Email", new AttributeValueUpdate
                        {
                            Value = new AttributeValue{ S =  user.Email },
                            Action = AttributeAction.PUT
                        }
                    },
                     {"Password", new AttributeValueUpdate
                        {
                            Value = new AttributeValue{ S =  user.Password },
                            Action = AttributeAction.PUT
                        }
                    }
                }
                };
                await client.UpdateItemAsync(updateRequest);

                return true;
            }
            catch (Exception ex)
            {  
                throw;
            }         
        }

        public async Task<User> FindUserByIdAsync(string userId)
        {    
            try
            {
                AmazonDynamoDBClient client = new AmazonDynamoDBClient(_connection, RegionEndpoint.USEast2);
                Table table = Table.LoadTable(client, "TblUsers_");
                Document result = await table.GetItemAsync(userId);
                return MapUserWithPassword(result);
            }
            catch (Exception ex)
            {  
                throw;
            }
        }

        public async Task<User> FindUserById(string id)
        {
            try
            {
                AmazonDynamoDBClient client = new AmazonDynamoDBClient(_connection, RegionEndpoint.USEast2);

                QueryRequest qry = new QueryRequest
                {
                    TableName = "TblUsers_",
                    ExpressionAttributeNames = new Dictionary<string, string>
                    {
                      { "#Id", "Id" }
                    },
                    ExpressionAttributeValues = new Dictionary<string, AttributeValue> { { ":id", new AttributeValue { S = id } } },
                    KeyConditionExpression = "#Id = :id",
                };

                var result = await client.QueryAsync(qry);

                if (result.Count == 0 || result is null)
                {
                    throw new Exception("No user");
                }
    
                return UsersMapper(result.Items.FirstOrDefault());
            }
            catch (Exception ex)
            {    
                throw;
            }   
        }

        public async Task<List<User>> GetUsers()
        {
            try
            {
                AmazonDynamoDBClient client = new AmazonDynamoDBClient(_connection, RegionEndpoint.USEast2);

                DynamoDBContext context = new DynamoDBContext(client);
                Table table = Table.LoadTable(client, "TblUsers_");

                //get all records
                var conditions = new List<ScanCondition>();
                // you can add scan conditions, or leave empty
                List<User> allUsers = await context.ScanAsync<User>(conditions).GetRemainingAsync();
                return allUsers;
            }
            catch (Exception ex)
            {    
                throw;
            }    
        }

        public async Task<bool> DeleteUserAsync(string id)
        {
            try
            {
                AmazonDynamoDBClient client = new AmazonDynamoDBClient(_connection, RegionEndpoint.USEast2);

                DeleteItemRequest request = new DeleteItemRequest
                {
                    TableName = "TblUsers_",
                    Key = new Dictionary<string, AttributeValue> { { "Id", new AttributeValue { S = id } } }
                };

                await client.DeleteItemAsync(request);

                return true;
            }
            catch (Exception ex)
            {    
                throw;
            }           
        }    

        private User MapUserWithPassword(Document document)
        {
            User user = new User(document["Id"], document["Name"], string.Empty, document["Email"]);
            return user;
        }

        private User UsersMapper(Dictionary<string, AttributeValue> item)
        {    
            try
            {
                User user = new User(item["Id"].S, item["Name"].S, item["Password"].S, item["Email"].S);

                return user;
            }
            catch (Exception ex)
            {   
                throw;
            }
        }
    }
}
 

Комментарии:

1. Подключена ли ваша функция AWS Lambda к VPC? Если да, то есть ли какая-то особая причина , по которой он подключен к VPC? DynamoDB-это служба, доступ к которой осуществляется через Интернет, но функция AWS Lambda, подключенная к VPC, имеет доступ в Интернет только в том случае, если также настроен шлюз NAT. Если доступ к VPC не требуется, отключите функцию Lambda от VPC и посмотрите, работает ли она.

2. Не имеет отношения к проблеме, но все ваши try { ... } catch(Exception ex) { throw; } обертывания бессмысленны. Поведение здесь такое же, как если бы вы опустили их. Эти оболочки просто усложняют чтение и обслуживание вашего кода.

3. @PeterCsala Я просто пытался посмотреть, не попало ли оно в исключение, но оно даже не доходит до улова, фактически оно прилипает к определенной строке (Обновите сообщение).

4. @JohnRotenstein наконец — то проблема была в vpc, видимо, на уровне кода она не дошла до базы данных, это решило мою проблему, большое вам спасибо !!!!!

Ответ №1:

DynamoDB-это услуга, доступ к которой осуществляется через Интернет. Поэтому, если ваша функция AWS Lambda не может получить доступ к Интернету, возможно, она не достигает DynamoDB.

Когда функция AWS Lambda настроена для использования VPC, она может получить доступ к DynamoDB только в том случае, если:

  • Функция Lambda подключена к частной подсети, а в общедоступной подсети имеется шлюз NAT, ИЛИ
  • VPC был настроен с конечной точкой VPC для DynamoDB, которая напрямую соединяет VPC с DynamoDB

Если для функции Lambda не требуется доступ к VPC, отключите функцию Lambda от VPC. Это автоматически обеспечит доступ в Интернет.