#.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. Это автоматически обеспечит доступ в Интернет.