|
1. 什么是RPC调用(远程过程调用)remote procedure call
半双工和全双工通信(实现难度和成本)
二进制协议
. 更小的数据包体积
. 更快的编解码速率
2. Buffer 编解码二进制数据包 (node 的二进制Buffer模块)
#buffer创建
// 具体用法参见文档
1. Buffer.from()
2. Buffer.alloc()
var buffer = Buffer.from('guiqing'); // <Buffer 67 75 69 71 69 6e 67>
var buffer = Buffer.from('股'); //<Buffer e8 82 a1>
对于默认的utf-8编码;英文占用一个字节,中文占用三个字节,为16进制
#buffer的写入
buffer.writeInt8
buffer.writeInt16BE
buffer.writeInt16LE
为啥writeInt8没有大小端,是因为一个字节为8位,刚好不需要两位,没有顺序之分 原生动态将多个string转为二进制的话,可能还需要获取写入的string对应的字节长度,以便管理下一次写入的offset; 可以通过Buffer.byteLength()来获取
(Protocol Buffers)用来编码二进制数据
protocol-buffers(npm包,用于方便实现编码二进制数据)
var obj = {
a: 1
}
var buffer = Buffer.from(JSON.stringify(obj))
console.log(buffer.toString())// 可以将json数据直接这样转为二进制数据
3. net 搭建多路复用的RPC通道
对应的https://github.com/geektime-geekbang/geek-nodejs/tree/master/chapter2/rpc
4. HTTP 服务性能测试
压力测试工具(ab、webbench)
通常用ab (https://www.jianshu.com/p/43d04d8baaf7)
找到性能瓶颈
. top (cpu、内存)
. iostat (硬盘)
5. Node.js性能分析工具
1⃣️ 自带的 profile 启动命令的时候带上--prof (eg. node --prof app.js)
这时会生成一个*.log 文件
可以通过命令: node --prof-process *.log > profile.txt (生成文件, 然后主要看这里,看主要的耗时)
2⃣️ Chrome devtool (eg. node --inspect-brk app.js)
chrome://inspect 进入
3⃣️ Clinic.js
4⃣️ 内存分析,可以点击Memory
这个就是你所占有的内存总量
6. 石头剪刀布游戏
1⃣️ process.argv
可以获取到用户输入的指令参数
2⃣️ module.exports 和 exports的区别
#lib.js
exports.a = 'hello world';
module.exports = function (){
console.log('exports被重新赋值了,上面定义的属性获取不到')
}
setTimeout(function(){
console.log(exports); // {a: 'hello world'}
}, 2000)
#index.js
const lib = require('./lib.js'); // lib 是引用类型
console.log(lib); //[Function]
lib.b = '我修改了对象'
3⃣️ process.stdin
7. callback 为啥采用error-first 模式
/**
* try catch只能抓到一个调用堆栈内,即一个事件循环里的错误
*/
// try {
interview(function (err, res) {
if (err) {
console.log('cry')
return;
}
console.log('smile')
})
// } catch (e) {
// console.log('cry')
// }
function interview(callback) {
setTimeout(() => {
if (Math.random() > 0.2) {
callback(null, 'success')
} else {
// throw new Error('fail');
callback(new Error('fail'))
}
}, 500)
}
8. promise 的状态是和最后一个then或者catch相关,或者是then中的其他promise状态相关
9. koa的优势
1⃣️. 不绑定中间间,更简洁
2⃣️. 使用async/await实现中间件,有暂停的能力(await next());在异步的情况下也符合洋葱模型
10. 使用es6模版和vm作为渲染引擎
// template.js const fs = require('fs');
const vm = require('vm');
const templateCache = {};
const templateContext = vm.createContext({
include: function (name, data) {
const template = templateCache[name] || createTemplate(name)
return template(data);
}
});
function createTemplate(templatePath) {
templateCache[templatePath] = vm.runInContext(
`(function (data) {
with (data) {
return \`${fs.readFileSync(templatePath, 'utf-8')}\`
}
})`,
templateContext
);
return templateCache[templatePath]
}
module.exports = createTemplate
// 使用 index.js
const template = require('./template');
const detailTemplate = template(__dirname + '/template/index.html');
app.use(async (ctx) => {
ctx.status = 200;
ctx.body = detailTemplate(result); })
渲染引擎模版要提供
1⃣️ include 子模版
2⃣️ 具备防止xss攻击,helper函数
11. graphQL: Facebook开发的实现API服务的库
比Restful的优势在于能够让前端有“自定义查询”数据的能力
koa-graphql(npm包)
12. 前后端同构
场景:服务端渲染,同时前端可以进行无刷新排序和分类等操作
难点:由于我们使用redux或者vuex; 所以数据方面比较难同构, react 可以用 next.js 进行服务端渲染
axios支持运行在浏览器和node.js
13. 子进程(child_process)和 工作线程(worker_threads)和集群(cluster)
# child_process.fork() 方法是 child_process.spawn(), 能和父进程进行通信
# index.js
const cp = require('child_process');
const child_process_demo = cp.fork(__dirname + '/child.js');
child_process_demo.send('hello');
#child.js
process.on('messaage', function(str) {
console.log(str);
process.send('world'); // process是全局变量, 且为当前子进程全局变量,所以只会接收到child_process_demo的消息
})
const cluster = require('cluster');
const os = require('os');
if (cluster.isMaster) {
for(let i = 0; i < os.cpus().length / 2; i++) {
cluster.fork();
};
} else {
require('./app.js');
};
//子进程启动的时候也会执行这个文件,并且isMaster是false
// cluster 启动多个子进程,但是能监听同个端口是进行了处理的。
// 处理成类似server.listen({fd: 7});这里不太清楚没细究
14. 反向代理和缓存服务 (nginx)
15. serverless (渐进式)
云函数(自行百度理解)
const fs = require('fs');
const mkdirp = require('mkdirp');
const webpack = require('webpack');
const mfs = new (require('memory-fs'));
module.exports = function (
businessName,
dataJSPath,
templatePath
) {
mkdirp.sync(__dirname + '/../business/' + businessName);
fs
.createReadStream(templatePath)
.pipe(fs.createWriteStream(__dirname + '/../business/' + businessName + '/template.tpl'));
const compileTask = webpack({
mode: 'development',
devtool: false,
target: 'node',
entry: dataJSPath,
module: {
rules: [
{ test: /.proto$/, use: 'text-loader' }
]
},
output: {
path: "/whatever",
filename: "data.js"
}
});
compileTask.outputFileSystem = mfs; // 这里可以借鉴,将webpack打包出来的文件先存在内存
compileTask.run(function(err) {
if (err) { return }
const content = mfs.readFileSync('/whatever/data.js')
fs.writeFileSync(__dirname + '/../business/' + businessName + '/data.js', content);
})
}
来源:https://www.cnblogs.com/luguiqing/p/11974334.html |