掌握聚合最新动态了解行业最新趋势
API接口,开发服务,免费咨询服务

深入理解 Node Stream 内部机制

文章来自公众号:小胡子哥

相信很多人对 Node 的 Stream 已经不陌生了,不论是请求流、响应流、文件流还是 socket 流,这些流的底层都是使用 stream 模块封装的,甚至我们平时用的最多的 console.log 打印日志也使用了它,不信你打开 Node runtime 的源码,看看 lib/console.js:

  1. function write(ignoreErrors, stream, string, errorhandler) {

  2.  // ...

  3.  stream.once('error', noop);

  4.  stream.write(string, errorhandler);

  5.  //...

  6. }

  7. Console.prototype.log = function log(...args) {

  8.  write(this._ignoreErrors,

  9.        this._stdout,

  10.        `${util.format.apply(null, args)}\n`,

  11.        this._stdoutErrorHandler);

  12. };

Stream 模块做了很多事情,了解了 Stream,那么 Node 中其他很多模块理解起来就顺畅多了。

本文代码和图片可以在这里取用:https://github.com/barretlee/dive-into-node-stream

stream 模块

如果你了解 生产者和消费者问题 的解法,那理解 stream 就基本没有压力了,它不仅仅是资料的起点和落点,还包含了一系列状态控制,可以说一个 stream 就是一个状态管理单元。了解内部机制的最佳方式除了看 Node 官方文档,还可以去看看 Node 的 源码:

  • lib/module.js

  • lib/_stream_readable.js

  • lib/_stream_writable.js

  • lib/_stream_tranform.js

  • lib/_stream_duplex.js

把 Readable 和 Writable 看明白,Tranform 和 Duplex 就不难理解了。

Readable Stream

Readable Stream 存在两种模式,一种是叫做 FlowingMode,流动模式,在 Stream 上绑定 ondata 方法就会自动触发这个模式,比如:

  1. const readable = getReadableStreamSomehow();

  2. readable.on('data', (chunk) => {

  3.  console.log(`Received ${chunk.length} bytes of data.`);

  4. });

这个模式的流程图如下:

1680-640.jpg.jpg

资源的数据流并不是直接流向消费者,而是先 push 到缓存池,缓存池有一个水位标记 highWatermark,超过这个标记阈值,push 的时候会返回 false,什么场景下会出现这种情况呢?

  • 消费者主动执行了 .pause()

  • 消费速度比数据 push 到缓存池的生产速度慢

有个专有名词来形成这种情况,叫做「背压」,Writable Stream 也存在类似的情况。

流动模式,这个名词还是很形象的,缓存池就像一个水桶,消费者通过管口接水,同时,资源池就像一个水泵,不断地往水桶中泵水,而 highWaterMark 是水桶的浮标,达到阈值就停止蓄水。下面是一个简单的 Demo:

  1. const Readable = require('stream').Readable;

  2. // Stream 实现

  3. class MyReadable extends Readable {

  4.  constructor(dataSource, options) {

  5.    super(options);

  6.    this.dataSource = dataSource;

  7.  }

  8.  // 继承了 Readable 的类必须实现这个函数

  9.  // 触发系统底层对流的读取

  10.  _read() {

  11.    const data = this.dataSource.<

    声明:所有来源为“聚合数据”的内容信息,未经本网许可,不得转载!如对内容有异议或投诉,请与我们联系。邮箱:marketing@think-land.com

  • 营运车判定查询

    输入车牌号码或车架号,判定是否属于营运车辆。

    输入车牌号码或车架号,判定是否属于营运车辆。

  • 名下车辆数量查询

    根据身份证号码/统一社会信用代码查询名下车辆数量。

    根据身份证号码/统一社会信用代码查询名下车辆数量。

  • 车辆理赔情况查询

    根据身份证号码/社会统一信用代码/车架号/车牌号,查询车辆是否有理赔情况。

    根据身份证号码/社会统一信用代码/车架号/车牌号,查询车辆是否有理赔情况。

  • 车辆过户次数查询

    根据身份证号码/社会统一信用代码/车牌号/车架号,查询车辆的过户次数信息。

    根据身份证号码/社会统一信用代码/车牌号/车架号,查询车辆的过户次数信息。

  • 风险人员分值

    根据姓名和身份证查询风险人员分值。

    根据姓名和身份证查询风险人员分值。

0512-88869195
数 据 驱 动 未 来
Data Drives The Future