了解Node.js机制,这就够了

使用了这么久的Node.js,之前只是知道它怎么使用,并没有去深入的了解它的机制,那么今天就来聊聊它的使用机制优缺点以及适合使用的场景

是什么

Node.jsJavaScript运行平台,底层是采用c++编写的,基于JavaScript V8引擎,意味着你可以使用JavaScript编写服务器端代码,然后交给Node.js去解释执行

特点

  • 事件驱动
  • 非阻塞异步I/O
  • 模块化
  • 单线程

运行机制解析

应用程序的瓶颈所在

应用程序的请求过程可以分为两个部分:CPU 运算和 I/O读写,CPU计算速度通常远高于磁盘读写速度,这就导致CPU运算已经完成,但是不得不等待磁盘I/O任务完成之后再继续接下来的业务。所以I/O才是应用程序的瓶颈所在,在I/O密集型业务中,I/O操作会使用大量的时间,而CPU只需很短的时候,这样就会使得性能不够好,那么一般都会使用多线程去优化,同时开启多个线程去处理请求,这样就会快很多。
但是由于一个CPU核心在一个时刻只能做一件事情,操作系统只能通过将CPU切分为时间片的方法,让线程可以较为均匀的使用CPU资源。但操作系统在内核切换线程的同时也要切换线程的上下文,当线程数量过多时,上下文切换会造成系统的很大开销,所以在大并发时,多线程结构还是无法做到强大的伸缩性。

使用Node.js解决瓶颈问题

Node.js的单线程并不是真正的单线程,只是开启了单个线程进行业务处理(cpu的运算),同时开启了其他线程专门去处理I/O。当一个指令到达主线程,主线程发现有I/O之后,直接把这个事件传给 I/O线程,不会等待I/O结束后,再去处理下面的业务,而是拿到一个状态后立即往下走,这就是单线程异步I/O
I/O操作完之后呢?Node.jsI/O 处理完之后会有一个回调事件,这个事件会放在一个事件处理队列里头,在进程启动时node会创建一个类似于While(true)的循环,它的每一次轮询都会去查看是否有事件需要处理,是否有事件关联的回调函数需要处理,如果有就处理,然后加入下一个轮询,如果没有就退出进程,这就是所谓的事件驱动

那么当我是多核CPU的时候呢?还有就是当主线程业务运算超时,岂不是来不及处理事件队列里的事件?
对于这俩个问题,首先要做的一点就是在代码编写的时候尽量避免耗时的计算,将大计算进行拆分,这样能够让主线程及时得到释放,处理消费事件队列里头的事件。其次,node.js提供了child_process模块开启子进程,理想状态下每个进程各自利用一个CPU,以此实现多核的利用,child_process提供创建子进程,以及进程状态监控,进程之间通信的API等。

一个Node.js饭店的发展历程

前面的一堆理论似乎不太好明白,最后讲一个关于饭店发展历程的故事作为结尾吧。

  • 第一年
    饭店开张,只有一个厨师(同时还兼任老板、服务员、打荷、收银员),当一个客人点餐之后,这个厨师就开始记录(服务员),然后他就开始备菜(打荷)、炒菜(厨师)、然后上菜(服务员)、收钱(收银员),这个时候即使有其他客人来了,等着吧还没忙完呢。这个厨师就这样兢兢业业,有条不紊的干着每一件事,因为每件事都是亲力亲为,都不能出错,虽然所有的事情都了然于心,但效率很低,一天只能卖出十多份饭菜。
    这是饭店单线程的第一年:
    :它没有线程上下文交换所带来性能上的开销(因为每件事都是亲力亲为);
    :无法利用多核CPU(厨房空间那么大,完全可以很多人一起干活),同时错误会引起整个应用退出,应用的健壮性值得考验(当这个厨师生病,或者有事了饭店就得停业)

  • 第二年
    这个厨师第一年赚了点钱,回到老家把表哥、表弟全拉过来,现在他们有5个人,可工作方式还是跟厨师第一年的时候一样。当客人来了,就会有一个人去记录,然后自己去厨房洗菜、切菜、炒菜、洗碗、上菜、收钱。当来了第六个客人的时候,就要等待前面的人做完所有事情才能空出一个人来接待。后来他们就想既然客户多了,厨师就得多,再回老家多叫几个兄弟吧。这时新的问题发生了,当每个厨师做完饭后就出去找客人,客人说我刚刚点餐了,然后厨师就去厨房问,刚刚是哪个表兄接待的那个客户,要是没有人接待的话,我来处理。就这样忙忙碌碌一年,他们比去年多做了好多生意,但是感觉每天客户多的时候,厨房里头乱糟糟的,总要询问这个询问那个。
    这就是饭店多线程的一年:
    :一个线程服务一个请求,线程之间可以共享数据,这样可以避免内存的浪费,可以同时处理多个请求;
    :操作系统内核在切换线程的同时也要切换线程的上下文,当线程数量过多时,时间将会被消耗在上下文切换上(厨房里头乱糟糟的,总要询问这个询问那个)。

  • 第三年
    老板娘过来了(Node.Js闪亮登场),她发现这帮厨师都在各自为战,自己拿到客户的点餐后去洗菜、切菜、洗碗、炒菜、上菜、收钱,一个人只能同时处理一个任务,而且作为厨师没必要去做洗菜、切菜、洗碗、收银之类费时的工作。
    所以老板娘把所有人进行了分工:
    老板作为厨师长(Node里头的主线程),他不再去洗碗、洗菜、切菜、炒菜、收银(我们可以把洗碗、洗菜、炒菜、切菜认为是比较耗时的I/O),他只负责将收银台小妹(观察者)拿过来的菜单分配给不同的厨师,打荷(这些人就是不同的I/O线程),吩咐下去之后他不会等菜出来再走(进入下一个轮询),又问收银台小妹还有没有菜单要做,如果有继续轮询,如果没有了休息(退出进程)。当菜做出来之后放在上菜区(回调),收银台就显示菜出来了(将回调放入事件队列),当老板查询收银员(观察者)的时候,收银员就告诉厨师长,厨师长就通知服务员(处理不同I/O的线程)上菜(完成回调),这样饭店有条不紊的运行下去,客人也越来越多了。
    有些高端客户不想在这挤,所以老板娘就想,饭店房子那么大(多核CPU),可以叫她弟弟(子进程的主线程)在这开个子店(child_process),然后发现一个收银员不够用,那就多招几个收银员(多个观察者),就这样每个分店(进程)只有一个主管(主线程),主管的弱点就是无暇顾及洗碗等杂活(I/O),只能关注业务,至于饭店能开多大(应用程序能处理多大请求),要看主管的处理能力(主线程的编程强壮度)。最后,大饭店起了个时髦的名字叫Hotel NodeJs

优缺点

优点
  1. 高并发(最重要的优点)
  2. 适合I/O密集型应用
  3. 现在新版本的Node.js已经可以使用子进程来充分利用多核CPU
缺点:
  1. 不适合CPU密集型应用;
    由于JavaScript单线程的原因,如果有长时间运行的计算(比如大循环),将会导致CPU时间片不能释放,使得后续I/O无法发起;
    解决方案:分解大型运算任务为多个小任务,使得运算能够适时释放,不阻塞I/O调用的发起;
  2. 可靠性低,一旦代码某个环节崩溃,整个系统都崩溃
    原因:单进程,单线程
    解决方案
    (1)Nnigx反向代理,负载均衡,开多个进程,绑定多个端口;
    (2)开多个进程监听同一个端口,使用cluster模块;
    (3)使用child_process
  3. 回调太多,代码不易读
  4. Debug不方便

使用NodeJS的场景

适合使用
  1. RESTful API
    Node.js可以充分发挥其非阻塞I/O模型以及JavaScriptJSON的功能支持(如JSON.stringfy函数)
  2. 单页面、多Ajax请求应用
    如Gmail,前端有大量的异步请求,需要服务后端有极高的响应速度
  3. 基于Node.js开发Unix命令行工具
    Node.js可以大量生产子进程,并以流的方式输出,这使得它非常适合做Unix命令行工具
  4. 流式数据
    传统的Web应用,通常会将HTTP请求和响应看成是原子事件。而Node.js会充分利用流式数据这个特点,构建非常酷的应用。如实时文件上传系统transloadit
不适合使用
  1. CPU使用率较重、I/O使用率较轻的应用
    如视频编码、人工智能等,Node.js的优势无法发挥
  2. 简单Web应用
    此类应用的特点是,流量低、物理架构简单,Node.js无法提供强大的框架

参考文档:http://www.csdn.net/article/a/2016-07-12/3358

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 198,932评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,554评论 2 375
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 145,894评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,442评论 1 268
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,347评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,899评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,325评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,980评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,196评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,163评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,085评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,826评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,389评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,501评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,753评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,171评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,616评论 2 339

推荐阅读更多精彩内容

  • 零、什么是Node.js? 引用Node.js官方网站的解释如下: Node.js® is a JavaScrip...
    JokerPeng阅读 2,981评论 0 15
  • topics: 1.The Node.js philosophy 2.The reactor pattern 3....
    宫若石阅读 1,041评论 0 1
  • 这是一个移动端工程师涉足前端和后端开发的学习笔记,如有错误或理解不到位的地方,万望指正。 Node.js 是什么 ...
    单纯的土豆阅读 1,211评论 2 17
  • 设计高性能Web服务器的要点在于非阻塞I/O和事件驱动 Node最大的特点是异步式I/O(非阻塞I/O)与事件紧密...
    JunChow520阅读 2,011评论 0 0
  • 姓名:张义跃 245期谦虚1组学员 公司:本一设计 【日精进打卡第80天】 【知~学习】 《六项精进》诵读0遍共3...
    小小蛋儿阅读 150评论 0 0