返回顶部
首页 > 资讯 > 精选 >Node中的Stream是什么
  • 746
分享到

Node中的Stream是什么

2023-07-05 01:07:49 746人浏览 独家记忆
摘要

本篇内容主要讲解“node中的Stream是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Node中的Stream是什么”吧!stream 是一个抽象的数据接口,它继承了 EventEmit

本篇内容主要讲解“node中的Stream是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Node中的Stream是什么”吧!

stream 是一个抽象的数据接口,它继承了 EventEmitter,它能够发送/接受数据,本质就是让数据流动起来,如下图:Node中的Stream是什么

流不是 Node 中独有的概念,是操作系统最基本的操作方式,在 linux 中 | 就是 Stream,只是 Node 层面对其做了封装,提供了对应的 api

为啥要一点一点?

首先使用下面的代码创建一个文件,大概在 400MB 左右

Node中的Stream是什么

当我们使用 readFile 去读取的时候,如下代码

Node中的Stream是什么

正常启动服务时,占用 10MB 左右的内存

Node中的Stream是什么

使用curl Http://127.0.0.1:8000发起请求时,内存变为了 420MB 左右,和我们创建的文件大小差不多

Node中的Stream是什么

改为使用使用 stream 的写法,代码如下

Node中的Stream是什么

再次发起请求时,发现内存只占用了 35MB 左右,相比 readFile 大幅减少

Node中的Stream是什么

如果我们不采用流的模式,等待大文件加载完成在操作,会有如下的问题:

  • 内存暂用过多,导致系统崩溃

  • CPU 运算速度有限制,且服务于多个程序,大文件加载过大且时间久

总结来说就是,一次性读取大文件,内存和网络都吃不消

如何才能一点一点?

我们读取文件的时候,可以采用读取完成之后在输出数据

Node中的Stream是什么

上述说到 stream 继承了 EventEmitter 可以是实现监听数据。首先将读取数据改为流式读取,使用 on("data", ()⇒{}) 接收数据,最后通过 on("end", ()⇒{}) 最后的结果

Node中的Stream是什么

有数据传递过来的时候就会触发 data 事件,接收这段数据做处理,最后等待所有的数据全部传递完成之后触发 end 事件。

数据的流转过程

数据从哪里来—source

数据是从一个地方流向另一个地方,先看看数据的来源。

  • http 请求,请求接口来的数据

    Node中的Stream是什么

  • console 控制台,标准输入 stdin

    Node中的Stream是什么

  • file 文件,读取文件内容,例如上面的例子

连接的管道—pipe

在 source 和 dest 中有一个连接的管道 pipe,基本语法为 source.pipe(dest) ,source 和 dest 通过 pipe 连接,让数据从 source 流向 dest

我们不需要向上面的代码那样手动监听 data/end 事件.

pipe 使用时有严格的要求,source 必须是一个可读流,dest 必须是一个可写流

??? 流动的数据到底是一个什么东西?代码中的 chunk 是什么?

到哪里去—dest

stream 常见的三种输出方式

  • console 控制台,标准输出 stdout

    Node中的Stream是什么

  • http 请求,接口请求中的 response

    Node中的Stream是什么

  • file 文件,写入文件

    Node中的Stream是什么

流的种类

Node中的Stream是什么

可读流 Readable Streams

可读流是对提供数据的源头(source)的抽象

所有的 Readable 都实现了 stream.Readable 类定义的接口

Node中的Stream是什么

? 读取文件流创建

fs.createReadStream 创建一个 Readable 对象

Node中的Stream是什么

读取模式

可读流有两种模式,流动模式(flowing mode)暂停模式(pause mode),这个决定了 chunk 数据的流动方式:自动流动和手工流动

在 ReadableStream 中有一个 _readableState 属性,在其中有一个 flowing 的一个属性来判断流的模式,他有三种状态值:

  • ture:表示为流动模式

  • false:表示为暂停模式

  • null:初始状态

Node中的Stream是什么

可以使用热水器模型来模拟数据的流动。热水器水箱(buffer 缓存区)存储着热水(需要的数据),当我们打开水龙头的时候,热水就会从水箱中不断流出来,并且自来水也会不断的流入水箱,这就是流动模式。当我们关闭水龙头时,水箱会暂停进水,水龙头则会暂停出水,这就是暂停模式。

流动模式

数据自动地从底层读取,形成流动现象,并通过事件提供给应用程序。

  • 监听 data 事件即可进入该模式
    当 data 事件被添加后,可写流中有数据后会将数据推到该事件回调函数中,需要自己去消费数据块,如果不处理则该数据会丢失

  • 调用 stream.pipe 方法将数据发送到 Writeable

  • 调用 stream.resume 方法

    Node中的Stream是什么

暂停模式

数据会堆积在内部缓冲器中,必须显式调用 stream.read() 读取数据块

  • 监听 readable 事件可写流在数据准备好后会触发该事件回调,此时需要在回调函数中使用 stream.read() 来主动消费数据。readable 事件表明流有新的动态:要么有新的数据,要么流已经读取所有数据

    Node中的Stream是什么

两种模式之间如何进行转换呢
  • 可读流在创建完成之后处于初始状态   //TODO:和网上的分享不一致

  • 暂停模式切换到流动模式

    - 监听 data 事件
    - 调用 stream.resume 方法
    - 调用 stream.pipe 方法将数据发送到 Writable

    Node中的Stream是什么

  • 流动模式切换到暂停模式

    - 移除 data 事件
    - 调用 stream.pause 方法
    - 调用 stream.unpipe 移除管道目标
实现原理

创建可读流的时候,需要继承 Readable 对象,并且实现 _read 方法

Node中的Stream是什么

创建一个自定义可读流

Node中的Stream是什么

当我们调用 read 方法时,整体的流程如下:Node中的Stream是什么

  • doRead

    流中维护了一个缓存,当调用 read 方法的时候来判断是否需要向底层请求数据

    当缓存区长度为0或者小于 highWaterMark 这个值得时候就会调用 _read 去底层获取数据 源码链接

    Node中的Stream是什么

可写流 Writeable Stream

可写流 是对数据写入目的地的一种抽象,是用来消费上游流过来的数据,通过可写流把数据写入设备,常见的写入流就是本地磁盘的写入

Node中的Stream是什么

可写流的特点
  • 通过 write 写入数据

    Node中的Stream是什么

  • 通过 end 写数据并且关闭流,end = write + close

    Node中的Stream是什么Node中的Stream是什么

  • 当写入数据达到 highWaterMark 的大小时,会触发 drain 事件

    Node中的Stream是什么

    调用 ws.write(chunk) 返回 false,表示当前缓冲区数据大于或等于 highWaterMark 的值,就会触发 drain 事件。其实是起到一个警示作用,我们依旧可以写入数据,只是未处理的数据会一直积压在可写流的内部缓冲区中,直到积压沾满 node.js 缓冲区后,才会被强行中断

自定义可写流

所有的 Writeable 都实现了 stream.Writeable 类定义的接口

只需要实现 _write 方法就能够将数据写入底层

Node中的Stream是什么

  • 通过调用调用 writable.write 方法将数据写入流中,会调用 _write 方法将数据写入底层

  • 当 _write 数据成功后,需要调用 next 方法去处理下一个数据

  • 必须调用 writable.end(data) 来结束可写流,data 是可选的。此后,不能再调用 write 新增数据,否则会报错

  • 在 end 方法调用后,当所有底层的写操作均完成时,会触发 finish 事件

双工流 Duplex Stream

双工流,既可读,也可写。实际上继承了 Readable 和 Writable 的一种流,那它既可以当做可读流来用又可以当做可写流来用

自定义的双工流需要实现 Readable 的 _read 方法和 Writable 的 _write 方法

Node中的Stream是什么

net 模块可以用来创建 Socket,socket 在 nodejs 中是一个典型的 Duplex,看一个 tcp 客户端的例子

Node中的Stream是什么

client 就是一个 Duplex,可写流用于向服务器发送消息,可读流用于接受服务器消息,两个流内的数据并没有直接的关系

转换流 Transform Stream

上述的例子中,可读流中的数据(0/1)和可写流中的数据(’F’,’B’,’B’)是隔离的,两者并没有产生关系,但对于 TransfORM 来说在可写端写入的数据经过变换后会自动添加到可读端。

Transform 继承于 Duplex,并且已经实现了 _write 和 _read 方法,只需要实现 _tranform 方法即可

Node中的Stream是什么

gulp 基于 Stream 的自动化构建工具,看一段官网的示例代码

Node中的Stream是什么

less → less 转为 CSS → 执行 css 压缩 → 压缩后的 css

其实 less() 和 minifyCss() 都是对输入的数据做了一些处理,然后交给了输出数据

Duplex 和 Transform 的选择

和上面的示例对比起来,我们发现一个流同时面向生产者和消费者服务的时候我们会选择 Duplex,当只是对数据做一些转换工作的时候我们便会选择使用 Tranform

背压问题

什么是背压

背压问题来源于生产者消费者模式中,消费者处理速度过慢

比如说,我们下载过程,处理速度为3Mb/s,而压缩过程,处理速度为1Mb/s,这样的话,很快缓冲区队列就会形成堆积

要么导致整个过程内存消耗增加,要么导致整个缓冲区慢,部分数据丢失

Node中的Stream是什么

什么是背压处理

背压处理可以理解为一个向上”喊话”的过程

当压缩处理发现自己的缓冲区数据挤压超过阈值的时候,就对下载处理“喊话”,我忙不过来了,不要再发了

下载处理收到消息就暂停向下发送数据

Node中的Stream是什么

如何处理背压

我们有不同的函数将数据从一个进程传入另外一个进程。在 Node.js 中,有一个内置函数称为 .pipe(),同样地最终,在这个进程的基本层面上我们有二个互不相关的组件:数据的_源头_,和_消费者_

当 .pipe() 被源调用之后,它通知消费者有数据需要传输。管道函数为事件触发建立了合适的积压封装

在数据缓存超出了 highWaterMark 或者写入的列队处于繁忙状态,.write() 会返回 false

当 false 返回之后,积压系统介入了。它将暂停从任何发送数据的数据流中进入的 Readable。一旦数据流清空了,drain 事件将被触发,消耗进来的数据流

一旦队列全部处理完毕,积压机制将允许数据再次发送。在使用中的内存空间将自我释放,同时准备接收下一次的批量数据

Node中的Stream是什么

我们可以看到 pipe 的背压处理:

  • 将数据按照chunk进行划分,写入

  • 当chunk过大,或者队列忙碌时,暂停读取

  • 当队列为空时,继续读取数据

到此,相信大家对“Node中的Stream是什么”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

--结束END--

本文标题: Node中的Stream是什么

本文链接: https://lsjlt.com/news/348910.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Node中的Stream是什么
    本篇内容主要讲解“Node中的Stream是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Node中的Stream是什么”吧!stream 是一个抽象的数据接口,它继承了 EventEmit...
    99+
    2023-07-05
  • node中的stream有哪些类型
    本篇内容介绍了“node中的stream有哪些类型”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! ...
    99+
    2024-04-02
  • 一文聊聊Node中的stream(流)
    流是用于在 Node.js 中处理流数据,也就是连续字节的抽象接口。 流有 4 种基本类型,本篇文章主要介绍其中两种 —— 可读流和可写流。可读的(Readable)我们可以通过 fs.createReadStream() 创建一个可读流 ...
    99+
    2023-05-14
    stream node nodejs​
  • 深入浅析Node中的Stream(流)
    和上面的示例对比起来,我们发现一个流同时面向生产者和消费者服务的时候我们会选择 Duplex,当只是对数据做一些转换工作的时候我们便会选择使用 Tranform背压问题什么是背压背压问题来源于生产者消费者模式中,消费者处理速度过慢比如说,我...
    99+
    2023-05-14
    前端 Node.js
  • node中Stream流的详细介绍
    目录一、是什么二、种类双工流双工流三、应用场景get请求返回文件给客户端文件操作一些打包工具的底层操作一、是什么 流(Stream),是一个数据传输手段,是端到端信息交换的一种方式,...
    99+
    2024-04-02
  • Java中Stream的作用是什么
    Java中Stream的作用是什么?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。Java可以用来干什么Java主要应用于:1. web开发;2. Android开发;3. ...
    99+
    2023-06-14
  • linux中stream的含义是什么
    这篇文章主要介绍“linux中stream的含义是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“linux中stream的含义是什么”文章能帮助大家解决问题。 ...
    99+
    2023-03-19
    linux stream
  • Java8中的Stream的原理是什么
    本篇内容主要讲解“Java8中的Stream的原理是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java8中的Stream的原理是什么”吧!Stream的组成与特点Stream(流)是一个...
    99+
    2023-06-15
  • 浅析php中的stream(流)是什么
    PHP Stream 是一种用于读取、写入和操作不同类型数据流的抽象概念。PHP Stream 给 PHP 程序员提供了一种统一的、灵活的方式来处理数据流,包括文件、网络连接、内存等等。通过使用 PHP Stream,开发者可以像处理本地磁...
    99+
    2023-05-14
    php
  • node-red中dashboard是什么
    这篇文章主要介绍node-red中dashboard是什么,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!Node-red支持自定义节点,当然也就支持自定义图形化的节点。也有优秀的开发者把自己建立的图形化节点无偿分享。...
    99+
    2023-06-29
  • 什么是node中间件
    本教程操作环境:Windows10系统、node v12.21.0版、Dell G3电脑。什么是node中间件?深入浅出nodejs中间件原理前言中间件是介于应用系统和系统软件之间的一类软件,它使用系统软件所提供的基础服务(功能),衔接网络...
    99+
    2023-05-14
    中间件 node
  • node中mongooes的概念是什么
    这篇文章主要介绍“node中mongooes的概念是什么”,在日常操作中,相信很多人在node中mongooes的概念是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”no...
    99+
    2024-04-02
  • node中multer的概念是什么
    这篇文章主要介绍“node中multer的概念是什么”,在日常操作中,相信很多人在node中multer的概念是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”node中m...
    99+
    2024-04-02
  • node中token的概念是什么
    这篇文章主要讲解了“node中token的概念是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“node中token的概念是什么”吧! ...
    99+
    2024-04-02
  • node中Transform的作用是什么
    本篇文章给大家分享的是有关node中Transform的作用是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。Transform流特性在开发...
    99+
    2024-04-02
  • Node中的可读流是什么
    这篇文章主要介绍了Node中的可读流是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Node中的可读流是什么文章都会有所收获,下面我们一起来看看吧。1. 基本概念1.1. 流的历史演变流不是 Nodejs ...
    99+
    2023-07-05
  • Node中的net模块是什么
    本文小编为大家详细介绍“Node中的net模块是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“Node中的net模块是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。1. OSI 七层协议模型想要学明白通...
    99+
    2023-07-05
  • Java8中Stream的使用方式是什么
    这篇文章主要介绍“Java8中Stream的使用方式是什么”,在日常操作中,相信很多人在Java8中Stream的使用方式是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java8中Stream的使用方式...
    99+
    2023-06-30
  • node中间层的作用是什么
    这篇文章主要介绍“node中间层的作用是什么”,在日常操作中,相信很多人在node中间层的作用是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”node中间层的作用是什么”...
    99+
    2024-04-02
  • node中的模块系统是什么
    这篇文章主要介绍“node中的模块系统是什么”,在日常操作中,相信很多人在node中的模块系统是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”node中的模块系统是什么”...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作