《深入理解nodejs》笔记 一

1 node介绍

node特点

事件驱动

异步IO / 非阻塞IO

事件与回调函数

世界上最大得开源生态系统-npm

单线程 维护事件循环队列实现

优点:在node中 js线程无法共享状态 不用关心状态问题 没有死锁 也没有线程切换得开销

缺点:1)无法利用多核CPU 2)错误会引起整个应用的退出 3)大量计算占用CPU导致无法继续调用异步IO

跨平台

应用场景

IO密集型 基于事件循环得处理能力 擅长

CPU密集型 擅长 挑战:长时间得计算会占用CPU时间片 解决:分解大型运算 

充分利用CPU:1)c#扩展来实现计算更高效 2)通过子进程 将计算与IO分离 还能充分利用多核CPU

与遗留系统不冲突

分布式应用

2 模块机制

规范 

- CommonJS 规范  侧重于后端 同步加载 require module.exports 模块标识符 相对路径 绝对路径 可以没有文件后缀名

- AMD 规范 侧重于前端 异步并行加载 依赖前置 模块定义 define(id?, dependencies?, factory); 

- CMD规范 支持动态引入  依赖就近 按需引入 

- ES6模块化  尽量的静态化 编译时就能确定依赖关系以及输入输出变量 import export 只读引用

详细说明 https://segmentfault.com/a/1190000015991869

node模块实现 

路径分析 文件定位 编译执行 三个步骤 详细 可参照 https://www.cnblogs.com/AliceX-J/p/5276125.html

npm 与包

第三方库得发布与管理工具

3 异步IO

单线程 原理多线程死锁 状态同步等问题 利用异步IO 原理单线程阻塞 更好得使用CPU 多核CPU 提供了类似webworker得子进程

阻塞IO 需要等待CPU等待系统内核执行完毕后返回 

非阻塞IO 调用后立即返回 通过轮询不断确认是都调用完毕

node得异步IO 事件循环 观察者 和请求对象 IO线程池

事件循环 每次循环为一个Tick 如果有待处理事件 则处理 如果有关联回调则执行 如果没有则下一个Tick

观察者 事件循环就是典型得生产者 消费者 异步IO 网络请求 就是事件的生产者 

请求对象 中间产物 所以的状态都保存在这个对象中 包括送入线程池等待执行以及IO操作完毕后的回调处理

执行回调 组装好请求兑现给送入IO线程池等待执行 是第一部分 回调通知是第二部分 结果存储在req->result 然后通知对象操作已完成 然后归还线程池 然后提交完成 事件轮询 会检查 然后执行

非IO异步

定时器 settimeout setinterval 创建的定时器会被插入到定时器观察者内部的一个红黑树中 每次Tick 会取出检查时都超时 执行 时间复杂度O(lg(n))

process.nextTick 将回调函数放入队列(数组) 下一轮Tick时取出执行 时间复杂度O(1) 

setimmediate 回调函数保存在链表中 一次Tick执行一个

4 异步编程

函数式编程

高阶函数 可以把函数作为参数 或者把函数作为返回值

偏函数 通过指定部分参数产生一个新的定制函数的形式

异步编程

优点 高效 非阻塞 

难点 1)异常处理 error-first  2)嵌套过深 3)阻塞代码 4)多线程编程 5)异步转同步

解决方案 

1)事件发布订阅模式  - hook机制  - 很容易继承 - 利用once解决雪崩(同一时间同意命令的大量请求)只查询一次 

2)promise deffer - promise只会存在三种状态 未完成 完成 失败 其中的一种 不可逆转 不可更改 

3)流程控制库

(但目前为止 异步的终极方案是ES7 的 async/await 是Promise加生成器模式的语法糖 将生成器和run封装)

5 内存控制

V8垃圾回收机制

新生代内存(存活时间短)Scavenge算法进行垃圾回收 具体实现中主要采用了Cheney算法 将空间一分为二 标记存活对象复制到另一半 然后将原来的空间清空 两个空间进行交换

晋升 两种情况(一个是看对象是否经历过Scavenge回收 一个时To空间的内存占用超过限制)

老生代内存 (常驻内存)Mark-Sweep & Mark-Compact 标记(标记活着的对象) 清除 (死亡的对象)

Incremental Marking 增量标记 拆分执行 (上面两种为全停顿“stop-the-world”)

影响内存的因素

闭包 和全局变量引用 

内存泄漏

缓存 队列 (消费速度低于生产速度 造成队列的堆积)

6 理解Buffer

对外内存 位于全局变量 使用无需require

Buffer对象类似于数组 元素为16进制的两位数 即0-255的值 dayu255依次-255 小于255依次+255

内存分配 slab分配机制 动态内存管理机制 申请固定大号的内存区域  8k为界限 

小于8k为小对象 放到没有被分配状态(empty)slab 或者 部分分配状态(partial)slab空间中

大对象 直接分配一个slowBuffer对象作为slab单元 独占

Buffer转字符串

toString()

Buffer拼接

对于中文宽字节 可能会出现buffer之间拼接转码错误的问题 可以设置setEncoding('utf-8'); 传递编码后的字符串 

7 网络编程

以下 还有 构建web应用 玩转进程 测试 产品化 就看了 但是看不懂 也许在这方面的基础知识太过欠缺 学一学网络之后再来看一遍再做笔记吧!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值