var net = require('net')var server = net.createServer(function (socket) { socket.on('data', function (data) { socket.write('a') }) socket.on('end', function () { console.log('disconnected.') }) socket.write('welcome')})server.listen(8124, function () { console.log('server bound')})
o→ 基本服务2
var server = net.createServer()server.on('connection', function (socket) {})server.listen(8124)
var fork = require('child_process').forkvar cpus = require('os').cpus()for (var i = 0; i < cpus.length; i++){ fork('./worker.js')}
o→ worker.js
var http = require('http')http.createServer(function(req, res){...}).listen(Math.round((1+Math.random()) * 1000), '127.0.0.1')
o→ spawn
var spawn = require('child_process').spawnfree = spawn('free', ['-m'])free.stdout.on('data', function (data) {})free.stderr.on('data', function (data) {})free.on('exit', function (code, signal) {})
o→ fork
需要至少30ms, 10M启动一个v8实例
var fork = require('child_process').forkvar cpus = require('os').cpus()for (var i = 0; i < cpus.length; i++) { fork('./worker.js')}
o→ 通信
只有子进程是node进程时才可以通信
var cp = require('child_process')var n = cp.fork(__dirname + '/sub.js')n.on('message', function (m) { console.log('PARENT got message: ', m)})n.send({a: 1})process.on('message', function (m) { console.log('CHILD got message:', m)})process.send({b: 2})
o→ 句柄通信
节省了代理建立socket浪费的文件描述符
var child = require('child_process').fork('child.js')var server = require('net').createServer()server.on('connection', function (socket) { socket.end('handled by parent \n')})server.listen(1337, function () { child.send('server', server)})// child.jsprocess.on('message', function (m, server) { if (m === 'server') { server.on('connection', function (socket) { socket.end('handled by child \n') }) }})
o→ 句柄负载http
对描述符是抢占式的
var cp = require('child_process')var child1 = cp.fork('child.js')var child2 = cp.fork('child.js')var server = require('net').createServer()server.listen(1337, function () { child1.send('server', server) child2.send('server', server) server.close()})// child.jsvar http = require('http')var server = http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}) res.end('handled by child, pid is ' + process.pid + '\n')})process.on('message', function (m, tcp) { if (m === 'server') { tcp.on('connection', function (socket) { server.emit('connection', socket) }) }})
cluster
介绍
child_process和net模块的组合
cluster启动时,内部启动tcp服务器
fork()时,将tcp服务器socket文件描述符发给worker, 实现共享端口
isWorker
判断process.env是否值为NODE_UNIQUE_ID
isMaster
判断cluster.isWorker
事件
fork # fork时
online # 工作进程创建好后
listening # 工作进程调listen()后
disconnect # 主进程和工作进程IPC通道断开后
exit # 所有工作进程退出后
setup # cluster.setupMaster()执行后
o→ cpu核数worker
var cluster = require('cluster')cluster.setupMaster({ exec: "worker.js"})var cpus = require('os').cpus()for (var i = 0; i < cpus.length; i++) { cluster.fork()}
var domain = require('domain');function async_error(){ setTimeout(function(){ var r = Math.random() * 10; console.log('random num is ' + r); if(r > 5) throw new Error('Error: random num ' + r + ' > 5'); }, 10);}var d = domain.create();d.on('error', function(err){ console.log(err);});setInterval(function(){ d.run(async_err);}, 1000);
未绑定不捕获
代码
var domain = require('domain');var EventEmitter = require('events').EventEmitter;var e = new EventEmitter();var timer = setTimeout(function(){ e.emit('data');}, 10);function next(){ e.once('data', function(){ throw new Error('Receive data error!'); });}var d = domain.create();d.on('error', function(err){ console.log(err);});d.run(next);