Nodejs-线程池大小为四时,可以同时运行的最大线程数是多少?

如何解决Nodejs-线程池大小为四时,可以同时运行的最大线程数是多少?

要求是每秒1000个并发请求和IO操作,例如对每个请求的数据库查询。由于nodejs在事件循环上工作,它将IO操作分配给线程池,但是线程池的默认大小为4,因此同时最多可以有4个线程(IO操作)工作,其余线程必须在队列中等待。一旦任何线程完成执行,便可以处理。

查询1-我们可以根据需要将线程池大小增加到N个吗,它会提高性能还是会降低性能?

查询2-如何在nodejs中实现以上要求?

查询3-Nodejs是此要求或其他建议(例如golang)的空闲选择

解决方法

node.js上的网络I / O操作在主线程上运行。

是的,node.js除了主线程外还产生了四个线程,但是它们都不用于网络I / O(例如数据库操作)。线程是:

  1. DNS解析器(因为大多数操作系统为此仅提供同步API)

  2. 文件系统API(因为这样做很麻烦,无法跨平台进行异步操作)

  3. 加密(因为这使用CPU)

  4. Zlib(zip压缩)

除非您自己生成worker_threads,否则其他所有内容都不会使用线程。有关更多信息,请参见节点自己的文档:https://nodejs.org/en/docs/guides/dont-block-the-event-loop/。不要依赖不是来自node.js项目本身的信息,例如youtube或中级文章,这些文章说节点I / O使用线程池-他们不知道自己在说什么。

增加线程池大小不会对网络I / O产生任何影响,因为node.js根本没有任何代码可以使网络I / O利用额外的线程。如果要将负载分散到多个处理器中,可以使用群集。您可以编写自己的集群代码,也可以使用诸如pm2之类的进程管理器的集群模式将连接传递给您的进程。

如果节点仅使用一个线程,怎么能声称自己具有高性能!

大多数非系统程序员不会意识到的是,等待I / O占用的CPU时间恰好为零。通过生成线程来执行此操作意味着您正在分配大量的RAM,并且所有这些线程通常都使用 zero CPU时间(设想生成1024个线程,每个线程根本不使用CPU)。当这些线程(或在主线程为node.js的情况下)正在等待来自数据库的1000条回复时,操作系统会将这些请求排队放入一系列数据包中,然后将其发送到您的网卡中,然后由网卡将其发送到数据库中一次一点点-是的,它的核心I / O不是并行的(除非您在多个网卡上使用中继)。因此,大多数繁重的工作都是通过以太网完成的,而操作系统会暂停您的进程(等待)。

node.js的作用是在请求等待时发出另一个请求。这就是非阻塞的意思。节点在处理所有其他请求之前不会等待请求完成。这意味着默认情况下,您在node.js中发出的所有请求都是并发的-它们不等待其他请求完成。

在请求完成侧,从服务器收到的任何响应都会触发节点搜索事件队列(由于此时队列中的任何项目都可以随时完成,因此这实际上只是一个设置),并找到相应的回调进行调用。执行回调要做会占用CPU时间,但不等待网络请求。

这就是为什么像node.js这样的系统可以与多线程系统竞争的原因。实际上,在某些情况下,它的性能可能会优于多线程系统,因为在同一线程上执行此操作意味着您不需要锁(互斥或信号量),并且避免了上下文切换的开销(当操作系统将一个线程置于睡眠状态时,将所有副本将值保存到RAM中,然后唤醒另一个线程,将另一个寄存器的值复制回RAM中以用于新进程。

,

libuv中的网络套接字是无阻塞的(即不在该线程池上)。首先建立测试工具。使用默认值可能会更好。

要增加线程池的大小,请将环境变量UV_THREADPOOL_SIZE=N设置为1024。

$ node --help
...
Environment variables:
...
UV_THREADPOOL_SIZE            sets the number of threads used in libuv's threadpool
,

nodejs中的网络不使用线程池,因此切换不会影响您的网络I / O吞吐量。联网使用的OS API已经是异步且无阻塞的。

在处理传入请求时运行的Javascript也不使用线程池。

磁盘I / O确实使用了线程池,但是如果您仅访问一个物理磁盘驱动器,那么扩大线程池可能不会给您带来很多好处,因为只有一个物理磁盘伺服器只能放在一个位置无论如何,如果并行运行20个磁盘请求,如果它们都在争夺相同的磁盘头位置,则不一定对您有帮助。实际上,当操作系统尝试在所有不同线程之间进行时间片划分时,甚至可能使情况变得更糟,从而导致磁盘头的移动超出了为每个线程服务的最佳范围。

要每秒处理1000个请求,您将必须进行基准测试并测试瓶颈所在。如果我猜想我敢打赌,瓶颈将是您的数据库,在这种情况下,重新配置nodejs设置并不是您需要集中精力的地方。但是,无论如何,只有在确定了特定应用程序中的瓶颈所在后,您才能正确地找出哪些选项可以帮助您解决该瓶颈。另外,请记住,每秒处理1000个请求意味着您不能为每个请求运行Java脚本,而每个请求花费的时间超过1毫秒。因此,您可能也必须对服务器进行群集(通常,服务器硬件中每个物理CPU内核一个群集)。因此,如果您有8核服务器,则可以设置8节点集群。

例如,如果您的Nodejs进程中的CPU受限于您的自己的Javascript的运行,那么也许您想实现nodejs集群以使多个CPU都运行不同的请求。但是,如果真正的瓶颈在您的数据库中,则对您的nodejs请求处理程序进行群集将无法解决数据库的瓶颈。

进行基准测试,测量,基于更改的数据得出理论,设计特定的测试以进行测量,然后实施其中一种理论并进行测量。根据您的测量进行调整。您只有通过先测量,进行适当的调整然后测量进度,才能真正正确地做到这一点(而不会浪费大量时间浪费在无效的方向上)。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 <select id="xxx"> SELECT di.id, di.name, di.work_type, di.updated... <where> <if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 <property name="dynamic.classpath" value="tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-