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的负载均衡的策略是随机分配的;
  • 利用进程中的消息通知来共享数据;
  • 防止上下文切换: 一般对于ncpu会开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随记01的更多相关文章

  1. NodeJS 学习总结 01 安装配置

    1 安装NodeJS 具体参考已发布的文章Ubuntu学习总结-07 Nodejs和npm的安装 2 使用淘宝 NPM 镜像 国内直接使用 npm 的官方镜像是非常慢的,这里推荐使用淘宝 NPM 镜像 ...

  2. 【NodeJS 学习笔记01】不学就老了

    前言 再不学nodeJs,我们就老了......在HTML5大浪袭来的时候,很多先辈就开始了NodeJs之旅,而那时我还在做服务器端的程序后来转成前端,和梯队的距离已经很大了,因为我会服务器端语言,还 ...

  3. Angular4+NodeJs+MySQL 入门-01

    有一定的后台开发经验ES6语法.后台没有用框架来,纯自己写.会sql语句 安装NodeJS的安装 从网上下载 https://nodejs.org/en/ 选择自己,我用的是最新版本 Angular ...

  4. 【Nodejs】记一次图像识别的冒险

    笔者的团队最近接到了一个有关图像识别的需求,本来应该由后端团队提供能力,native提供容器,前端团队仅负责一些“外围的形式工作”,不过由于各种各样的原因,最后的结果变成了前端团队在原有工作基础上,承 ...

  5. nodejs学习总结01

    主流渲染引擎介绍1.渲染引擎又叫 排版引擎 或 浏览器内核 .(双内核:执行html和css的)2,主流的渲染引擎有**Chrome浏览器**:Blink引壁(WebKit的一个分支)**Safari ...

  6. nodejs随记04

    aes加密 资料 简介; 例子; process 改变工作目录: process.chdir(path); 路径计算 例子 获取调用执行所在文件地址 function getCaller() { tr ...

  7. css随记01编辑技巧,背景与边框

    代码优化 一个按钮的例子,使其值同比例变化; button{ color: white; background: #58a linear-gradient(#77a0bb, #58a); paddin ...

  8. nodejs随记03

    文件操作 文件系统的操作 fs.readFile(filename, [options], callback) fs.writeFile(filename, data, [options], call ...

  9. nodejs随记02

    Basic认证 检查报文头中Authorization字段,由认证方式和加密值构成: basic认证中,加密值为username:password,然后进行Base64编码构成; 获取username ...

随机推荐

  1. 【leetcode】Binary Tree Zigzag Level Order Traversal (middle)

    Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to ...

  2. Linux面试题汇总答案

    转自:小女生的Linux技术~~~Linux面试题汇总答案~~ 一.填空题:1. 在Linux系统中,以 文件 方式访问设备 .2. Linux内核引导时,从文件 /etc/fstab 中读取要加载的 ...

  3. iOS进阶面试题----Block部分

    1 什么是block 对于闭包 (block),有很多定义,其中闭包就是能够读取其它函数内部变量的函数,这个定义即接近本质又较好理解.对于刚接触Block的同学,会觉得有些绕, 因为我们习惯写这样的程 ...

  4. 解决ERROR 2003 (HY000): Can't connect to MySQL server on

    方案一: .打开cmd; .输入命令:net stop +MySQL的服务名,停止MySQL服务,如果未启动MySQL服务则可跳过该步骤: .输入命令:mysqld --remove卸载MySQL服务 ...

  5. 矿场搭建(codevs 1996)

    题目描述 Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使 ...

  6. python基础——访问限制

    python基础——访问限制 在Class内部,可以有属性和方法,而外部代码可以通过直接调用实例变量的方法来操作数据,这样,就隐藏了内部的复杂逻辑. 但是,从前面Student类的定义来看,外部代码还 ...

  7. [转]DB2时间类函数

    Src URL:http://www.cnblogs.com/wanghonghu/archive/2012/05/25/2518604.html 1.db2可以通过SYSIBM.SYSDUMMY1. ...

  8. Struts2拦截器之ExceptionMappingInterceptor(异常映射拦截器)

    一.异常拦截器是什么? 异常拦截器的作用是提供一个机会,可以设置在action执行过程中发生异常的时候映射到一个结果字符串而不是直接中断. 将异常整合到业务逻辑中,比如在分层系统的调用中可以从底层抛出 ...

  9. 用spring+hibernate+struts 项目记录以及常用的用法进等

    一.hibernate1. -----BaseDao------ // 容器注入 private SessionFactory sessionFactory; public void setSessi ...

  10. const和#define 区别

    1: 编译器处理不同     define宏是在预处理阶段展开,const常量是编译运行阶段使用. 2:类型和安全检查不同 const常量有数据类型,而宏常量没有数据类型,仅仅是展开.编译器可以对前者 ...