Node.js学习——理论篇

本文已迁移至我的个人博客:http://ipenge.com/35934.html


前端时间学习了Node.js,重点看了《深入浅出Node.js》这本书,作为一个对javascript只有概念性认识的后端程序员,对Node多少有了一些自己的认识。将学习过程整理成两篇(理论篇、实战篇),方便与大家交流讨论。本文是第一篇——理论篇。

概念与源起

首先来看Node.js官网给出的对node的描述:

Node.js is a JavaScript runtime built on Chrome’s V8 Javascript engine. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient.

从该描述中,我们可以找出几个关键词:

JavaScript runtime:表明node.js是一个javascript的运行时环境。

V8:node构建在V8引擎上。

event-driven:时间驱动。

non-blocking I/O:非阻塞I/O。

以上四个特性成就了Node.js的流行,使它一度成为了github上最受关注的开源项目。

Node.js诞生于2009年。2009年5月,Ryan Dahl 在GitHub上发布了Node.js的最初版本。仅仅两年后,2011年11月,Node超过Ruby on Rails,成为GitHub上关注度最高的项目。(目前排在第4位, https://github-ranking.com/)


Node.js作者Ryan Dahl


github关注度排行。2016.8.29

Javascript发展历史

任何一项新技术都不是凭空产生的,而是在一个时代的大背景下,通常是站在巨人的肩膀上,Node.js也不例外。由于node.js使用javascript作为开发语言,因此这里我们来简单回顾一下javascript的发展历程。


javascript发展历史

1990年,www(world wide web)诞生,这是整个互联网的基石。

1994年,盛极一时的网景公司成立,并发布了navigator浏览器,大获成功,迅速占领了整个浏览器市场90%的份额。

1995年,网景公司意识到,需要一种一种运行在浏览器端的脚本,由于当时的带宽非常有限,很多表单数据提交到服务器后,才发现表单填写错误,这对带宽是一种浪费,如果能够在客户提交请求之前就做好检查,则一方面可以提升用户体验,另一方面减少带宽占用以及服务器端压力。在这种背景下,他们开发了一种脚本语言,名叫Mocha。由于同年,Java语言也刚刚诞生并大获流行,为了更提高知名度,网景公司与sun公司达成协议,将Mocha更名为Javascript。

1997年,为了使javascript能够成为浏览器脚本语言的通行标准,网景公司将javascript提交到ECMA标准化组织,该组织发布了ECMAScript1.0版本,javascript正式成为一种规范。

2005年,Ajax技术诞生。异步的应用,大大提升了客户端浏览体验。

2008年,google发布了V8引擎,该引擎性能强劲,是javascript引擎中名副其实的王者,这也使得javascript的性能不再成为瓶颈,为javascript的大范围应用提供了基础。

2009年,CommonJS规范发布,定义了很多应用程序接口,如文件系统,IO等,从而填补了javascript在浏览器之外领域的空白。该规范希望javascript可以在任何地方执行。同年,Node.js诞生,可以看到,Node.js的成功虽然离不开其基于事件的、异步IO特性,但是也离不开v8引擎的性能驱动以及commonJS规范的理论基础。

2010年,npm包管理器发布,从此开发者可以更方便的发布js模块,极大的促进了javascript生态的繁荣。

2011年,Node.js项目成为github最受欢迎的项目。

应用场景

基于node的特性,它特别适合两类应用:

IO密集型

可以使用node来搭建RESTfull API,来响应客户端的高并发请求。典型的RESTfull API通常的逻辑是接受请求,解析参数,然后查询数据库或缓存,进行一些简单的业务处理,然后返回结果。其中数据库查询是比较耗时的IO操作,其他业务处理都是非常快的,因此这种场景就适合使用Node.js来处理。

数据密集型

大批量数据的处理场景,例如队列输入,实时仪表盘等。淘宝指数就曾使用node.js来搭建服务,另外还有linkedid的移动端服务。linkedin在2011 年将核心移动端服务从ruby迁移到node.js,负责人给出三点理由:

(1)更高的性能,在特定场景下Node.js能比Rails快20倍。

(2)使用3个服务器而不是30个就能应对10倍的流量增长。

(3)前端工程师能够进行后端代码的开发,两个团队实际上合二为一了。

同步or异步

同步与异步的区别在于消息通知机制:

同步:发起调用后,被调用者不会立即返回结果,而是直到执行完毕才返回。(主动获取结果)

异步:发起调用后,被调用者立即返回,但是真正的结果是在被调用者执行完毕后通过消息通知、回调等方式告知调用者。(被动等结果通知)

同步


异步

拿去餐厅吃包子为例,同步的方式是,点完包子后,服务员不会主动告诉你包子好没好,你要想能吃到包子,就得自己反复的询问:“我的包子好了吗?”,最终吃到包子前,可能需要经过多次轮询。而异步则是点了包子后,服务员给你一个号码牌,你自己不用去问,包子好了会喊号。

阻塞or非阻塞

阻塞与非阻塞的区别在于等待结果的过程中会不会被挂起:

阻塞:结果返回前,调用方挂起,不能执行其他任务。(挂起)

非阻塞:结果返回前,调用方无需挂起,可以执行其他任务。(不挂起)


阻塞


非阻塞

仍然拿吃包子为例,阻塞的方式是:店里只有一个厨师,你点了包子后,他就去后厨做了,你也不知道他什么时候能做好,只能一直等着。非阻塞的方式是:店里有一个服务员,你点了包子后,服务员告诉厨师做包子,你可以随时问包子好了没有,如果没好,你可以做别的事情,如果好了,你就可以拿走吃包子了。

单线程or多线程

单线程和多线程区别在于任务是不是连续执行,会不会被中断:

单线程:一个任务处理完后才处理下一个任务。(无任务切换)

异步:同时处理多个任务,每个任务执行一段时间然后切换到下一个任务。(任务不断切换)


单线程


多线程

单线程:大家排好队买包子,一个一个的点单,做好了张三的包子,再给李四点单。

多线程:只有有人买包子,就可以点单,如果张三和李四都点单了,就做一会张三的包子,做一会李四的包子,哪个包子做好了就给哪个。

Node的就餐体验

店里有一个服务员负责点单,每个人点单后可以领到一个号码牌,包子好了就叫号。后厨有多名厨师负责制作包子。类似于肯德基和麦当劳。

异步:点完包子后,领到号码牌,等着叫号

非阻塞:等待叫号期间,可以做别的事

单线程:前台给一个客户点完餐后,接着给下一个客户点餐。

node执行过程

Node.js架构


node架构

application/modules:我们的应用程序或者模块,由javascript写成。

c/c++ binding:打通js和c++通信的胶水。由于上层应用是javascript,而v8和底层实现由C++写成,因此需要胶水语言进行不同语言间的通信。

Addons:提供给开发者使用的开发c模块供上层js使用的工具。

libuv:屏蔽不同操作系统底层异步功能的实现。Window系统使用IOCP(Input/Output Completion Port)实现;Linux系统使用epoll系统调用实现。

其他组件:包括node实现的一些底层功能模块,包括文件系统、http等等,也包括开发者自己用c++实现的功能模块。

IOCP和epoll

IOCP(I/O Completion Port):IO完成端口,是一种windows中的异步IO模式。其原理大致如下(个人理解,如有错误,敬请指正):

IOCP原理

首先有一个主线程,用于不停的接受IO请求,然后将请求绑定到ICOP上,然后发起一个异步调用去执行IO操作。IO完成后,数据已经被写入到缓冲区,同时将完成信息放入IOCP中。IOCP虽然名为完成端口,但其实是一个类似队列的存在,用于存放已经完成的IO事件信息。另有一个工作线程池,每个线程不停的检查IOCP中是否有完成的IO操作,如果有的话,就从缓冲区中读取已经完成的数据信息,执行后续的数据处理操作。

epoll是Linux内核为处理大批量文件描述符而作了改进的poll,是Linux下多路复用IO接口select/poll的增强版本,其大致工作原理如下:

epoll工作原理

在Linux中,有关epoll有3个系统调用函数,分别是epoll_create,epoll_ctl,epoll_wait。

epoll_create用于初始化,会在内核中创建一个高速cache,其中保存了一颗红黑树,每一个节点是一个IO事件。

epoll_ctl:用于添加IO事件,会将新的IO事件添加到红黑树中,等待执行。每个IO事件被注册到系统中断中,当执行完毕后,就放入就绪队列。

epoll_wait:从就绪队列中检查是否有已完成的IO事件,有的话做下一步处理。

Node.js生态

一项新的技术,我们是否考虑在生产环境使用,除了它本身是否足够优秀外,还要考虑这些技术的生态,是否有好的技术支持,是否有活跃的技术社区。就像我们买房子,除了房子本身的质量外,我们还会考虑物业是否完善,周围的配套设施是否完备。

可以说,node具有了非常良好的生态,一方面,有node.js基金会来负责维护,会不定期发布新版本,修改上个版本的bug(有好物业);另一方面,有非常繁荣的开发者社区,github上有成千上万的node模块,提供的日常开发所用到的各种基础模块,例如socket编程,mvc,单元测试,运维等等,基础设施足够完备。

有了以上基础,我们有理由相信,node.js将可以在很多领域给我们带来非常出色的表现,我们也可以尝试去使用这项技术。

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

推荐阅读更多精彩内容