Node.js 简介
Node 是一个让 JavaScript 运行在服务端的开发平台,它让 JavaScript 成为与PHP、Python、Perl、Ruby 等服务端语言平起平坐的脚本语言。发布于2009年5月,由Ryan Dahl开发,实质是对Chrome V8引擎进行了封装。
Node对一些特殊用例进行优化,提供替代的API,使得V8在非浏览器环境下运行得更好。V8引擎执行Javascript的速度非常快,性能非常好。Node是一个基于Chrome JavaScript运行时建立的平台, 用于方便地搭建响应速度快、易于扩展的网络应用。Node 使用事件驱动, 非阻塞I/O 模型而得以轻量和高效,非常适合在分布式设备上运行数据密集型的实时应用。
特点一、事件驱动
事件驱动,是指在持续事务管理过程中,进行决策的一种策略,即跟随当前时间点上出现的事件,调动可用资源,执行相关任务,使不断出现的问题得以解决,防止事务堆积。 Nodejs设计思想中以事件驱动为核心,事件驱动在于异步回调,他提供的大多数api都是基于事件和异步的风格。而事件驱动的优势在于充分利用系统资源,执行代码无须阻塞等待某种操作完成,有限的资源用于其他任务。事件驱动机制是通过内部单线程高效率地维护事件循环队列来实现的,没有多线程的资源占用和上下文的切换。
event.on事件监听。
event.emit发送事件。
下面这段代码,event.on就是在监听some_event的发生,一旦发生后,调用回调函数,打印(some_event occured)
var EventEmitter = require('events').EventEmitter;
var event = new EventEmitter();
event.on('some_event',function() {
console.log('some_eventoccured');
});
setTimeout(function(){
event.emit('some_event')//发送事件
},2000)
特点二、异步、非阻塞I/O
Nodejs提供的很多模块中都是异步执行的。比如,文件操作的函数。
一个异步I/O的大致流程:
- 发起I/O调用:
① 用户通过js代码调用nodejs的核心模块,将回调函数和参数传入核心模块。
② 将回调函数和参数封装成请求对象。 - 执行回调:
① 操作完成将结果储存到请求对象的result属性上,并发出完成通知。
② 循环事件,如果有未完成的,就在进入对象请求I/O观察者队列,之后当做事件处理。
异步I/O机制,因此在执行访问数据库的代码之后,将立即去执行其后面的代码,把数据库返回结果的处理代码放在回调函数中,每个调用之间无需等待之前的I/O调用结束,提高了程序的执行效率。
var fs = require('fs');
fs.readFile(‘/path’, function(err,file) {
console.log('读取文件完成')
});
console.log('发起读取文件')
这里的“发起读取文件”是在“读取文件完成”之前输出的,同样,“读取文件完成”的执行也取决于读取文件的异步调用何时结束。
特点三、单线程
在传统web 服务模型中,大多都使用多线程来解决并发的问题,因为I/O 是阻塞的,单线程就意味着用户要等待,显然这是不合理的,所以创建多个线程来响应用户的请求。在Java、PHP或者.net等服务器端语言中,会为每一个客户端连接创建一个新的线程。而每个线程需要耗费大约2MB内存。也就是说,理论上,一个8GB内存的服务器可以同时连接的最大用户数为4000个左右。要让Web应用程序支持更多的用户,就需要增加服务器的数量,而Web应用程序的硬件成本当然就上升了。
Node.js的单线程指的是主线程是“单线程”,由主线程去按照编码顺序一步步执行程序代码,主线程是不需要等待结果返回的,只要发出指令并给一个回调函数马上就可以去忙其他事情了,Node.js不为每个客户连接创建一个新的线程,而仅仅使用一个线程。当有用户连接了,就触发一个内部事件,通过非阻塞I/O、事件驱动机制,让Node.js程序宏观上也是并行的。使用Node.js,一个8GB内存的服务器,可以同时处理超过4万用户的连接。另外,单线程的带来的好处,还有操作系统完全不再有线程创建、销毁的时间开销。坏处,就是一个用户造成了线程的崩溃,整个服务都崩溃了,其他人也崩溃了。
NodeJS的优缺点
优点:
- 高并发(最重要的优点)
- 适合I/O密集型应用
缺点:
不适合CPU密集型应用;CPU密集型应用给Node带来的挑战主要是:由于JavaScript单线程的原因,如果有长时间运行的计算(比如大循环),将会导致CPU时间片不能释放,使得后续I/O无法发起;
解决方案:分解大型运算任务为多个小任务,使得运算能够适时释放,不阻塞I/O调用的发起;只支持单核CPU,不能充分利用CPU
原因 : 因为nodejs是单线程的,进行密集型的运算会导致主线程挂起可靠性低,一旦代码某个环节崩溃,整个系统都崩溃
原因:单进程,单线程
解决方案:
(1)Nnigx反向代理,负载均衡,开多个进程,绑定多个端口;
(2)开多个进程监听同一个端口,使用cluster模块;开源组件库质量参差不齐,更新快,向下不兼容
-
Debug不方便,错误没有stack trace,不方便追踪