要求是每秒1000个并发请求和IO操作,如对每个请求的数据库查询。由于nodejs工作在事件循环上,它会将IO操作分配给线程池,但线程池的默认大小是4,因此同时最多可以有4个线程(IO操作)工作,其余的线程必须在队列中等待。一旦任何线程完成执行,它们就可以进行处理。
问题1-我们是否可以根据需要将线程池大小增加到N个,这样会提高性能还是会降低性能?
问题2-如何在nodejs中实现上述要求?
查询3-对于此需求或其他建议,Nodejs是空闲的选择
发布于 2020-08-12 14:24:12
node.js上的网络I/O操作在主线程上运行。
是的,除了主线程之外,node.js还派生了四个线程,但它们都不用于网络I/O,如数据库操作。这些线程是:
很麻烦
zip compression) (zip
其他一切都不要使用线程,除非您自己生成worker_threads
。有关这方面的更多信息,请参阅节点自己的文档:https://nodejs.org/en/docs/guides/dont-block-the-event-loop/。不要依赖不是来自node.js项目本身的信息,比如youtube或medium文章,这些文章说节点I/O使用线程池-他们不知道自己在说什么。
增加线程池大小不会对网络I/O做任何事情,因为node.js根本没有任何代码来使网络I/O利用额外的线程。如果你想将负载分散到多个处理器上,你可以使用集群。您可以编写自己的集群代码,也可以使用流程管理器的集群模式(如pm2 )将连接传递给您的进程。
如果节点只使用一个线程,它怎么能号称高性能!
大多数非系统程序员没有意识到的是,等待I/O完全没有占用CPU时间。通过派生线程来实现这一点意味着您正在分配大量的内存,并且大部分时间都在为所有这些线程使用零cpu时间(想象一下,派生1024个线程,每个线程根本不使用)。当这些线程(或者在node.js的情况下是主线程)在等待来自数据库的1000个回复时,操作系统将这些请求排队成一系列的包,并将它们发送到网卡,网卡再一次一位地将它们发送到数据库-是的,它核心的I/O不是并行的(除非你在多个网卡上使用中继)。因此,大部分繁重的工作都是由以太网完成的,而您的进程则由操作系统暂停(等待)。
node.js所做的是,当请求等待时,它会发出另一个请求。这就是非阻塞的含义。节点在处理所有其他请求之前不会等待请求完成。这意味着在默认情况下,您在node.js中发出的所有请求都是并发的-它们不会等待其他请求完成。
在请求完成端,从服务器接收到的任何响应都会触发节点来搜索事件队列(实际上,这只是一个集合,因为队列中的任何项都可以在任何时间完成),并找到相应的回调来调用。执行回调do会占用CPU时间,但不会等待网络请求。
这就是为什么像node.js这样的系统可以与多线程系统竞争。事实上,在某些情况下,多线程系统的性能要好于多线程系统,因为在同一线程上执行该操作意味着您不需要锁(互斥或信号量),并且可以避免上下文切换的成本(当操作系统将一个线程置于睡眠状态时,将所有寄存器值复制到RAM,然后唤醒另一个线程,从RAM复制回新进程的寄存器值)。
发布于 2020-08-12 13:29:13
libuv中的网络套接字是非阻塞的(即不在该线程池中)。首先构建一个测试工具。您很可能会对默认设置感到满意。
要增加线程池大小,请将环境变量UV_THREADPOOL_SIZE=N
设置为1024。
$ node --help
...
Environment variables:
...
UV_THREADPOOL_SIZE sets the number of threads used in libuv's threadpool
发布于 2020-08-12 14:15:41
nodejs中的网络不使用线程池,因此切换不会影响您的网络I/O吞吐量。网络使用的操作系统API已经是异步和非阻塞的。
在处理传入请求时运行的Javascript也不使用线程池。
磁盘I/O确实使用线程池,但是如果您只访问一个物理磁盘驱动器,那么您可能不会从扩大线程池中获得太多好处,因为只有一个物理磁盘服务器一次只能位于一个位置,因此如果它们都在竞争相同的磁盘头位置,那么并行运行20个磁盘请求不一定会对您有所帮助。事实上,它甚至可能使事情变得更糟,因为操作系统试图在所有不同的线程之间进行时间切片,导致磁盘头的移动超过了为每个线程提供服务的最佳状态。
要每秒处理1000个请求,您必须进行基准测试和测试,找出瓶颈所在。如果非要我猜的话,我敢打赌瓶颈一定是您的数据库,在这种情况下,重新配置nodejs设置并不是您需要集中精力的地方。但是,在任何情况下,只有在确定了特定应用程序中的瓶颈所在之后,才能正确地找出哪些选项可以帮助您解决该瓶颈。此外,请记住,服务1000个请求/秒意味着您不能在每个请求上运行Javascript,每个请求花费的时间超过1ms。因此,您可能还必须对服务器进行集群(通常服务器硬件中的每个物理CPU核心都有一个集群)。所以,如果你有一个8核的服务器,你需要设置一个8节点的集群。
例如,如果在运行自己的Javascript时,nodejs进程中的CPU有限,那么您可能希望实现nodejs集群,以使多个CPU都运行不同的请求。但是,如果真正的瓶颈在您的数据库中,那么集群您的nodejs请求处理程序将无助于解决数据库瓶颈。
基准测试,测量,提出基于数据的理论来改变什么,设计具体的测试来测量,然后实现其中的一个理论和测量。根据您测量的内容进行调整。你只能通过首先测量,进行适当的调整,然后测量进度,才能真正正确地做到这一点(而不会在无效的方向上浪费大量时间)。
https://stackoverflow.com/questions/63369876
复制相似问题