NodeJS与Django协同应用开发(0) —— node.js 基础知识


系列目录


不管怎样,当你想要分享一个东西的时候你就逃不开要解释它是什么,它是做什么用的。所以作为基础知识储备,这里就介绍一下node.js以及其最重要的模块之一Socket.io。

node.js

对于node.js最多的介绍就是:它是基于异步事件驱动的高性能非阻塞IO框架。

所谓非阻塞IO模型(non-blocking I/O model),讲到这个恐怕得从最初的服务器网络模型说起。
最初的服务器都是单进程的阻塞IO,所有的请求都在同一个进程里连续处理,如果当前请求耗费了较长的CPU时间,那么其他后续所有请求都要等待这个请求处理结束后才能处理,而在处理期间这个进程也会被挂起。所谓是一卡全都卡。
在这之后发展出的是多进程多线程的网络模型。首先是简单的多进程模型:对于每一个连接都分配一个进程。这种做法简单粗暴得解决了一个请求阻塞导致全部请求都阻塞的问题,在请求量稍高但是不那么高的场景下完全足够了。但是当请求量一旦多起来,就又暴露出2个缺点:

  1. 一个进程所需的系统资源是不容忽视的,但是相比处理单个请求来说又显得杀鸡用牛刀,高并发情况下系统资源极易耗尽。
  2. 同时能够处理的进程数取决于CPU核数,进程越多就意味着更频繁的进程调度,也就意味着更多的时间被花在了切换进程上,导致整个系统的性能下降。
    于是又加入了多线程模型,让一个进程可以处理多个请求,以求降低系统资源的消耗。虽然多线程对于上述2个问题都能有所改善,但是治标不治本。创建线程开销小于创建进程,切换线程开销也小于切换进程(原因在于切换进程涉及到换页,涉及到代码段换入换出,线程不涉及代码段,只涉及数据段,也就是寄存器状态和栈状态),不过这只是把压力阈值提高了一些而已,依然有一部分系统资源、CPU时间浪费在了非处请请求上。

到这里为止所说的都还是阻塞IO模型,也就是一个处理请求的单元从收到请求,处理请求,到返回结果之间都是线性的,任何一步因为任何原因阻塞了都会导致这个处理单元的阻塞,并被挂起。假如我们在一个请求的处理过程中需要查询数据库,或是依赖外部服务,而这些操作又有很大的延迟,那么在这段时间内处理单元就会被挂起,但由于这个请求没有处理完,资源就不能拿出来处理其他的请求。所以哪怕服务负载特别高,资源的利用率也不高。所以就催生出了非阻塞IO模型。
在非阻塞IO模型里,最重要的一点就是任何操作都不会将当前处理单元挂起,从而能够允许其执行之后的请求。这么做的好处在于更大化得利用了CPU时间,让CPU时刻都在处理需要处理的事务。所以在这种模型下,多进程多线程就显得没那么必要,只要能够完全利用CPU的核数,单线程也完全足够,且性能还要优于之前的模型。这也是为什么现在的负载均衡器都建议按照CPU核数来部署应用。

举个例子,假设我们只有一个进程(单线程),此时来了3个请求,第一个请求需要查询数据库,耗时500ms,第二个请求需要调用外部服务,耗时2000ms,第三个请求查询系统时间,耗时5ms。
在普通的阻塞IO模型里,第一个请求来了之后先花500ms处理完,再花2000ms处理第二个请求,再花5ms处理第三个请求。也就是说第一个用户500ms后得到了结果,第二个用户却用了2500ms得到结果,第三个用户仅仅只要查一下时间却用了2505ms才得到结果。
而在非阻塞IO模型里,同样第一个请求过来后,查询工作交给数据库,紧接着就开始处理第二个请求。同样任务交给外部服务后,就开始处理第三个请求。第三个请求很快就得到了结果,并返回给了用户,此时才经过了5ms。在500ms的时间点,数据库查询工作结束,并返回给了第一个用户,在2000ms的时间点,外部服务返回了结果,于是就返回给了第二个用户。

下面这个表格就很清楚的展示了两种模型的差异。

发起请求到获得结果时间表 阻塞IO模型 非阻塞IO模型
用户1 500ms 500ms
用户2 2500ms 2000ms
用户3 2505ms 5ms

可以看出,非阻塞IO模型在请求量很多的时候,对于每一个用户而言都有很好的体验。

这一系列的演化,举个例子,就好比有一个水库需要排水,最初你只有一个水管(单进程)排水,突然有些水草把管子堵住了(当前请求阻塞),那在你把水草清理掉之前水都流不出来(所有请求阻塞)。后来你决定再多买一些水管(多进程),但是受财力限制你只能买100根(系统资源耗尽)。不过水草堵了之后依然需要人力来清理,但是依然财力所限你只能请4个工人(CPU核数),而工人大部分时间又花在了在水管间走来走去,而不是实际清理水草上(进程切换)。这时候有个公司过来找你说他们有种技术可以把25根管子包进一个大管子里,看上去你只用了4个水管排水(多线程),而且还比原来便宜(减少系统资源开销)。但是水管依然会堵,工人依然要找究竟哪个小管子堵了(线程依然需要切换)。再后来又有个公司过来找你说有一套新型管子,能够在水草堵住的时候自动切换到备用水管,并自动开始清理水草,永远能够让水顺利流出(非阻塞模型),价值是原来的一个工人和25根水管的总和。于是你非常开心的辞退了所有工人,卖了原先的所有水管,买了4套新型管子(最大化利用CPU核数)。此后就再也不用担心水排不出了。

这就是非阻塞IO模型,而node.js的设计初衷就是搭建灵活的网络应用,于是在此之上选用了JavaScript这一灵活的语言和异步事件驱动设计。

所谓事件驱动(event-driven),通俗来讲就是发生了什么事,我们才做相应的处理。这里的事件可以是一个用户操作,可以是一次内容变化,也可以是一次网络请求,甚至可以是一次系统异常。凡是我们关心的,都可以成为事件,然后我们再做相应的处理。

而异步(asynchronous communication)的意思就是说,当一个调用到来时,并不等到有结果了再返回,而是直接返回,有结果了再通知调用方。
同步与异步、阻塞与非阻塞,看上去非常相似但本质是不同的。同步异步关心的是消息通信机制,阻塞非阻塞关心的是等待调用结果时的状态。

以下内容引用自知乎用户 卢毅 在问题怎样理解阻塞非阻塞与同步异步的区别?中的回答:

[同步异步]
举个通俗的例子:
你打电话问书店老板有没有《分布式系统》这本书,如果是同步通信机制,书店老板会说,你稍等,”我查一下",然后开始查啊查,等查好了(可能是5秒,也可能是一天)告诉你结果(返回结果)。
而异步通信机制,书店老板直接告诉你我查一下啊,查好了打电话给你,然后直接挂电话了(不返回结果)。然后查好了,他会主动打电话给你。在这里老板通过“回电”这种方式来回调。

[阻塞非阻塞]
还是上面的例子,
你打电话问书店老板有没有《分布式系统》这本书,你如果是阻塞式调用,你会一直把自己“挂起”,直到得到这本书有没有的结果,如果是非阻塞式调用,你不管老板有没有告诉你,你自己先一边去玩了, 当然你也要偶尔过几分钟check一下老板有没有返回结果。
在这里阻塞与非阻塞与是否同步异步无关。跟老板通过什么方式回答你结果无关。

而node.js在运行时是采用单线程架构的,又综合了异步与非阻塞的优点,这就是为什么它还能保持高性能的原因。至于为什么node.js选用了JavaScript和异步事件驱动,那就不是这里论述的话题了,只能说它就是这么选了,它乐意。

题外话:
node.js选择了JavaScript,所以就选择了Google V8引擎,而原本V8是为了浏览器所设计的高性能js解释器,因此并不具备多线程能力,所以node.js也只能是单线程架构。但我认为如果技术上能够让node.js支持多线程,性能并不会高于单线程。引入多线程就势必引入锁,在某些情况下加锁的开销是不能忽略的,所以不见得多线程就是好。不过单线程的node.js并不能100%发挥出多核CPU的能力,所以通过child_process.fork(),也就是现在的cluster模块,允许node在多进程下编程。这样更加能够利用硬件资源来支撑高并发高访问量。

Socket.io

相比node.js, socket.io就简单得多了。这是一个用来构建实时web应用的JavaScript库,对于浏览器的客户端和后台服务器端有两套接口相似的库,与node.js相同,它也是事件驱动的。
多数情况下socket.io是基于websocket协议的,但是对于不支持的浏览器它也能够自动回退到flash或是长轮询。
socket.io的好处就在于自动选择合适的协议,简单易上手的api。可以说node.js的热度有相当一部分是由socket.io撑起来的。
对于socket.io也没有那么多可以介绍的,各种特性实例代码一看便知,所以这篇文章就先写到这吧,后文会搭建出一套node.js+socket.io+Django+redis的原型,更详细的内容可以移步那里。

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

推荐阅读更多精彩内容