认识
总起
- 前后端语言不同而分散梳离的知识点,奇迹般的因为Node重新连接起来
- 为什么是nodejs,与java等区别
- 为什么nodejs 高并发,可伸缩性
- 为什么不适合cpu密集型
- 进程、线程、协程、系统内核态、用户态、上下文切换
- 阻塞IO/非阻塞IO
- 高性能web服务器/ nginx 事件驱动
- web workers / child_process
- 与公司其他语言如何异构共存
模块机制
- commonjs 规范 服务端 (AMD、CMD)
- browerify
- 加载顺序
- 模块加载实现
- 用户模块、核心模块(js/c++)、c++扩展模块
- 性能
- npm cnpm dnpm区别
- c++扩展模块
- 为什么要编写c++扩展模块
- 复用能力
- dubble 位运算
- 提高性能,性能一定更高么?
- 扩展模块如何被js调用的、process.dlopen 、动态链接库、静态链接库
- 如何编写c++扩展模块
- V8 ApI
- NAN
- N-API
- GYP / makefile
- 为什么要编写c++扩展模块
异步I/O
- 为什么异步I/O、为什么是异步函数
- 多线程、创建、切换开销;死锁、状态同步
- 异步IO实现 (系统层)
- 轮询 (epool 自动挂起,进程or线程)
- IOCP (Input/Output Completion Port,IOCP)
- DMA(Direct Memory Access)直接内存存取, 芯片. 为什么可以并行IO,一个中断异常
- Node 异步IO/ 应用程序层 实现
- linux 自定义IO线程
- windows 系统级IO线程
- IO线程池
- 事件循环、请求对象,IO线程池
- 非IO类异步API
- 定时器红黑树
- timemout/interval/ nexttick / immediate先后顺序
- 事件循环每次tick 做的 6 个阶段cb先后顺序
- process.nextTick() 不在 Event Loop 的任何阶段执行,而是在各个阶段切换的中间执行,即从一个阶段切换到下个阶段前执行。
- macrotask 宏任务 和 microtask微任务 的概念
- Idel观察者,io观察者,check观察者。数组,红黑树,链表
异步编程
- 函数可以入参返参一等公民,c++指针实现,故有回调函
- 高阶函数
- 柯里化函数
- 异步编程 提交阶段、处理阶段
- 异步编程问题
- 异步不能try catch ,回调函数 标准化,第一个参数异常
- 函数嵌套
- 没有sleep
- 多线程利用
- 同步转异步
- 解决方案 事件发布/订阅模式 Promise/Deferred模式 流程控制库 async await 协程 性能对比
- 并发控制 为什么要并发控制 并发雪崩 加锁状态控制 只有一份SQL 文件读写不能太多,文件标识符用光 每个同步代码块要尽量小于10ms,否则 没有了多线程处理,而且丢掉了异步io的能力。当前处理cpu, 导致io来不及接收,导致后面cpu又在等活干
内存控制
- 为什么要有垃圾回收
- 为什么node要有堆内存限制
- 为什么分代垃圾回收
- RSS、堆、对外内存 关系
- 堆中的、新生代、老生代、大对象、代码区
- gc日志
- 有哪些内存泄露的场景
- 缓存
- 全局变量
- 闭包
- 生产者消费者
- 异常处理
- 有哪些定位内存泄露的方法
- 大对象内存操作方法
Buffer
- 字符 与字节区别
- 为什么会有需要buffer
- buffer 内存分配过程,堆外空间,slab 8kb 大内存, 全部回收才回收
- 字符与字节转换,编码
- 字符串转化到buffer 两个服务qps 差1倍,静态内容事先buffe
- 文件内容buffer
- unix 一切皆文件 IO
- 流stream/readable/writable/duplex/transform
网络编程
- web服务容器apache/tomcat, 为什么node不需要
- net/dgram/http/https
- OSI网络模型 7层
- 三次握手 syn ack ack+1
- net: tcp
- tcp: net.createServer 服务端 / net.connect client 客户端
- 方法/事件:connect/ write /data/end(FIN)/error/close/timeout
- 套接字是stream
- 默认Nagle算法,粘包,setNoDelay(true) dubbo通信
- dgram: udp
- udp createSocket 套接字是EventEmitter非Stream
- 方法/事件: send/close/listening事件/error
- http
- http /http报文、继承 net
- tcp connection维度
- http 将connection抽象tcp 抽象成req 读流,req写流
- kop/express 更高级的封装
- http_praser 核心模块解析
- keep alive
- res.write() /req.end(), 一旦write 后,不能在setHeader/writeHeade, 报文前后顺序决定
- http事件
- http.createServer/http.request
- 链接建立connection事件
- request, 请求来的时候,触发
- 服务close,本机触发close事件
- http客户端请求同浏览器,同ip端口最大5个并发,连接池
- websocket
- 为什么 websocket 与node很配
- upgrade 事件
- websocket 握手http
- 通信传输层tcp (websocket数据帧)
- 方法/事件: new webSocket , send onmessage (之前长轮询,comet req.end())
- 通用掩码加密
- node中没有websocket库自带,ws/ socket.io
- ssl/tls
- http应用层透明数据、网景ssl(浏览器实现). secure socket layer / 到标准化(服务端、浏览器)TLS transport Layer secure
- crypto/ tls/ https
- tls 建立在 ssl/tls 之上的tcp
- https 建立在tls (openSSL 实现的 ssl/tls)
- tls 非对称加密,对称加密 (对称加密公私秘钥一样速度快)
- 公钥加密传输,私钥解密查看 (互相交换,互相加密发送,自己解密查看)
- 发送之前,服务端和客户端互换 RSA秘钥文件
- 为什么需要数字证书,防止中间人假装服务器
- CA第三方认证中心
web应用
- 基础功能
- 上传方法
- url
- 参数
- cookie
- session
- 缓存
- 路由解析,url,restful
- 数据上传,MIME,不同类型不同 处理
- 中间件
- 什么叫中间件,操作系统
- 如何高效中间件
- 精确路由
- 尽快next, 交接控制权
- 中间调度实现原理
- express/koa 中间件区别
- 中间件异常处理、4个参数、3个参数
- 页面渲染
- 返回不同MIMI 处理
- 文件上传时如何处理的
- 下载文件content-dispostion: inline/attachment
- 视图渲染,渲染引擎,数据、模板、如何优化速度
- bigpipe技术,异步时间全返回,逐步返回,逐步显示,不end ,只write
进程
- node如何利用cpu
- node如何保障稳定性
- node 如何做到可伸缩性
- pm2 进程管理、cluster进程管理、手动进程管理、如何实现
- 同步,复制进程、多进程多线程、基于事件驱动
- 创建多进程方式,master-worker 主从模式、child_process.xxx , webworker浏览器
- exec/execfile/spawn/fork 区别相同, 文件/命令、fork js文件、是否有回调 stdout stderr/ fork/spawn
- options.stdio
- 'pipe' - 相当于 ['pipe', 'pipe', 'pipe'](默认值)。 subprocess.stdout stdin/stderr
- 'ignore' - 相当于 ['ignore', 'ignore', 'ignore']。
- 'inherit' - 相当于 ['inherit', 'inherit', 'inherit'] 或 [0, 1, 2], process.stdout 输出到
- 进程间通信
- 如何进程通信
- 进程通信底层如何做的
- send/ on('message'), exit / error/ disconnect(关闭ipc通道)/close
- *内存共享、消息队列、socket libuv(window(命名管道) linux domian socket),序列化,反序列化(打碎,重建的过程,人的时空穿梭,物质)
- 句柄传递 (服务器句柄、客户端句柄)(句柄是os级别一个文件描述符id number)
- 多进程监听相同端口,不能
- 代理,请求转发,work监听不同端口号
- 主进程监听端口,传递server socket句柄,惊群,抢夺现象。node通信支持发送句柄,文件描述符 (父listen p xxx, 把sever传递,然后每个on('connenction', socket客户端))()
- 主进程监听端口,传递连接进来后的客户端socket, 逻辑层来负载均衡。
- 多进程存活管理
- work平滑重启
- 配置、静态数据动态载入
- subprocess.kill(信号)
- process.kill(pid, 信号)
- kill -l 事件数值,node提供了对应的事件监听
- 问题进程不在接受新请求,延迟退出,主创建新进程,后问题进程退出
- 频繁重启、报警策略
- 单机最大长连接数
- linux系统单机支持的tcp连接数主要受三个方面的限制:
- 文件描述符的限制
- tcp本身的限制,就涉及到tcp四元组(远端IP,远端端口号,本地IP,本地端口号),它标识一个tcp连接
- 系统内存限制
- 进程间数据共享
- 轮询
- 主动通知,启动注册
- cluster 多进程模式
- cluster.isMaster isWorker
- 向master进程注册该worker,若master进程是第一次接收到监听此端口/描述符下的worker,则起一个内部TCP服务器,来承担监听该端口/描述符的职责, 随后在master中记录下该worker
- hack掉worker进程中的net.Server实例的listen方法里监听端口/描述符的部分,使其不再承担该职责
单元测试
- benchmark 基础测试
- 性能压测
产品化
-
项目目录规范
-
构建规范
-
编码规范
-
代码审查
-
构建
-
部署
-
性能动静分离,缓存, cdn
-
日志,日志分等级、日志格式、日志切割
-
监控
- 日志监控
- pv/uv
- 耗时
- 进程
- 磁盘
- 网络
- cpu
- gc
- cpu load
-
稳定性,多进程、多实例、多机器、多机房,负载均衡,物理、软件、异地双活、lvs
-
微服务,异构同存,语言做适合的事,通过协议打通