nodejs随记01
2015-07-31 15:24
441 查看
EventEmitter
var stream = require('stream'); var Readable = stream.Readable; //写入类(http-req就是),初始化时会自动调用_read接口; var util = require('util'); var Reader = function () { Readable.call(this); //继承其他构造器; this.counter = 0; } util.inherits(Reader, Readable); Reader.prototype._read = function () { if(++this.counter > 10) return this.push(null); //传入null即停止; return this.push(this.counter.toString()); } var reader = new Reader(); reader.setEncoding('utf8'); reader.on('data', function(chunk) { console.log(chunk); }) reader.on('end', function(chunk){ console.log('--finished--'); })
http.createServer
http.Server的实例,后者扩展自
EventEmitter
import http from 'http'; const server = new http.Server(); server.on('connection', socket=> { console.log('Client arrived: ' + new Date()); /* socket.on("end", function() { console.log("Client left: " + new Date()); });*/ socket.write('Hello World!', 'utf8'); socket.end(); }); //客户端数据处理 //测试: curl http://localhost:3000 -d "Here is some data" server.on('request', (req, socket)=> { req.setEncoding('utf8'); req.on('readable', ()=> { console.log(req.read()) //读取 }); }); /* 可以把end延迟执行 server.setTimeout(2000, socket=> { socket.write('Too Slow!', 'utf8'); socket.end(); }); */ server.listen(3000);
http.request
读取流,很容易piped到写入流import http from 'http'; const options = { host: 'www.google.com', method: 'GET', path: '/' }; const callback = function (res) { res.setEncoding('utf8'); res.on('readable', ()=> { console.log(res.read()); //读取 }); /* res.on('end', ()=> { console.log('client end'); }); */ }; const client = http.request(options, callback); client.end();
get方式直接使用
http.get;
构建代理和隧道
import http from 'http'; const proxy = new http.Server(); proxy.on('request', (req, socket)=> { const options = { host: 'www.google.com', method: 'GET', path: '/' }; http.request(options, res=> { res.pipe(socket); //不再手动监听,直接push到写入流; }).end(); }); proxy.listen(3000);
子进程
child_process: 使用的进程方法包括
spawn, fork, exec, execFile.
spawn(command, [arguments], [options])
//option cwd: 子进程的当前工作目录 env: 环境变量键值对 stdio: 子进程 stdio 配置 customFds: 作为子进程 stdio 使用的文件标示符 detached: 进程组的主控制 uid: 用户进程的ID. gid: 进程组的ID.
import {spawn} from 'child_process'; const ls = spawn('ls', ['-1h']); ls.stdout.on('data', data=> { console.log('stdout: ' + data); }); ls.stderr.on('data', ()=> { console.log('stderr: ' + data); }); ls.on('close', code=> { console.log('child process exited with code ' + code); });
fork(modulePath, [arguments], [options])//仅仅用于执行
node
//parent.js import {fork} from 'child_process'; const cp = fork('./child.js'); cp.on('message', msgobj=> { console.log('Parent got message: ', msgobj.text); }); cp.send({ text: 'Hello World!' }); //child,js process.on('message', function (msgobj) { console.log('Child got message:', msgobj.text); process.send({ text: msgobj.text + ' too' }); });
exec(command, [options], callback)//回调
execFile(file, [args], [options], [callback])//直接执行特定的程序,参数作为数组传入,不会被bash解释,因此具有较高的安全性。
注意:如果命令参数是由用户来输入的,对于exec函数来说是有安全性风险的,因为Shell会运行多行命令,比如
ls -l .;pwd,如逗号分隔,之后的命令也会被系统运行。但使用exeFile命令时,命令和参数分来,防止了参数注入的安全风险。
对应的三个同步方法
spawnSync,execFileSync,execSync;
构建集群
//parent import {fork} from 'child_process'; import net from 'net'; import {cpus} from 'os'; let children = []; cpus().forEach((f, idx)=> { children.push(fork('./child.js', [idx])); }); net.createServer(socket=> { const rand = Math.floor(Math.random() * children.length); children[rand].send(null, socket); }).listen(8080) //child var id = process.argv[2]; process.on('message', function (n, socket) { socket.write('child' + id + ' was your server today. \r\n'); socket.end(); });
cluster
基于child_process, 简化多进程并行化开,构建负载均衡的集群;
//简化上面的集群 import cluster from 'cluster'; import http from 'http'; import {cpus} from 'os'; const numCPUS = cpus().length; if(cluster.isMaster) { //总控制节点 for (let i = 0; i < numCPUS; i++) { cluster.fork(); //让所有cpu运行子进程 } } if(cluster.isWorker) { //运行节点 http.createServer((req, res)=> { res.writeHead(200); res.end(`Hello from ${cluster.worker.id}`) }).listen(8080); }
可以考虑其他多次封装的包cluster2
cluster的负载均衡的策略是随机分配的;
利用进程中的消息通知来共享数据;
防止上下文切换: 一般对于
n核
cpu会开
n-1个进程;如果有多个应用还应该减少每个开的进程数;
注意:使用
process.send时,在
master进程中不存在该方法;
master->worker:
worker.send;
worker->master:
process.send;
//判断 var cluster = require('cluster'); if(cluster.isMaster){ var worker = cluster.fork() worker.on('message', function(msg){ console.log(msg); }); }else{ process.send({as: 'message’}); }
帮助工具util
util.inherits(constructor, superConstructor): 原型继承;
util.inspect(object[, {showHidden, depth}]): 将任意对象转换为字符串,用于调试和错误输出;
util.isArray(object)
util.isRegExp(object)
util.isError(object)
util.isDate(object)
util.isBuffer(object)
util.deprecate(function, string)//标明该方法不要再使用
相关文章推荐
- nodejs安装express
- nodejs windows环境安装
- Delete Node in a Linked List Java LeetCode
- LeetCode_237 Delete Node in a Linked List
- Cannot delete .... . Name node is in safe mode
- hadoop启动后jps查看总是不显示namenode进程,然后重新格式化hdfs
- node-odata: ASP.NET WEB API OData的替代品
- VFS,super_block,inode,dentry—结构体图解
- [CareerCup] 4.2 Route between Two Nodes in Directed Graph 有向图中两点的路径
- java学习脚印:xml中空白文本结点(whitespace TextNode)处理及验证方法
- leetcode之路019 Remove Nth Node From End of List
- NodeJS + PhantomJS 抓取页面信息以及截图
- 利用nodejs+phantomjs+casperjs采集淘宝商品的价格
- Algorithms—237.Delete Node in a Linked List
- datanode无法启动
- 116.Populating Next Right Pointers in Each Node(二叉完全树的next结点)
- nodemailer的使用
- Node.js学习系列总索引
- Nodejs加密php解密
- 使用pm2 管理你的node项目