Node JS 是否为新请求启动新进程?

Does NodeJS spin up a new process for new reqest?

我有一个后端 NodeJS API,我正在尝试设置跟踪 ID。我一直在想的是,我会通过单例模块生成一个 UUID,然后将其用于日志记录。但是由于 NodeJS 是单线程的,这是否意味着所有客户端的 UUID 将始终保持相同?

例如:如果 API 从 https://www.example.com/client-1https://www.example-two.com/client-2 收到请求,它会旋转一个新进程并因此生成单独的 UUID 吗?或者它只是一个 运行 单线程的进程?如果它只是一个进程和一个线程,那么我认为两个客户端应用程序都会分配相同的 UUID。

这个理解对吗?

查看此图以了解与其他语言服务器相比,node js 服务器如何处理请求

所以在你的情况下不会有单独的 thread

并且除非您通过使用 pm2 为您的应用 运行 创建一个单独的进程,或者使用内部模块显式创建该进程,否则它不会是一个单独的 process

Node.js 是单线程 run-time 环境,前提是它在内部确实为阻塞事件循环的请求分配线程。

What I have been thinking is that I would generate a UUID through a Singleton module

是的,它只会生成一次 UUID,每次你有新的请求时,它都会重复使用相同的 UUID,这是使用 Singleton 设计模式的主要目的。

would it spin a new process and thereby generate separate UUIDs? or it's just one process that would be running with a single thread?

进程是任何可以有一个或多个线程的计算机程序的实例,在这种情况下它是Node.js(进程),事件循环和执行上下文或堆栈是这两个线程的一部分过程。每次收到请求都会进入事件循环,然后传递到栈中执行。

您可以使用子模块在 Node.js 中创建一个单独的进程。

Is this understanding correct?

是的,您对 UUID 单例模式的理解是正确的。我建议您查看 Node.js 如何处理请求。 This 视频可帮助您了解事件循环的工作原理。

Nodejs 只使用一个线程来 运行 你所有的 Javascript (除非你专门创建一个 WorkerThread 或 child_process)。 Nodejs 在内部使用一些线程用于某些库函数,但这些线程不用于 运行 宁你的 Javascript 并且对你是透明的。

因此,与其他一些环境不同,每个新请求 运行 都在同一个线程中。没有为传入请求创建新进程或线程。

如果你使用一些单例,它对每个请求都有相同的值。

But since NodeJS is single threaded, would that mean that UUID will always remains the same for all clients?

是的,所有请求的 UUID 都相同。

For eg: If the API gets a request from https://www.example.com/client-1 and https://www.example-two.com/client-2, would it spin a new process and thereby generate separate UUIDs?

不,它不会旋转新进程,也不会生成新的 UUID。

or it's just one process that would be running with a single thread? If it's just one process with one thread then I think both the client apps will get the same UUID assigned.

一个进程。一个线程。来自单例的相同 UUID。


如果您试图在每个日志语句中放置一些 request-specific UUID,那么没有太多选择。通常的选择是在某些中间件中为每个新请求创建一个新的 UUID,并将其作为 属性 附加到 req 对象,例如 req.uuid,然后传递 req对象或 uuid 本身作为可能想要访问它的所有代码的函数参数。

还有一种称为“异步本地存储” 的技术可以为您服务。这是 doc。它可以像“线程本地存储”一样在其他环境中使用,这些环境确实为每个新请求使用一个线程。它提供了一些与执行上下文相关联的本地存储,每个仍在处理的传入请求都将拥有该执行上下文,即使它经历了各种异步操作,甚至当它 returns 暂时控制回事件循环时也是如此。

据我所知,异步本地存储接口已经经历了几次不同的实现,仍然被认为是实验性的。