[Node]基础知识

1. Node特性

Node的功能强大,它将JavaScript扩展到了更多领域,特别是后端网站服务器开发。它是对高性能V8引擎的封装,通过提供一系列优化的API类库,使V8在浏览器之外依然能高效运行。

Node的一大特性是对高性能的追求。首先,V8采用了编译领域的一些最新技术,使代码运行效率能够接近C等底层语言。其次,Node利用了JavaScript的事件驱动特性来构建高度可扩展的服务器程序,它采用事件循环架构,让开发高效的服务器程序变得简单和安全。

Node提供了一系列非阻塞函数库来支持事件循环特性。比如把文件系统或数据库操作封装成事件驱动形式的函数接口,当对文件系统发起请求时,程序不需要闲置等待硬盘把文件读取出来。

Node的强大特性还包括能在服务器端运行JavaScript。除了可以用Node现有的库来构建应用外,也可以轻松为其扩展新的库。正因为Node容易扩展,在Node项目对外发布后,其社区便迅速涌现出大量扩展库。


2. 编写程序

设计Node.js的一个主要目的是提供高度可扩展的服务器环境,除了用V8引擎来解析JavaScript外,还提供了高度优化的应用库,用来提高服务器效率。比如HTTP模块是专为快速非阻塞式HTTP服务器而用C重新编写的,例如:

var http = require('http');
http.createServer(function(req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(9000, '127.0.0.1');
console.log('Server running at http://127.0.0.1:9000');

这个示例首先通过require方法把HTTP库包含到程序中,接着调用HTTP模块的一个工厂方法来创建新的HTTP服务器,并监听在9000端口。

当调用createServer的时候,传了一个匿名函数作为参数,此函数绑定在新创建服务器的事件监听器上进行request事件处理。每当一个新的访问请求到达Web服务器,它都将调用指定的函数方法来处理,我们称这类方法为回调。

例子中的回调函数有两个参数,一个是请求的对象,一个是响应的对象。首先调用res.writeHead方法来设置HTTP响应头,接着可以写入HTTP正文及调用res.end方法关闭连接,但是因为调用end方法的同时还传入了一个字符串,所以end方法将在把此内容发送给客户端后才关闭。

例子的最后一行调用了console.log方法,它将在标准输出stdout上打印信息。


3. 事件循环

Node的一个核心功能就是事件循环,它采用的方式是,所有的I/O事件都应该是非阻塞的。这意味着需要让程序暂停操作的HTTP请求、数据库查询、文件读写,以及其他事情在数据返回之前并不暂停执行。这些事件都将独立运行,而后在数据准备好以后触发一个事件。也就是说,用Node.js编程会用到很多回调函数。

比如Web服务器被请求要从数据库中读取一些数据,然后返回给用户。首先,用户的请求多是要Web服务器返回一个网页,处理这个初始请求的回调函数A会先从请求的对象中确定要从数据库读取的内容,然后向数据库发起请求,并传入一个回调函数B供请求完成时使用。处理完请求后,回调函数A结束并返回,当数据库找到相应内容后,再触发相应事件,事件循环队列则调用回调函数B,让它把数据发送给用户。


4. 差错处理

JavaScript包含了try/catch功能,但这个方法只有当错误发生在内联位置时才有用。比如使用Node的非阻塞I/O时,给函数传递了一个回调函数,当回调函数被事件触发调用时,是不在try/catch代码块中的。所以我们需要为异步运行情景提供差错处理的办法,而error事件让我们能够处理所有使用的模块中可能出现的问题,例如:

var http = require('http');
var opts = {
  host: 'test.net',
  port: 80,
  path: '/'
};
var req = http.get(opts, function(res) {
  console.log('This will nerver get called');
});
req.on('error', function(e)) {
  console.log('Got that pesky error trapped');
});


5. 使用多处理器

Node提供了一个cluster模块,可以把任务分配给子进程,每个子进程能够与其他子进程共享socket连接。当使用cluster把工作共享到一组复制的Node程序时,主进程不会参与到每个具体的事务中,当子进程与I/O操作交互时,它们是直接进行操作的,不需要通过主进程。通过cluster API,可以把工作分布在服务器所有可用的处理器上,例如:

var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
  for (var i = 0; i < numCPUs; i++) {
    cluster.fork();
  }
  cluster.on('death', function(worker) {
    console.log('worker ' + worker.pid + ' died');
  });
} else {
  http.Server(function(req,res) {
    res.writeHead(200);
    res.end("Hello World\n");
  }).listen(9000);
}

cluster工作的原理是每一个Node进程要么是主进程,要么成为工作进程。当一个主进程调用cluster.fork()方法时,它会创建与主进程一样的子进程。在主进程中,cluster.isMaster.isMaster返回true,而在子进程中,cluster.isWorker返回true。在使用cluster的地方使用listen()监听一个socket的时候,多个进程可以同时监听同一个socket。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章