概述:

  NodeJS宣称其目标是“旨在提供一种简单的构建可伸缩网络程序的方法”,那么它的出现是为了解决什么问题呢,它有什么优缺点以及它适用于什么场景呢?

  本文就个人使用经验对这些问题进行探讨。

一. NodeJS的特点

  我们先来看看NodeJS官网上的介绍:

  Node.js is a platform built on Chrome's JavaScript runtime for easily building fast, scalable network applications. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices.

  其特点为:

  1. 它是一个Javascript运行环境

  2. 依赖于Chrome V8引擎进行代码解释

  3. 事件驱动

  4. 非阻塞I/O

  5. 轻量、可伸缩,适于实时数据交互应用

  6. 单进程,单线程

二. NodeJS带来的对系统瓶颈的解决方案

  它的出现确实能为我们解决现实当中系统瓶颈提供了新的思路和方案,下面我们看看它能解决什么问题

  1. 并发连接

  举个例子,想象一个场景,我们在银行排队办理业务,我们看看下面两个模型

  (1)系统线程模型:

  

  这种模型的问题显而易见,服务端只有一个线程,并发请求(用户)到达只能处理一个,其余的要先等待,这就是阻塞,正在享受服务的请求阻塞后面的请求了

  (2)多线程、线程池模型:

  

  这个模型已经比上一个有所进步,它调节服务端线程的数量来提高对并发请求的接收和响应,但并发量高的时候,请求仍然需要等待,它有个更严重的问题:

  回到代码层面上来讲,我们看看客户端请求与服务端通讯的过程:

  

  服务端与客户端每建立一个连接,都要为这个连接分配一套配套的资源,主要体现为系统内存资源,以PHP为例,维护一个连接可能需要20M的内存

  这就是为什么一般并发量一大,就需要多开服务器

  那么NodeJS是怎么解决这个问题的呢?

  我们来看另外一个模型,想象一下我们在快餐店点餐吃饭的场景

  (3)异步、事件驱动模型

  

  我们同样是要发起请求,等待服务器端响应;但是与银行例子不同的是,这次我们点完餐后拿到了一个号码,

  拿到号码,我们往往会在位置上等待,而在我们后面的请求会继续得到处理,同样是拿了一个号码然后到一旁等待,接待员能一直进行处理。

  等到饭菜做号了,会喊号码,我们拿到了自己的饭菜,进行后续的处理(吃饭)

  这个喊号码的动作在NodeJS中叫做回调(Callback),能在事件(烧菜,I/O)处理完成后继续执行后面的逻辑(吃饭),

  这体现了NodeJS的显著特点,异步机制、事件驱动

  整个过程没有阻塞新用户的连接(点餐),也不需要维护已经点餐的用户与厨师的连接

  基于这样的机制,理论上陆续有用户请求连接,NodeJS都可以进行响应,因此NodeJS能支持比Java、PHP程序更高的并发量

  虽然维护事件队列也需要成本,再由于NodeJS是单线程,事件队列越长,得到响应的时间就越长,并发量上去还是会力不从心

  

  总结一下NodeJS是怎么解决并发连接这个问题的:

  更改连接到服务器的方式,每个连接发射(emit)一个在NodeJS引擎进程中运行的事件(Event),放进事件队列当中,

  而不是为每个连接生成一个新的OS线程(并为其分配一些配套内存)

  2. I/O阻塞

  NodeJS解决的另外一个问题是I/O阻塞,看看这样的业务场景:需要从多个数据源拉取数据,然后进行处理

  (1)串行获取数据,这是我们一般的解决方案,以PHP为例

  

  假如获取profile和timeline操作各需要1S,那么串行获取就需要2S

  (2)NodeJS非阻塞I/O,发射/监听事件来控制执行过程

  

  NodeJS遇到I/O事件会创建一个线程去执行,然后主线程会继续往下执行的,

  因此,拿profile的动作触发一个I/O事件,马上就会执行拿timeline的动作,

  两个动作并行执行,假如各需要1S,那么总的时间也就是1S

  它们的I/O操作执行完成后,发射一个事件,profile和timeline,

  事件代理接收后继续往下执行后面的逻辑,这就是NodeJS非阻塞I/O的特点

  总结一下:

  Java、PHP也有办法实现并行请求(子线程),但NodeJS通过回调函数(Callback)和异步机制会做得很自然

三. NodeJS的优缺点

  优点:

  1. 高并发(最重要的优点)

  2. 适合I/O密集型应用

    缺点:

  1. 不适合CPU密集型应用;CPU密集型应用给Node带来的挑战主要是:由于JavaScript单线程的原因,如果有长时间运行的计算(比如大循环),将会导致CPU时间片不能释放,使得后续I/O无法发起;

    解决方案:分解大型运算任务为多个小任务,使得运算能够适时释放,不阻塞I/O调用的发起;

  2. 只支持单核CPU,不能充分利用CPU

  3. 可靠性低,一旦代码某个环节崩溃,整个系统都崩溃

    原因:单进程,单线程

    解决方案:(1)Nnigx反向代理,负载均衡,开多个进程,绑定多个端口;

         (2)开多个进程监听同一个端口,使用cluster模块;

  4. 开源组件库质量参差不齐,更新快,向下不兼容

  5. Debug不方便,错误没有stack trace

四. 适合NodeJS的场景

  1. RESTful API

  这是NodeJS最理想的应用场景,可以处理数万条连接,本身没有太多的逻辑,只需要请求API,组织数据进行返回即可。

  它本质上只是从某个数据库中查找一些值并将它们组成一个响应。

  由于响应是少量文本,入站请求也是少量的文本,因此流量不高,一台机器甚至也可以处理最繁忙的公司的API需求。

  2. 统一Web应用的UI层

  目前MVC的架构,在某种意义上来说,Web开发有两个UI层,一个是在浏览器里面我们最终看到的,另一个在server端,负责生成和拼接页面。

  

  不讨论这种架构是好是坏,但是有另外一种实践,面向服务的架构,更好的做前后端的依赖分离。

  如果所有的关键业务逻辑都封装成REST调用,就意味着在上层只需要考虑如何用这些REST接口构建具体的应用。

  那些后端程序员们根本不操心具体数据是如何从一个页面传递到另一个页面的,他们也不用管用户数据更新是通过Ajax异步获取的还是通过刷新页面

  

  3. 大量Ajax请求的应用

  例如个性化应用,每个用户看到的页面都不一样,缓存失效,需要在页面加载的时候发起Ajax请求,

  NodeJS能响应大量的并发请求

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

五. 结尾

  其实NodeJS能实现几乎一切的应用

  我们考虑的点只是适不适合用它来做

六. 参考文献

  [1] Node.js能构建支持并发和高负载的大型应用吗?

  [2] 理解Node.js事件驱动编程

  [3] 是否不擅长CPU密集型业务

  [4] 使用 Node.js 的优势和劣势都有哪些?有大公司用吗?

  [5] Node.js给前端带来了什么

[NodeJS] 优缺点及适用场景讨论的更多相关文章

  1. NodeJS优缺点及适用场景讨论

    概述:NodeJS宣称其目标是“旨在提供一种简单的构建可伸缩网络程序的方法”,那么它的出现是为了解决什么问题呢,它有什么优缺点以及它适用于什么场景呢? 本文就个人使用经验对这些问题进行探讨. 一. N ...

  2. [转载]NodeJS优缺点及适用场景讨论

    http://www.xprogrammer.com/159.html 概述:NodeJS宣称其目标是“旨在提供一种简单的构建可伸缩网络程序的方法”,那么它的出现是为了解决什么问题呢,它有什么优缺点以 ...

  3. [NodeJS] 优缺点及适用场景

    概述: NodeJS宣称其目标是“旨在提供一种简单的构建可伸缩网络程序的方法”,那么它的出现是为了解决什么问题呢,它有什么优缺点以及它适用于什么场景呢? 本文就个人使用经验对这些问题进行探讨. 一. ...

  4. Ajax原理、优缺点及应用场景

    前言 Ajax的全称为Asynchronous JavaScript And Xml,是一种web客户端与服务器端异步通信的技术,如今,可以说是web开发人员必须掌握的的一项技能了.本文讲述了Ajax ...

  5. JS中lambda表达式的优缺点和使用场景(转)

    add by zhj: 最近在看ES6,看到了箭头函数,我个人感觉箭头函数适用于函数体中不用this的匿名函数,在箭头函数中使用this是一个坑 原文:http://ourjs.com/detail/ ...

  6. SSH框架阶段 ——SSH的优缺点,使用场景?

    Hibernate优点: (1) 对象/关系数据库映射(ORM)它使用时只需要操纵对象,使开发更对象化,抛弃了数据库中心的思想,完全的面向对象思想(2) 透明持久化(persistent)带有持久化状 ...

  7. c#中的var优缺点和适用场景

    var是c# 3.0新加的特性,叫做隐式类型局部变量,大家都知道c#其实是一种强类型的语言,为什么会引入匿名类型呢? 我猜测是因为linq的原因吧,因为感觉var在linq中被大量使用.下面说下var ...

  8. AngularJS优缺点、使用场景

    AngularJS 优缺点 优点: AngularJS模板功能强大丰富,自带了极其丰富的angular指令. AngularJS是完全可扩展的,与其他库的兼容效果很好,每一个功能可以修改或更换,以满足 ...

  9. Kafka leader副本选举与消息丢失场景讨论

    如果某个broker挂了,leader副本在该broker上的分区就要重新进行leader选举.来简要描述下leader选举的过程 1.4.1 KafkaController会监听ZooKeeper的 ...

随机推荐

  1. 场景9 深入RAC运行原理

    场景9 深入RAC运行原理 OPS(Oracle Parallel Server)通过磁盘的节点判定数据是否最新   —>   Data Guard   —>    RAC(Real Ap ...

  2. maven总结2

    依赖 maven版本:apache-maven-3.1.1    IDE: springsource   默认支持maven集成             若使用的是eclipse,则需要先安装m2ec ...

  3. iOS简单排序--字母排序、NSDictionary排序

    // 数组用系统方法compare做字母的简单排序 NSArray *oldArray = @[@"bac",@"bzd",@"azc",@ ...

  4. URAL1658. Sum of Digits(DP)

    链接 这题卡了挺久了 昨天试着用类似dfs的方法直接TLE在第二组 看了下题解,,发现s1,s2的范围是个幌子..100位最大的s1900 s28100 觉得s1s2太大不敢开二维.. 这样就简单了 ...

  5. SVN安装详解

    (一)安装服务器端1. 先安装VisualSVN-Server-2.6.0.msi 2.点击Next SVN服务端已经安装好了 选中Repositores --->选中“新建”---->点 ...

  6. python学习笔记--基础语法

    等待用户输入 #!/usr/bin/python raw_input("\n\nPress the enter key to exit.") 简单的判断 #!/usr/bin/py ...

  7. 计算机图形学学习方法和相关书籍,做游戏,GIS,虚拟现实,三维引擎的都能够看看.

    本书參照<<图形学扫盲>> 整理的,原文内容引子: http://www.cppblog.com/lai3d/archive/2008/12/30/70796.html 前言: ...

  8. 安装cocopods 更新ruby

    最近弄cocoapods出现如标题提示  So度娘一番.感谢作者.纯属学习没有商业用途 1.打开终端 终端输入  $ruby -v  查看ruby的版本 打印代码: ruby 2.0.0p648 (2 ...

  9. iOS音频播放、录音、视频播放、拍照、视频录制

    随着移动互联网的发展,如今的手机早已不是打电话.发短信那么简单了,播放音乐.视频.录音.拍照等都是很常用的功能.在iOS中对于多媒体的支持是非常强大的,无论是音视频播放.录制,还是对麦克风.摄像头的操 ...

  10. Golang 探索对Goroutine的控制方法

    前言 在golang中,只需要在函数调用前加上关键字go即可创建一个并发任务单元,而这个新建的任务会被放入队列中,等待调度器安排.相比系统的MB级别线程栈,goroutine的自定义栈只有2KB,这使 ...