node.js开发实战

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);
    })
}

 

 
posted @ 2019-12-03 00:53  潮哥  阅读(1175)  评论(0编辑  收藏  举报