【发布时间】:2023-03-11 09:40:02
【问题描述】:
在 .NET Core DI 的上下文中,如果服务注册为 Singleton(生命周期,不要与模式混淆),它是否能够处理多个并发请求?
文档说“每个后续请求都使用相同的实例”。假设我们的数据访问实现是这样注册的。这是否意味着它不会扩展和处理并发请求,并且每个请求基本上都会排队使用该服务?
【问题讨论】:
标签: .net performance .net-core dependency-injection singleton
在 .NET Core DI 的上下文中,如果服务注册为 Singleton(生命周期,不要与模式混淆),它是否能够处理多个并发请求?
文档说“每个后续请求都使用相同的实例”。假设我们的数据访问实现是这样注册的。这是否意味着它不会扩展和处理并发请求,并且每个请求基本上都会排队使用该服务?
【问题讨论】:
标签: .net performance .net-core dependency-injection singleton
这是否意味着它不会扩展和处理并发请求,并且每个请求基本上都会排队使用该服务?
一点也不。当您将服务声明为Singleton(或其他范围)时,您只需 为 DI 定义其生命周期(创建和处置行为)。不多也不少。它对线程的访问方式和服务请求没有任何关系或影响。因此,您必须注意服务的并发问题,并在非线程安全的代码上到处定义锁。
假设我们的数据访问实现是这样注册的
特别是如果您使用像实体框架这样的 ORM,您应该知道它的 DbContext 不是线程安全的,并且将其声明为 Singleton 会导致许多并发问题,应该避免。
【讨论】:
根据Microsoft:
Singleton 生命周期服务 (AddSingleton) 在第一次被请求时创建(或者在 Startup.ConfigureServices 运行并使用服务注册指定实例时)。每个后续请求都使用相同的实例。如果应用程序需要单例行为,建议允许服务容器管理服务的生命周期。不要实现单例设计模式并提供用户代码来管理类中对象的生命周期。
根据上面的说法,你在问题中提到的请求将被排队。
但如果你从性能的角度考虑,你的替代方案是
您不仅在开始时通过实例化对象付出了性能损失,而且在收集它们时还需要 GC 付出更多的努力。
如果您的单例服务中有一些非常繁重的 CPU 操作,每个请求会使用多次,那么重新考虑您的方法并实现范围生命周期实际上可能是有意义的。
但是从性能的角度来看,如果可能的话,总体而言创建单例服务仍然是最好的解决方案。
【讨论】: