You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core迁移至.NET 6后,AWS Serverless应用无法连接MySQL主机

.NET 6 Lambda 无法连接 AWS RDS MySQL 主机问题排查

问题概述

项目从.NET Core 3.0迁移至.NET 6后,部署到AWS Serverless(Lambda)的.NET 6 API无法连接MySQL主机,Swagger和Postman请求均返回504网关超时,但本地运行完全正常。

环境信息

  • ORM框架:Entity Framework Core Code First
  • MySQL驱动:Pomelo.EntityFrameworkCore.MySql 6.0.1
  • EF Core版本:Microsoft.EntityFrameworkCore 6.0.2
  • 部署环境:AWS Lambda(.NET 6运行时),已按官方文档完成基础配置

错误日志

[Error] Amazon.Lambda.AspNetCoreServer.AbstractAspNetCoreFunction: Unknown error responding to request: MySqlException:
MySqlConnector.MySqlException (0x80004005): Unable to connect to any of the specified MySQL hosts.
   at NurseScalettAPI.Controllers.UserManagementController.GetCaseDetails(Int32 caseId)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task last task, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
   at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
   at Amazon.Lambda.AspNetCoreServer.AbstractAspNetCoreFunction.ProcessRequest(ILambdaContext lambdaContext, Object context, InvokeFeatures features, Boolean rethrowUnhandledError)

已尝试操作

  • 移除连接字符串中的冗余空格和重复配置,当前连接字符串:
"DefaultConnection": "server=aws-cluster-instance-1.cva0y.us-east-1.rds.amazonaws.com;port=3306;database=sample_database;user=sample_user;password=passwrd;Persist Security Info=false;Connect Timeout=60;Convert Zero Datetime=true;Allow User Variables=True;" 

核心代码片段

DataContext 代码

public class DataContext: DbContext
{
    protected readonly IConfiguration Configuration;
    private readonly AppSettingOptions _options;
    public DataContext(IConfiguration configuration, IOptions<AppSettingOptions> options)
    {
        Configuration = configuration;
        _options = options.Value;
    }

    protected override void OnConfiguring(DbContextOptionsBuilder options)
    {
        string mySqlConnectionString = _options.DefaultConnection;             
        if (mySqlConnectionString != null)
        {
            options.UseMySql(mySqlConnectionString, ServerVersion.AutoDetect(mySqlConnectionString));
        }
    }
    public DbSet<CaseDetails> CaseDetails { get; set; }
}

UserManagementController 代码

[Route("api/[controller]")]
[ApiController]
public class UserManagementController : ControllerBase
{
    private readonly ICoreLogger<UserManagementController> _logger;
    private readonly DataContext _context;
    private readonly IUserRepository _userService;
    private readonly IHttpContextAccessor _httpContext;
    private readonly IConfiguration _config;

    public UserManagementController(IUserRepository userService, IPersistService cache, DataContext context, IHttpContextAccessor httpContext, ICoreLogger<UserManagementController> logger, IConfiguration config)
    {
        _logger = logger;
        _context = context;
        _userService = userService;
        _httpContext = httpContext;
        _config = config;   
    }
    [HttpGet("{caseId}")]
    public async Task<IActionResult> GetCaseDetails(int caseId)
    {
        try
        {
            var connStr1 = _config.GetConnectionString("DefaultConnection");
            _logger.LogInformation($"Get connectionstring from appsetting : {connStr1}"); // 可在CloudWatch日志中打印
            
            var str = _context.Database.GetConnectionString().Split(";");
            _logger.LogInformation($"Connection string: {str[0]} , {str[2]}");

            var result = _context.CaseDetails.FirstOrDefault(x => x.Case_Id == caseId);
            return result != null ? Ok(result) : BadRequest();
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
}

Startup.cs 代码

public class Startup
{
    public Startup(IConfiguration configuration, IWebHostEnvironment env)
    {
        Configuration = configuration;
        var builder = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json", optional: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);

        builder.AddEnvironmentVariables();
        Configuration = builder.Build();
    }
    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<AppSettingOptions>(Configuration.GetSection(AppSettingOptions.ConnectionStrings));
        services.AddDbContext<DataContext>();

        services.AddSingleton<IServiceCollectionProvider>(new ServiceCollectionProvider(services));

        services.AddControllers();

        services.AddControllers().AddNewtonsoftJson(options =>
                 options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore);

        #region UserManagement
        services.Configure<CookiePolicyOptions>(options =>
        {
            options.CheckConsentNeeded = context => false;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });

        services.AddMemoryCache();
        services.AddHttpContextAccessor();
        services.Configure<AppConfig>(Configuration.GetSection("AppConfig"));
        services.Configure<S3Configuration>(Configuration.GetSection("AwsConfiguration"));
        services.Configure<SearchConfig>(Configuration.GetSection("SearchConfig"));
        services.Configure<ExternalKnowledgeSource>(Configuration.GetSection("ExternalKnowledgeSource"));
        services.Configure<SQSConfiguration>(Configuration.GetSection("ServiceConfiguration"));

        services.AddScoped<IUserRepository, UserRepository>();
        services.AddScoped<UserContextManager>();
        services.AddScoped<IPersistService, CacheService>();
        #endregion

        services.AddScoped<IUserService, UserServices>();
        services.AddScoped<IUserServiceAsync, UserServicesAsync>();

        services.AddSingleton<IAppConfiguration, AppConfiguration>();

        services.AddSingleton(typeof(ICoreLogger<>), typeof(CoreLogger<>));

        #region UserManagement
        services.AddAuthentication(options =>
        {
            options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        })
         .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
         {
             options.LoginPath = "/User/Login";
             options.LogoutPath = "/User/Logout";
             options.ReturnUrlParameter = "";
         });
        #endregion

        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new OpenApiInfo
            {
                Version = "v1",
                Title = "Nurse Scarlett API",
                Description = "Nurse Scarlett API"
            });
        });
        services.AddAWSLambdaHosting(LambdaEventSource.RestApi);
        services.AddCors(options =>
        {
            options.AddPolicy(
                name: "AllowOrigin",
                builder => {
                    builder.AllowAnyOrigin()
                            .AllowAnyMethod()
                            .AllowAnyHeader();
                });
        });
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseCors("AllowOrigin");

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseSwagger();

        app.UseSwaggerUI(c => {
            var swaggerJsonBasePath = string.IsNullOrWhiteSpace(c.RoutePrefix) ? "." : "..";
            c.SwaggerEndpoint($"{swaggerJsonBasePath}/swagger/v1/swagger.json", "MyAPI");
        });

        app.UseHttpsRedirection();

        app.UseRouting();

        app.UseAuthentication();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
            endpoints.MapGet("/", async context =>
            {
                await context.Response.WriteAsync("Welcome to running ASP.NET Core on AWS Lambda");
            });
        });
    }
} 

排查建议

  • 网络连通性:

    • 检查Lambda所在VPC的安全组是否允许出站访问3306端口
    • 确认RDS安全组是否开放Lambda所在VPC/安全组的入站连接
    • 若Lambda在私有子网,需配置NAT网关或RDS VPC端点以实现内网访问
  • 连接字符串优化:

    • 确认Lambda环境变量中是否正确配置连接字符串(AWS Lambda优先读取环境变量,而非仅appsettings)
    • 添加SslMode=Required参数(AWS RDS默认强制SSL连接)
    • 简化连接字符串至必要参数:server=xxx;port=3306;database=xxx;user=xxx;password=xxx;SslMode=Required
  • EF Core配置调整:

    • 替换ServerVersion.AutoDetect为手动指定版本,例如ServerVersion.Parse("8.0.28-mysql"),避免Lambda环境中版本检测失败
    • 验证AppSettingOptions.ConnectionStrings节点是否与appsettings中的配置键名完全匹配
  • Lambda超时设置:

    • 当前连接超时为60秒,需将Lambda函数的超时时间设置为大于60秒(如90秒),避免因连接未完成导致的504超时
  • 依赖包更新:

    • 升级Pomelo.EntityFrameworkCore.MySql至最新兼容.NET 6的版本,修复潜在的版本兼容性问题

内容的提问来源于stack exchange,提问作者Sachin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 17:32:35