AWS Lambda中AddScoped注册服务跨请求复用实例问题
问题根因
出现这个现象的核心原因是.NET依赖注入的Scoped生命周期规则和AWS Lambda的执行模型没有对齐:
- .NET原生DI框架中,
AddScoped注册的服务实例生命周期和独立的IServiceScope作用域绑定。如果直接从根ServiceProvider解析Scoped服务,服务实例会和根容器的生命周期完全绑定,实际表现和Singleton单例完全一致。 - AWS Lambda的执行逻辑是:冷启动时仅执行一次Function构造函数,只要实例没有被平台回收(热启动阶段),所有后续函数调用都会复用构造函数中初始化的根
_serviceProvider实例。你一直直接从根容器解析服务,没有为每次Lambda调用创建独立的请求级作用域,自然Scoped服务不会按调用维度重新生成。 - 你之前使用
AddTransient能正常工作,是因为Transient生命周期的服务每次解析都会生成新实例,不依赖独立作用域的创建逻辑。
修复方案
在每次Lambda函数触发(即FunctionHandler方法执行)时,先基于根容器创建一个独立的DI作用域,本次调用的所有服务都从这个请求级作用域解析,调用结束后自动释放作用域,就能实现「同一次请求内Scoped服务实例相同,不同请求返回独立实例」的预期效果。
修改后的FunctionHandler代码如下:
public string FunctionHandler(object input, ILambdaContext context) { // 为当前Lambda调用创建独立的DI作用域,调用结束后自动释放 using var scope = _serviceProvider.CreateScope(); // 所有服务均从当前请求作用域解析,不要直接从根_serviceProvider获取 var tenantInfo= scope.ServiceProvider.GetRequiredService<ITenantInfo>(); var service1 = scope.ServiceProvider.GetRequiredService<IService1>(); var service2 = scope.ServiceProvider.GetRequiredService<IService2>(); // 原有业务逻辑 LambdaLogger.Log("Service 1 GUID==>" + service1.GetTenantInfo().GUID); LambdaLogger.Log(Environment.NewLine); LambdaLogger.Log("Service 2 GUID==>" + service2.GetTenantInfo().GUID); LambdaLogger.Log(Environment.NewLine); return "Done"; }
注意事项
不要为了实现效果把BuildServiceProvider逻辑挪到FunctionHandler里、每次调用都重建根容器:这种写法会让所有注册的服务不管声明什么生命周期,都会在每次调用时重新初始化,既浪费Lambda热启动的性能优化优势,也会导致同一次请求内的Scoped服务无法共享实例,不符合DI生命周期设计预期。
内容的提问来源于stack exchange,提问作者John Smith
相关产品推荐
相关产品推荐

