Node.js Notes
- Node.js是一个基于Chrome V8引擎的Javascript运行环境
- Node.js使用了一个事件驱动、非阻塞式I/O的模型,使其轻量又高效
Node.js适合的服务
- Web服务中间层(搜索引擎优化 + 首屏速度优化 = 服务端渲染)
- 构建工作流 - Gulp、Webpack
- 开发工具 - Visual Studio Code
- 游戏 - wayward(可扩展性 - 大型应用需要给使用者自定义模块的能力)
- 客户端应用 - twitch.tv(用Node.js客户端技术(Electron)实现,最大限度复用现有工程)
CommonJS模块规范
- commonJS模块被引用后,如果没有导出,默认是个空对象 {}
- 导出的引用与模块内部的exports引入是同一个,因此外部也可以修改模块的引用
- exports = module.exports
Node.js内置模块
利用EventEmitter实现观察者模式
事件循环(Event Loop)
libuv这个库提供两个最重要的东西是事件循环和线程池,两者共同构建了异步非阻塞I/O模型,而事件驱动只是在整个非阻塞I/O模型当中线程池通知事件循环它已经完成I/O操作的这样一种机制而已
- 每一个事件循环都是一个全新的调用栈
- 微任务
- 宏任务
Micro-Task and Macro-Task
Promise
Async/Await
- Async function 是Promise的语法糖封装
- 异步编程的终极方案 - 以同步的方式写异步
-
- await 关键字可以 “暂停” async function 的执行
- await 关键字可以以同步的写法获取Promise的执行结果
- try-catch 可以获取await 所得到的错误
Express
核心功能
- 路由
-
- request/response
-
- request: pathname, query等
- response: send(), json(), jsonp()等
- 中间件 - 洋葱模型
Express洋葱模型不完善,有设计缺陷,所以作者新写了Koa
Koa
核心功能
- 中间件 - 洋葱模型
- Context - 将request和response整合进了context,使其更符合语义
- 中间件支持异步函数,可以使用 await next(); 阻塞住,不会出现express的异步调用缺陷
- Express vs Koa
-
- Express 门槛更低,koa更强大优雅
- Express 封装更多东西,开发更快速,koa可定制型更高
RPC调用
- Remote Procedure Call (远程过程调用)
- 和Ajax的相同点
-
- 都是两个计算机之间的网络通信
- 需要双方约定一个数据格式
- 和Ajax的不同点
-
- 不一定使用DNS作为寻址服务
- 应用层协议一般不使用HTTP
- 基于TCP或UDP协议
- 寻址/负载均衡
-
- Ajax: 使用DNS进行寻址
- RPC: 使用特有服务进行寻址
- TCP通信方式
-
- 单工通信
- 半双工通信 (轮番单工通信)
- 全双工通信
- 二进制协议
-
- 更小的数据包体积
- 更快的编解码速率
Buffer编解码二进制数据包
- Protocol buffer协议 Google提供
Node.js net模块
- 全双工的通信通道搭建
-
- 关键在于应用层协议需要有标记包号的字段
- 处理以下情况,需要有标记包长的字段
-
- 粘包
- 不完整包
- 错误处理
API服务 - Restful
- 简单易懂
- 可以快速搭建
- 在数据的聚合方面有很大劣势
API服务 - GraphQL
- 专注数据聚合,前端要什么就返回什么
压测工具
- Ab (apache bench)
- webbench
- 找到性能瓶颈所在地
-
- top
- iostat
Node.js性能分析工具
- Chrome devtools
Node.js Cluster
动静分离
- 静态内容
-
- 基本不会变动,也不会因为请求参数不同而变化
- -> CDN分发,HTTP缓存等
- 动态内容
-
- 各种因为请求参数不同而变动,且变种的数量几乎不可枚举
- -> 用大量的源站机器承载,结合反向代理进行负载均衡
设计模式
学习设计模式最主要的不是学习模式,而是理解设计模式的原则,理解要怎么样才能做出架构优秀的程序
- 观察者模式
-
- EventEmitter
- DOM addEventListener
- 外观模式
-
- jQuery
- 设计模式六大法则
-
- 单一职责原则
-
- 每个模块/类只做一件事情
- 微服务
- 方便重用
- 解耦
- 里氏替换原则
- 依赖倒转原则
- 接口隔离
- 最小知晓原则
- 开闭原则
-
- 对扩展开放,对修改关闭
- Webpack loader设计
- 每一个模块都有明确的功能
- 新增功能只需要新增模块,不需要修改原有部分
Serverless
- 云函数
-
- 不用再因为运维、架构的事情操心
-
- 缩短业务上线周期
- 减少出错的概率
- 业务开发的上手难度更低
- 渐进式
- less
- 把能在多个业务复用的东西下沉,屏蔽细节