我是一个长期学习nestjs的spring开发人员。这些相似之处是如此惊人,我很喜欢这让我的工作效率如此之高。然而,一些文档让我对一件事感到困惑。
我尝试将嵌套“提供者”比作具有默认作用域的springbean。例如,我创建了@injectable服务类,并认为它们类似于spring@services。因此,我假设这些服务类需要是线程安全的-没有状态,等等。但是,这里的嵌套文档对我来说有点含糊不清,并暗示这可能不是必需的(我的重点):
对于来自不同编程语言背景的人来说,在nest中,几乎所有的东西都是在传入的请求之间共享的,这可能是出乎意料的。我们有一个到数据库的连接池、具有全局状态的单例服务等。请记住,node.js不遵循请求/响应多线程无状态模型,其中每个请求都由一个单独的线程处理。因此,对于我们的应用程序来说,使用单例示例是完全安全的。
如果单个请求没有在它们自己的线程中处理,那么嵌套提供程序是否可以包含可变状态?这将取决于应用程序,以确保每个传入的请求都以“干净的板岩”开始,例如,用一个nestinterceptor初始化该状态。但对我来说,doc读取到提供者是作为单例创建的,因此可以用作类似于数据 Package 容器的东西,比如java中的threadlocal。
是我看错了,还是这是巢穴和Spring行为上的差异?
1条答案
按热度按时间oxosxuxt1#
您真的应该使请求处理成为无状态的。
我对spring一无所知,但在nestjs(以及一般的异步javascript)中,它是单线程的,但不会阻塞i/o。这意味着同一个服务示例的同一个线程可以同时处理多个请求。它一次只能做一件事,但可以在前一件事等待数据库查询、等待请求完成传输、等待外部服务响应、等待文件系统传递文件内容等时开始做下一件事。
因此,在一个线程中,对于一个服务示例,这可能会发生:
一个请求进来了。
为请求a调度数据库查询。
请求b进来了。
为请求b调度数据库查询。
返回请求a的数据库查询,并发送响应。
返回对请求b的数据库查询,并发送响应。
这对state意味着它将在请求之间共享。如果您的服务在异步操作的一个步骤设置了示例属性,那么另一个异步操作可能会在第一个步骤完成之前启动,并为该示例属性设置一个新值,这可能不是您想要的。
我相信nest文档提到的“全局状态”不是每个请求,而是一般配置状态。比如外部服务的url,或者数据库的凭据。
还值得一提的是,控制器接收一个请求对象,它表示特定的请求。向请求对象添加属性是很常见的,例如当前已验证的用户。请求对象可以以一种对该体系结构友好的方式传递给您的控制器和服务上下文。