Node.js学习笔记-04
这第九章也是个大重点
九、玩转进程
Node在选型时决定在V8引擎之上构建,也就意味着它的模型与浏览器类似。
本章关于进程的介绍和讨论将会解决如下两个问题:
- 单进程单线程并非完美,如今CPU基本均是多核的,真正的服务器(非VPS)往往还有多个CPU。——如何充分利用多核CPU服务器?
- 由于Node执行在单线程上,一旦单线程上抛出的异常没有捕获,将会引起整个进程的崩溃。——如何保证进程的健壮性和稳定性?
9.1 服务模型的变迁
9.1.1 石器时代:同步
9.1.2 青铜时代:复制进程
9.1.3 白银时代:多进程
9.1.4 黄金时代:事件驱动
9.2 多进程架构
面对单进程单线程对多核使用不足的问题,前人的经验是启动多进程即可。理想状态下每个进程各自利用一个CPU,以此实现多核CPU的利用。
Node提供了 child_process 模块,并且也提供了 child_process.fork()函数实现进程复制。
9.2.1 创建子进程
child_process 模块提供了4个方法用于创建子进程。
spawn(); // 启动一个子进程来执行命令。
exec(); // 启动一个子进程来执行命令,与spawn()不同的是其接口不同,它有一个回调函数获知子进程的状况。
execFile(); // 启动一个子进程来执行可执行文件。
fork(); // 与spawn()类似,不同点在于它创建的Node的子进程只需指定要执行的JavaScript文件模块即可。
- spawn()、exec()、execFile()不同点:后两者创建时可以指定timeout属性设置超时时间,一旦创建的进程超过设定的时间将会被杀死。
这里的可执行文件是指可以直接执行的文件,如果是JavaScript文件通过execFile()运行,它的首行内容必须添加如下代码:
#!/usr/bin/env node
尽管4种创建子进程的方式有些差别,但事实上后面三种方法都是spawn()的延伸应用。
9.2.2 进程间的通信
-
创建子进程后为了实现父子进程之间的通信,父与子之间会创建IPC通道,通过IPC通道父子进程之间才能通过
message和send()传递消息。 -
IPC(Inter-Process Communication)进程间的通信。实现进程间通信的技术也有很多,如:命名管道、匿名管道、socket、信号量、共享内存、消息队列、Domain Socket等。Node中实现IPC通道的是管道(pipe)技术。在Node中管道只是个抽象层面的称呼,具体实现由 libuv 提供,在Windows下有命名管道(named pipe)实现,*nix系统则采用Unix Domain Socket实现,表现在应用层上的进程间通信只有简单的 message 事件和 send() 方法。
-
与网络socket的行为比较类似,属于双向通信。不同的是他们在系统内核中就完成了进程间的通信,而不用经过实际的网络层,非常高效。
-
注意:只有启动的子进程是Node进程时,子进程才会根据环境变量去连接IPC通道,对于其他类型的子进程无法实现进程间的通信,除非其他进程也按约定去连接这个已经创建好的IPC通道。
9.2.3 句柄传递
send(message, [sendHandle])方法除了能通过IPC发送数据外,还能发送句柄,第二个可选参数就是句柄。
什么是句柄?一种可以用来标识资源的引用,它的内部包含了指向对象的文件描述符。比如句柄可以用来标识一个服务器端socket对象、一个客户端socket对象、一个UDP套接字、一个管道等。P252
发送句柄意味着什么?在前一个问题中,我们可以去掉代理这种方案,使主进程接收到 socket 请求后,将这个socket直接发送给工作进程,而不是重新与工作进程之间建立新的socket连接来转发数据。文件描述符浪费的问题可以通过这样的方式轻松解决。P253
1、句柄发送与还原
2、端口共同监听
9.2.4 小结
至此,我们介绍了创建子进程、进程间通信的IPC通道实现、句柄在进程间的发送和还原、端口共用等细节。通过这些基础技术,用child_process模块在单机上搭建Node集群是件相当容易的事情。因此在多核CPU的环境下让Node进程能够充分利用资源不再是难题。
9.3 集群稳定之路
- 性能问题。
- 多个工作进程的存活状态管理。
- 工作进程的平滑重启。
- 配置或者静态数据的动态重新载入。
- 其他细节。
9.3.1 进程事件 P258
9.3.2 自动重启 P259
9.3.3 负载均衡 P264
9.3.4 状态共享 P265
9.4 Cluster 模块
前文介绍了child process模块中的大多数细节,以及如何通过这个模块构建强大的单机集群。如果熟知Node,也许你会惊讶为何迟迟不谈cluster模块。上述提及的问题,Node在v0.8版本时新增的cluster模块就能解决。在v0.8版本之前,实现多进程架构必须通过child process来实现,要创建单机Node集群,由于有这么多细节需要处理,对普通工程师而言是一件相对较难的工作,于是v0.8时直接引入了cluter模块,用以解决多核CPU的利用率问题,同时也提供了较完善的API,用以处理进程的健壮性问题。
P267
9.4.1 Cluster 工作原理
事实上cluster模块就是child process和net模块的组合应用。cluster启动时,如同我们在9.2.3节里的代码一样,它会在内部启动TCP服务器,在cluster.fork()子进程时,将这个TCP服务器端socket的文件描述符发送给工作进程。如果进程是通过cluster.fork()复制出来的,那么它的环境变量里就存在NODE_UNIOUE_ID如果作进中存在listen()侦听网络端口的调用,它将拿到该文件描述符,通过SO_REUSEADDR端口重用,从而实现多个子进程共享端口。对于普通方式启动的进程,则不存在文件描述符传递共享等事情。
在cluster内部隐式创建TCP服务器的方式对使用者来说十分透明,但也正是这种方式使得它无法如直接使用child_process那样灵活。在cluster模块应用中,一个主进程只能管理一组工作进程,如下图所示。( 书中P268)

对于自行通过child process来操作时,则可以更灵活地控制工作进程,甚至控制多组工作进程。其原因在于自行通过child process操作子进程时,可以隐式地创建多个TCP服务器使得子进程可以共享多个的服务器端socket。
9.4.2 Cluster 事件
对于健壮性处理,cluster模块也暴露了相当多的事件。
- fork:复制一个工作进程后触发该事件。
- online:复制好一个工作进程后,工作进程主动发送一条nline消息给主进程,主进程收到消息后,触发该事件。
- listening:工作进程中调用listen()(共享了服务器端Socket)后,发送一条listening消息给主进程,主进程收到消息后,触发该事件。
- disconnect:主进程和工作进程之间IPC通道断开后会触发该事件。
- exit:有工作进程退出时触发该事件。
- setup:cluster.setupMaster()执行后触发该事件。
这些事件大多跟child process模块的事件相关,在进程间消息传递的基础上完成的封装这些事件对于增强应用的健壮性已经足够了。
9.5 总结
尽管Node从单线程的角度来讲它有够脆弱的:既不能充分利用多核CPU资源,稳定性也无法得到保障。但是群体的力量是强大的,通过简单的主从模式,就可以将应用的质量提升一个档次。在实际的复杂业务中,我们可能要启动很多子进程来处理任务,结构甚至远比主从模式复杂,但是每个子进程应当是简单到只做好一件事,然后通过进程间通信技术将它们连接起来即可。这符合Unix的设计理念,每个进程只做一件事,并做好一件事,将复杂分解为简单,将简单组合成强大。
尽管通过child_process模块可以大幅提升Node的稳定性,但是一旦主进程出现问题所有子进程将会失去管理。在Node的进程管理之外,还需要用监听进程数量或监听日志的方式确保整个系统的稳定性,即使主进程出错退出,也能及时得到监控警报,使得开发者可以及时处理故障。
个人心得:这章学得我脑壳痛,下次再重新学一遍然。
相关文章:
Node.js学习笔记-04
这第九章也是个大重点 九、玩转进程 Node在选型时决定在V8引擎之上构建,也就意味着它的模型与浏览器类似。 本章关于进程的介绍和讨论将会解决如下两个问题: 单进程单线程并非完美,如今CPU基本均是多核的,真正的服务器…...
基于dbn+svr的交通流量预测,dbn详细原理
目录 背影 DBN神经网络的原理 DBN神经网络的定义 受限玻尔兹曼机(RBM) DBN+SVR的交通流量预测 基本结构 主要参数 数据 MATALB代码 结果图 展望 背影 DBN是一种深度学习神经网络,拥有提取特征,非监督学习的能力,是一种非常好的分类算法,本文将DBN+SVR用于交通流量预测…...
【第一阶段】kotlin中反引号中的函数名特点
在kotlin中可以直接中文定义函数,使用反引号进行调用 eg: fun main() {2023年8月9日定义的函数(5) }private fun 2023年8月9日定义的函数(num:Int){println("反引号的用法$num") }执行结果 在Java中is,in可以定义方法,但是在kotlin中is,in是…...
数据分析-python学习 (1)numpy相关
内容为:https://juejin.cn/book/7240731597035864121的学习笔记 导包 import numpy as np numpy数组创建 创建全0数组,正态分布、随机数组等就不说了,提供了相应的方法通过已有数据创建有两种 arr1np.array([1,2,3,4,5]) 或者datanp.loadt…...
数据库的游标
数据库的游标(Cursor)是用于在数据库中进行数据操作的一个控制结构。它类似于在编程语言中使用的指针或迭代器,用于遍历数据库结果集并在结果集上执行各种操作。 游标允许我们在数据库查询的结果集中逐行移动,并对每一行执行特定…...
【设计模式】前端控制器模式
前端控制器模式(Front Controller Pattern)是用来提供一个集中的请求处理机制,所有的请求都将由一个单一的处理程序处理。该处理程序可以做认证/授权/记录日志,或者跟踪请求,然后把请求传给相应的处理程序。以下是这种…...
SQL | 过滤数据
4-过滤数据 4.1-使用WHERE子句 数据根据 WHERE 子句中指定的搜索条件进行过滤。WHERE 子句在表名( FROM 子句)之后给出。 select prod_name,prod_price from products where prod_price 3.49; 上述语句查询价格为3.49的行,然后输出名字和…...
【力扣每日一题】2023.8.13 合并两个有序数组
目录 题目: 示例: 分析: 代码: 题目: 示例: 分析: 题目给我们两个升序数组,让我们合并它们,要求合并之后仍然是升序,并且这个合并操作是在数组1原地修改…...
数据结构篇七:排序
文章目录 前言1.插入排序1.1 基本思想1.2 代码实现1.3 特性总结 2.希尔排序2.1 基本思想2.2 代码实现2.3 特性总结 3. 选择排序3.1 基本思想3.2 代码实现3.3 特性总结 4. 堆排序4.1 基本思想4.2 代码实现4.3 特性总结 5. 冒泡排序5.1 基本思想5.2 代码实现5.3 特性总结 6. 快速…...
Vue组件的边界情况
01.$root; 访问组件的根实例;用的不多,基本上在vuex上进行数据操作; 02.$parent/$children; 可以获得父组件或者子组件上边的数据;一般不建议使用$parent,因为如果获取这个值进行修改的话,也会更改父组件上…...
less、sass的使用及其区别
CSS预处理器 CSS 预处理器是一种扩展了原生 CSS 的工具,它们添加了一些编程语言的特性,以便更有效地编写、组织和维护样式代码。预处理器允许开发者使用变量、嵌套、函数、混合等功能,从而使 CSS 更具可读性、可维护性和重用性,特…...
[保研/考研机试] 猫狗收容所 C++实现
题目描述: 输入: 第一个是n,它代表操作序列的次数。接下来是n行,每行有两个值m和t,分别代表题目中操作的两个元素。 输出: 按顺序输出收养动物的序列,编号之间以空格间隔。 源代码ÿ…...
Kotlin 基础教程一
Kotlin 基本数据类型 Java | Kotlin byte Byte short Short int Int long Long float Float double Double boolean Boolean c…...
数据结构笔记--前缀树的实现
1--前缀树的实现 前缀树的每一个节点拥有三个成员变量,pass表示有多少个字符串经过该节点,end表示有多少个字符串以该节点结尾,nexts表示该字符串可以走向哪些节点; #include <iostream> #include <unordered_map>str…...
C/C++时间获取函数
time.h包含C/C中用于获取时间,和时间转换方面的函数。 1、time() 函数 time_t time(time_t *seconds) 返回自(1970-01-01 00:00:00 UTC)起经过的时间,以秒为单位。如果 seconds 不为空,则返回值也存储在变量 seconds …...
sql中判断日期是否是同一天
sql中判断日期是否是同一天的sql sql: select id,product_id,seckill_price,stock_count,time,intergral,start_date from t_seckill_product where to_days(start_date) to_days(now()) to_days函数: 使用to_days(start_date) to_days(now())的方式是一种常见的…...
NAS搭建指南一——服务器的选择与搭建
一、服务器的选择 有自己的本地的公网 IP 的请跳过此篇文章按需求选择一个云服务器,目的就是为了进行 frp 的搭建,完成内网穿透我选择的是腾讯云服务器,我的配置如下,仅供参考: 4. 腾讯云服务器官网地址 二、服务器…...
豪越HYDO智能运维助力智慧医院信息化建设
随着国家政策的推动与支持,医疗行业信息化应用不断普及,大数据、AI、医疗物联网等技术的应用,快速推动了电子病历、智慧服务、智慧管理的智慧医院建设和医院信息标准化建设,通过不断探索创新“智慧医院”服务模式,实现…...
Week1题目重刷
今天把week1的题目都重新刷了一遍,明天开始week2的内容~ 704.二分查找 class Solution {public int search(int[] nums, int target) {int l 0, r nums.length - 1, m;while (l < r) {m (l r) >>> 1;if (nums[m] < target) {l m 1;} else if…...
考研数据结构:第七章 查找
文章目录 一、查找的基本概念二、顺序查找和折半查找2.1顺序查找2.3折半查找2.3.1算法思想2.3.2代码实现2.3.3查找效率分析2.3.4折半查找判定树的构造2.3.5折半查找效率2.3.6小结 2.4分块查找 三、树形查找3.1二叉排序树3.1.1二叉排序树定义3.1.2查找操作3.1.3插入操作3.1.4二叉…...
AI基础设施权力更迭:AWS Bedrock 凭什么在 2026 年让开发者集体“倒戈”?
声明:本文由AI编辑生成,内容仅供参考。文中涉及的行业判断、平台能力分析、商业趋势推演与产品价值描述,均基于公开资料、通用观察及示意性表达整理,不构成任何商业承诺、采购建议、投资建议或服务保证。实际产品能力、接口支持范…...
2026年三角洲俱乐部3×3保险箱:守护私密空间的智能选择
在《三角洲行动》这款充满策略与竞技的游戏中,无论是珍贵的“暗星燃料”、“勇者之证”,还是辛苦积累的“哈夫币”,都是玩家心血的结晶。如何安全、便捷地管理这些虚拟资产,成为许多玩家,尤其是高端玩家和团队管理者关…...
OpenClaw个人知识库:Qwen3-32B+Obsidian自动化信息归档系统
OpenClaw个人知识库:Qwen3-32BObsidian自动化信息归档系统 1. 为什么需要自动化知识管理 作为一个长期被信息过载困扰的技术写作者,我每天需要处理数十篇技术文章、研究报告和行业动态。传统的手动分类方式让我陷入两个困境:一是收藏的文章…...
SpringCloud-Stream + RocketMQ/Kafka
一、核心认知:Spring Cloud Stream 是什么?解决什么问题?1.1 基本定义Spring Cloud Stream 是 Spring 生态下的「消息驱动微服务框架」,基于 Spring Boot 构建,核心定位是「统一消息中间件接口,简化消息驱动…...
从零入门性能测试:理论+JMETER实操,看完就能上手婪
一、环境准备 Free Spire.Doc for Python 是免费 Python 文档处理库,无需依赖 Microsoft Word,支持 Word 文档的创建、编辑、转换等操作,其中内置的 Markdown 解析能力,能高效实现 Markdown 到 Doc/Docx 格式的转换,且…...
如何用Tweepy构建强大的Twitter数据分析报告:5个高级搜索聚合技巧
如何用Tweepy构建强大的Twitter数据分析报告:5个高级搜索聚合技巧 【免费下载链接】tweepy Twitter for Python! 项目地址: https://gitcode.com/gh_mirrors/tw/tweepy Tweepy是Python中最流行的Twitter API客户端库,让开发者能够轻松访问Twitter…...
FaceFusion快速部署指南:无需配置,开箱即用的AI换脸神器
FaceFusion快速部署指南:无需配置,开箱即用的AI换脸神器 想体验电影级的AI换脸特效,却苦于复杂的安装配置?今天给大家介绍一个真正的“开箱即用”神器——FaceFusion。它把那些繁琐的命令行、环境依赖、模型下载全部打包好&#…...
GCViewer扩展开发终极指南:自定义数据读取器与导出格式的完整教程
GCViewer扩展开发终极指南:自定义数据读取器与导出格式的完整教程 【免费下载链接】GCViewer Fork of tagtraum industries GCViewer. Tagtraum stopped development in 2008, I aim to improve support for Suns / Oracles java 1.6 garbage collector logs (inclu…...
使用开源 Authentik 实现 AWS 单点登录
前言 懒得自己编了, Gemini 这样介绍 Authentik: 简单来说,Authentik 是一款功能极其强大的开源身份验证与访问管理 (IAM) 解决方案。 如果你觉得像 Okta 或 Auth0 这种商业服务太贵,或者觉得像 Keycloak 这种传统方案配置起来太头疼,那么…...
HTML函数在老旧浏览器运行慢是硬件问题吗_软硬协同分析【教程】
老旧浏览器HTML操作卡顿主因是渲染与JS引擎陈旧,如IE8不支持CSS3选择器致querySelectorAll遍历DOM;验证需看Performance面板中Recalculate Style/Layout占比超60%;兼容须降级:拆解选择器、用DocumentFragment批量插入、避免强制同…...
