node的一个最大特性就是单线程,单线程带来的好处是不用像多线程编程那样去考虑状态的同步问题,也不用去担心出现死锁,也没有线程上下文所带来的性能的开销。
同时也带来了一些问题,比如无法充分利用的多核CPU,线程会阻塞的问题。
- process对象。
- child_process对象。
- cluster模块。
process 对象
process模块允许你获得或者修改当前node进程的设置,不想其他的模块,process是一个全局进程(node主进程),你可以直接通过process变量直接访问它。
在nodejs使用中,有一种情况比如:函数不存在、语法错误什么的,整个nodejs运行断掉,程序停止。
process模块提供了uncaughtException 事件用于处理这个问题。
process.on('uncaughtException', function (err) {
console.log('Caught exception: ' + err);
});
setTimeout(function () {
console.log('This will still run.');
}, 500);
// Intentionally cause an exception, but don't catch it.
nonexistentFunc();
console.log('This will not run.');
复制代码
process 属性
process.version://包含当前node实例的版本号;
process.platform://列举node运行的操作系统的环境,只会显示内核相关的信息,如:linux2, darwin,而不是“Redhat ES3” ,“Windows 7”,“OSX 10.7”等;
process.uptime()://包含当前进程运行的时长(秒);
process.getgid(), process.setgid()://获取或者设置group id;
process.getuid(), process.setuid()://获取或者设计user id;
process.pid://获取进程id;
process.title://设置进程名称;
process.execPath://当前node进程的执行路径,如:/usr/local/bin/node;
process.cwd()://当前工作目录;
process.memoryUsage()://node进程内存的使用情况,rss代表ram的使用情况,vsize代表总内存的使用大小,包括ram和swap;
process.heapTotal,process.heapUsed://分别代表v8引擎内存分配和正在使用的大小。
process.env 查看环境变量
复制代码
process.stdin.resume(); //这句话是为了不让控制台推出
process.on('SIGINT', function () { //SIGINT这个信号是系统默认信号,代表信号中断,就是ctrl+c
});
复制代码
自定义监听process事件on
process.on('SIGUSR1', function (d) { //这里监听 SIGUSR1 事件
console.log('Bye-'+d); //这里将输出Bye-Bye,然后推出进程
process.exit(0);
});
process.emit('SIGUSR1', 'Bye'); //利用emit触发SIGUSR1,然后传参数为Bye
复制代码
console.log = function (d) {
process.stdout.write(d + '\n');
};
复制代码
process.stdin.resume();
process.stdin.setEncoding('utf8');
process.stdin.on('data', function (chunk) {
process.stdout.write('data: ' + chunk);
});
process.stdin.on('end', function () {
process.stdout.write('end');
});
复制代码
child_process属性
- 可以实现创建多进程,以利用单机的多核计算资源。
- 可以在程序中直接创建子进程,并使用主进程和子进程之间实现通信,等到子进程运行结束以后,主进程再用回调函数读取子进程的运行结果。
- child_process.exec()
- child_process.spawn()
process.exec 执行系统命令
var cp = require('child_process');
cp.exec('ls -l', function(e, stdout, stderr) {
if(!e) {
console.log(stdout);
console.log(stderr);
}
});
复制代码
自定义 options
var options = {
encoding: 'utf8', // I/O流的编码格式;
timeout: 0, // 进程超时时间;
maxBuffer: 200 * 1024, // 当时间或者缓冲区超限时终止进程的信号;
killSignal: 'SIGTERM', // stdout或stderr可增长的最大值;
setsid: false, // 决定在进程中是否创建一个新的会话;
cwd: null, // 进程的初始工作目录,为null时表示使用node的当前工作目录;
env: null // 进程的环境变量。
};
var cp = require('child_process');
cp.exec('ls -l', options, function(e, stdout, stderr) {
if(!e) {
console.log(stdout);
console.log(stderr);
}
});
复制代码
process.spawn
var cp = require('child_process');
var cat = cp.spawn('cat');
cat.stdout.on('data', function(d) {
console.log(d.toString());
});
cat.on('exit', function() {
console.log('kthxbai');
});
cat.stdin.write('hello world!');
cat.stdin.end();
***child_process.spawn( )比child_process.exec( )更加强大和灵活
复制代码
cluster
cluster模块可以轻松实现运行在同一机器不同进程上的TCP或HTTP服务器集群。它们仍使用相同的底层套接字,从而在相同的IP地址和端口组合上处理请求。
fork: //当新的工作进程已经被派生时发出。callback函数接收worker对象作为唯一的参数。function(Worker)
online: //当新的进程发回一消息,表明它已经启动时发出。callback同上。
listening: //当工作进程调用listen()开始监听端口时发出。callback:fucntion(Worker,address)
disconnect: //当IPC通道被切断时发出。如服务器调用worker.disconnect()的时候。callback:function(Worker)
exit: //在Worker对象已断开时发出。callback:function(Worker,code,signal)
setup: //在setupMaster()被首次调用时发出。
属性和方法:
settings: //包含exec(工作进程的javascript文件)、args(传递的参数数组)、silent(断开工作进程的IPC机制)属性值,用于建立集群
isMaster: //判断当前进程是否是主进程
isWorker: //判断当前进程是否是工作进程
setupMaster([settings]): //启动主进程
disconnect([callback]): //断开工作进程的IPC机制,并关闭句柄,当断开连接完成时回调
worker: //引用在工作进程的当前Worker对象
workers://包含Worker对象,可以通过标识从主进程引用它们。cluster.workers[workerId]
复制代码
var cluster = require('cluster');
var http = require('http');
if (cluster.isMaster) {
cluster.on('fork', function(worker) {
console.log("Worker " + worker.id + " created");
});
cluster.on('listening', function(worker, address) {
console.log("Worker " + worker.id +" is listening on " +
address.address + ":" + address.port);
});
cluster.on('exit', function(worker, code, signal) {
console.log("Worker " + worker.id +" Exited");
});
cluster.setupMaster({exec:'cluster_worker.js'}); //图例二js demo
var numCPUs = require('os').cpus().length;
for (var i = 0; i < numCPUs; i++) {
if (i>=4) break;
cluster.fork();
}
Object.keys(cluster.workers).forEach(function(id) {
cluster.workers[id].on('message', function(message){
console.log(message);
});
});
}
复制代码
const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
console.log(`主进程 ${process.pid} 正在运行`);
// 衍生工作进程。
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', (worker, code, signal) => {
console.log(`工作进程 ${worker.process.pid} 已退出`);
});
} else {
// 工作进程可以共享任何 TCP 连接。
// 在本例子中,共享的是一个 HTTP 服务器。
http.createServer((req, res) => {
res.writeHead(200);
res.end('hellow world \n');
}).listen(8000);
console.log(`工作进程 ${process.pid} 已启动`);
}
复制代码
var cluster = require('cluster');
var http = require('http');
if (cluster.isWorker) {
http.Server(function(req, res) {
res.writeHead(200);
res.end("Process " + process.pid + " says hello");
process.send("Process " + process.pid + " handled request");
}).listen(8080, function(){
console.log("Child Server Running on Process: " + process.pid);
});
}
复制代码