前言

Nodejs目前处境稍显尴尬很多语言都已经拥有异步非阻塞的能力阿里的思路是比较合适的但是必须要注意绝对不能让node做太多的业务逻辑他只适合接收生成好的数据然后或渲染后或直接发送到客户端

为什么nodejs 还可以成为主流技术哪

是因为nodejs 对于大前端来说还是非常重要的技术!!!如果你理解nodejs 的编程原理很容易就会理解angularjsreactjs vuejs 的设计原理

 

NodeJS

Node是一个服务器端JavaScript解释器用于方便地搭建响应速度快易于扩展的网络应用。Node使用事件驱动非阻塞I/O 模型而得以轻量和高效非常适合在分布式设备上运行数据密集型的实时应用
Node是一个可以让JavaScript运行在浏览器之外的平台它实现了诸如文件系统模块操作系统 API、网络通信等Core JavaScript没有或者不完善的功能历史上将JavaScript移植到浏览器外的计划不止一个Node.js 是最出色的一个

 

V8引擎

V8 JavaScript引擎是Google用于其Chrome浏览器的底层JavaScript引擎很少有人考虑JavaScript在客户机上实际做了些什么!

实际上,JavaScript引擎负责解释并执行代码。Google使用V8创建了一个用C++编写的超快解释器该解释器拥有另一个独特特征您可以下载该引擎并将其嵌入任何应用程序。V8 JavaScript引擎并不仅限于在一个浏览器中运行

因此,Node实际上会使用Google编写的V8 JavaScript引擎并将其重建为可在服务器上使用

 

事件驱动

在我们使用Java,PHP等语言实现编程的时候我们面向对象编程是完美的编程设计这使得他们对其他编程方法不屑一顾却不知大名鼎鼎Node使用的却是事件驱动编程的思想那什么是事件驱动编程
事件驱动编程为需要处理的事件编写相应的事件处理程序代码在事件发生时执行 
为需要处理的事件编写相应的事件处理程序要理解事件驱动和程序就需要与非事件驱动的程序进行比较实际上现代的程序大多是事件驱动的比如多线程的程序肯定是事件驱动的早期则存在许多非事件驱动的程序这样的程序在需要等待某个条件触发时会不断地检查这个条件直到条件满足这是很浪费cpu时间的而事件驱动的程序则有机会释放cpu从而进入睡眠态注意是有机会当然程序也可自行决定不释放cpu),当事件触发时被操作系统唤醒这样就能更加有效地使用cpu。
来看一张简单的事件驱动模型(uml):

 

事件驱动模型主要包含3个对象事件源事件和事件处理程序

  事件源产生事件的地方(html元素)

  事件点击/鼠标操作/键盘操作等等

  事件对象当某个事件发生时可能会产生一个事件对象该时间对象会封装好该时间的信息传递给事件处理程序

  事件处理程序响应用户事件的代码 

 

运行原理

当我们搜索Node.js夺眶而出的关键字就是 “单线程异步I/O,事件驱动”,应用程序的请求过程可以分为俩个部分:CPU运算和I/O读写,CPU计算速度通常远高于磁盘读写速度这就导致CPU运算已经完成但是不得不等待磁盘I/O任务完成之后再继续接下来的业务
所以I/O才是应用程序的瓶颈所在I/O密集型业务中假设请求需要100ms来完成其中99ms化在I/O如果需要优化应用程序让他能同时处理更多的请求我们会采用多线程同时开启100、1000个线程来提高我们请求处理当然这也是一种可观的方案
但是由于一个CPU核心在一个时刻只能做一件事情操作系统只能通过将CPU切分为时间片的方法让线程可以较为均匀的使用CPU资源但操作系统在内核切换线程的同时也要切换线程的上线文当线程数量过多时时间将会被消耗在上下文切换中所以在大并发时多线程结构还是无法做到强大的伸缩性
那么是否可以另辟蹊径呢?!我们先来看看单线程,《深入浅出Node》一书提到 “单线程的最大好处是不用像多线程编程那样处处在意状态的同步问题这里没有死锁的存在也没有线程上下文切换所带来的性能上的开销”,那么一个线程一次只能处理一个请求岂不是无稽之谈先让我们看张图

Node.js的单线程并不是真正的单线程只是开启了单个线程进行业务处理(cpu的运算),同时开启了其他线程专门处理I/O。当一个指令到达主线程主线程发现有I/O之后直接把这个事件传给I/O线程不会等待I/O结束后再去处理下面的业务而是拿到一个状态后立即往下走这就是单线程”、“异步I/O”。
I/O操作完之后呢?Node.jsI/O 处理完之后会有一个回调事件这个事件会放在一个事件处理队列里头在进程启动时node会创建一个类似于While(true)的循环它的每一次轮询都会去查看是否有事件需要处理是否有事件关联的回调函数需要处理如果有就处理然后加入下一个轮询如果没有就退出进程这就是所谓的事件驱动”。这也从Node的角度解释了什么是事件驱动”。
node.js事件主要来源于网络请求文件I/O根据事件的不同对观察者进行了分类有文件I/O观察者网络I/O观察者事件驱动是一个典型的生产者/消费者模型请求到达观察者那里事件循环从观察者进行消费主线程就可以马不停蹄的只关注业务不用再去进行I/O等待

 

优点

Node 公开宣称的目标是 “旨在提供一种简单的构建可伸缩网络程序的方法”。我们来看一个简单的例子 Java PHP 这类语言中每个连接都会生成一个新线程每个新线程可能需要 2 MB 的配套内存在一个拥有 8 GB RAM 的系统上理论上最大的并发连接数量是 4,000 个用户随着您的客户群的增长如果希望您的 Web 应用程序支持更多用户那么您必须添加更多服务器所以在传统的后台开发中整个 Web 应用程序架构包括流量处理器速度和内存速度中的瓶颈是服务器能够处理的并发连接的最大数量这个不同的架构承载的并发数量是不一致的
Node的出现就是为了解决这个问题更改连接到服务器的方式Node 声称它不允许使用锁它不会直接阻塞 I/O 调用。Node在每个连接发射一个在 Node 引擎的进程中运行的事件而不是为每个连接生成一个新的 OS 线程并为其分配一些配套内存)。

 

缺点

如上所述,nodejs的机制是单线程这个线程里面有一个事件循环机制处理所有的请求在事件处理过程中它会智能地将一些涉及到IO、网络通信等耗时比较长的操作交由worker threads去执行执行完了再回调这就是所谓的异步IO非阻塞吧但是那些非IO操作只用CPU计算的操作它就自己扛了比如算什么斐波那契数列之类它是单线程这些自己扛的任务要一个接着一个地完成前面那个没完成后面的只能干等因此CPU要求比较高的CPU密集型任务多的话就有可能会造成号称高性能适合高并发的node.js服务器反应缓慢

 

适合场景

1、RESTful API

这是适合 Node 的理想情况,因为您可以构建它来处理数万条连接。它仍然不需要大量逻辑;它本质上只是从某个数据库中查找一些值并将它们组成一个响应。由于响应是少量文本,入站请求也是少量的文本,因此流量不高,一台机器甚至也可以处理最繁忙的公司的 API 需求。

2、实时程序

比如聊天服务

聊天应用程序是最能体现 Node.js 优点的例子:轻量级、高流量并且能良好的应对跨平台设备上运行密集型数据(虽然计算能力低)。同时,聊天也是一个非常值得学习的用例,因为它很简单,并且涵盖了目前为止一个典型的 Node.js 会用到的大部分解决方案。

3、单页APP

ajax很多。现在单页的机制似乎很流行,比如phonegap做出来的APP,一个页面包打天下的例子比比皆是。

总而言之,NodeJS适合运用在高并发、I/O密集、少量业务逻辑的场景

 

posted on 2017-12-13 15:23  peiyu1988  阅读(12429)  评论(2编辑  收藏