что такое стрим
определение
Английский потокstream
, Stream — это абстрактный интерфейс данных,Node.js
Многие объекты в потоке реализуют потоки, а потокиEventEmitter
Экземпляр объекта, который в любом случае принимает форму данных (сBuffer
единиц) или что-то, что поглощает данные, что, по сути, заставляет их течь.
Может быть, будет более интуитивно смотреть на картинку:
Уведомление:stream
Это не уникальная концепция node.js, а самый простой метод работы операционной системы, но у node.js есть API для поддержки этого метода работы. команда Linux |stream
.
Об авторе: koala, сосредоточив внимание на совместном использовании полного стека технологий Node.js, от JavaScript до Node.js, до серверной базы данных, я желаю вам стать отличным старшим инженером Node.js. [Руководство по развитию программиста] Автор, блог Github с открытым исходным кодомGitHub.com/koala-co Nth…
Зачем изучать стримы
Пример воспроизведения видео
Маленькие друзья наверняка видели фильм онлайн, сравните картинку в определении-水桶管道流转图
,source
Это серверное видео.dest
Просто свой плеер (или flash и h5 видео в браузере). Подумайте об этом, способ просмотра фильма похож на замену воды в трубе на картинке выше.Видео передается с сервера на локальный проигрыватель по крупицам, воспроизводится во время потоковой передачи и заканчивается, когда трансляция завершена.
Описание: В этом примере воспроизведения видео, если мы не используем метод конвейера и потоковой передачи, видеофайл загружается непосредственно с сервера, а затем воспроизводится. вызовет много проблем
- Система зависает или дает сбой из-за слишком большого использования памяти
- Поскольку скорость нашей сети, память и скорость работы процессора ограничены, а также существует несколько программ для совместного использования и использования, размер видеофайла после загрузки может достигать нескольких гигабайт.
Пример чтения данных большого файла
Есть такое требование, пример желания прочитать большой файл data
читать с помощью файла
const http = require('http');
const fs = require('fs');
const path = require('path');
const server = http.createServer(function (req, res) {
const fileName = path.resolve(__dirname, 'data.txt');
fs.readFile(fileName, function (err, data) {
res.end(data);
});
});
server.listen(8000);
Используйте этот файлы синтаксиса кода для чтения, и нет проблем, но если файл data.txt очень большой, к сотням m, когда пользователь в ответ на большое количество одновременных запросов, программа может потреблять большие суммы Память, которая может привести к тому, что пользователи проблему медленного подключения. И одновременный запрос слишком велик, накладные расходы на серверу будут отличными. На этот раз мы смотрим наstream
выполнить.
const http = require('http');
const fs = require('fs');
const path = require('path');
const server = http.createServer(function (req, res) {
const fileName = path.resolve(__dirname, 'data.txt');
let stream = fs.createReadStream(fileName); // 这一行有改动
stream.pipe(res); // 这一行有改动
});
server.listen(8000);
Используя поток, вам не нужно читать все файлы, а затем возвращать, а возвращать во время чтения, и данные поступают к клиенту через конвейер, что действительно снижает нагрузку на сервер.
Прочитав два примера, я думаю, что мои друзья должны знать, что什么要使用stream
Ну давай же! Поскольку чтение и работа с большими файлами одновременно, память и сеть невыносимы, поэтому позвольте данным течь и работать понемногу.
потоковый процесс
посмотри на это снова水桶管道流转图
stream
Весь процесс потока включает в себя источник, место назначения и конвейер, соединяющий их (ядро потока) Три представлены отдельно, чтобы помочь вам понять поток процесса потока.
откуда берется поток - soucre
stream
Есть три распространенных источника:
- ввод из консоли
-
http
в запросеrequest
- прочитать файл
Здесь сначала从控制台输入
Таким образом, 2 и 3 два путиstream应用场景
Главы объяснят подробно.
смотреть абзацprocess.stdin
код
process.stdin.on('data', function (chunk) {
console.log('stream by stdin', chunk)
console.log('stream by stdin', chunk.toString())
})
//控制台输入koalakoala后输出结果
stream by stdin <Buffer 6b 6f 61 6c 61 6b 6f 61 6c 61 0a>
stream by stdin koalakoala
Запустите приведенный выше код: тогда все, что будет введено с консоли, будетdata
событие отслеживается,process.stdin
только одинstream
объект, данные
даstream
Пользовательская функция, которую объект использует для мониторинга входящих данных, которые можно увидеть на выходе.process.stdin
является потоковым объектом.
проиллюстрировать:stream
Объект может слушать"data"
,"end"
,"opne"
,"close"
,"error"
и т.д. события.node.js
Слушайте пользовательские события, используя.on
Метод, например,process.stdin.on(‘data’,…)
, req.on(‘data’,…)
, таким образом, очень интуитивно понятно контролироватьstream
входящие и исходящие данные
Труба, соединяющая ковш с трубой
Как видно из схемы работы ковшового трубопровода, вsource
а такжеdest
Между ними имеется соединительная трубка.pipe
, его основной синтаксисsource.pipe(dest)
,source
а такжеdest
Это подключение через канал и передача данных изsource
течь кdest
.
куда идет поток -dest
Общий выходной поток тремя способами:
- консоль вывода
-
http
в запросеresponse
- записать в файл
потоковые сценарии приложений
stream
Сценарий приложения в основном касаетсяIO
операция, при этомhttp请求
а также文件操作
принадлежатьIO
работать. Снова здесьstream
характер - за счет одноразовогоIO
Операция слишком велика, а накладные расходы на оборудование слишком велики, что влияет на эффективность работы программного обеспечения.IO
Работайте пакетами и сегментами, и пусть данные текут, как водопровод, пока поток не будет завершен, то есть операция не будет завершена. Ниже представлено несколько распространенных сценариев применения.
Представляем небольшой инструмент для стресс-тестирования
Инструмент для нагрузочного тестирования сетевых запросовab
,ab
полное имяApache bench
,ДаApache
поставляется с инструментом, поэтому используйтеab
должен быть установленApache
. система mac os поставляется сApache
,windows
用户视自己的情况进行安装。 бегатьab
начать раньшеApache
,mac os
Способ начатьsudo apachectl start
.
Подробный адрес изучения соответствующих параметров стенда Apache, вы можете посмотреть, если вам интересноПодробный адрес изучения соответствующих параметров стенда Apache
Целью введения этого гаджета является визуальное тестирование следующих сценариев, чтобы увидеть, какие улучшения производительности достигаются при использовании потока.
Применить поток в запросе на получение
Такое требование:
Используйте node.js для реализации HTTP-запроса, чтения файла data.txt, создания службы, прослушивания порта 8000, чтения файла и возврата его клиенту.Говоря о запросах на получение, используйте обычный файл для чтения и сравнения это, см. пример ниже.
- Регулярное использование чтения файла и возврат к примеру ответа клиента, файл называется как
getTest1.js
// getTest.js
const http = require('http');
const fs = require('fs');
const path = require('path');
const server = http.createServer(function (req, res) {
const method = req.method; // 获取请求方法
if (method === 'GET') { // get 请求方法判断
const fileName = path.resolve(__dirname, 'data.txt');
fs.readFile(fileName, function (err, data) {
res.end(data);
});
}
});
server.listen(8000);
- Используйте поток, чтобы вернуть ответ клиенту
Внесите некоторые изменения в приведенный выше код и назовите файл как
getTest2.js
// getTest2.js
// 主要展示改动的部分
const server = http.createServer(function (req, res) {
const method = req.method; // 获取请求方法
if (method === 'GET') { // get 请求
const fileName = path.resolve(__dirname, 'data.txt');
let stream = fs.createReadStream(fileName);
stream.pipe(res); // 将 res 作为 stream 的 dest
}
});
server.listen(8000);
Для примера использования потока в запросе на получение ниже, некоторые мелкие партнеры зададут вопрос, является ли ответ также объектом потока, да, да, для этого水桶管道流转图
, ответ - это дест.
Хотя потоки могут использоваться в запросах на получение, по сравнению с прямым чтением файлов·res.end(data)
Каковы преимущества? В настоящее время используется гаджет стресс-теста, который мы только что рекомендовали.getTest1
а такжеgetTest2
два фрагмента кода, которыеdata.txt
Чтобы увеличить содержимое, используйтеab
инструмент для тестирования, запустите командуab -n 100 -c 100 http://localhost:8000/
,в-n 100
Указывает, что последовательно отправлено 100 запросов,-c 100
Указывает, что количество запросов, отправленных за один раз, равно 100. Сравнив результаты и проанализировав использование потоковой передачи, можно увидеть очень большое улучшение производительности, и друзья могут это увидеть сами.
использовать стрим в посте
Требование генерировать QR-код через сообщение, запрашивающее адрес апплета WeChat.
/*
* 微信生成二维码接口
* params src 微信url / 其他图片请求链接
* params localFilePath: 本地路径
* params data: 微信请求参数
* */
const downloadFile=async (src, localFilePath, data)=> {
try{
const ws = fs.createWriteStream(localFilePath);
return new Promise((resolve, reject) => {
ws.on('finish', () => {
resolve(localFilePath);
});
if (data) {
request({
method: 'POST',
uri: src,
json: true,
body: data
}).pipe(ws);
} else {
request(src).pipe(ws);
}
});
}catch (e){
logger.error('wxdownloadFile error: ',e);
throw e;
}
}
Посмотрите на этот код, который использует поток, создайте объект потока для пути, соответствующего локальному файлу, а затем напрямую.pipe(ws)
, Перенесите поток данных почтового запроса в этот локальный файл.Этот вид потокового приложения чаще используется в процессе разработки серверной части узла.
Публикуйте и используйте резюме потока
Запрос и ответ являются объектами потока и могут использовать характеристики потока. Разница между ними заключается в том, что давайте посмотрим水桶管道流转图
,
Использование потоков в файловых операциях
Пример копии файла
const fs = require('fs')
const path = require('path')
// 两个文件名
const fileName1 = path.resolve(__dirname, 'data.txt')
const fileName2 = path.resolve(__dirname, 'data-bak.txt')
// 读取文件的 stream 对象
const readStream = fs.createReadStream(fileName1)
// 写入文件的 stream 对象
const writeStream = fs.createWriteStream(fileName2)
// 通过 pipe执行拷贝,数据流转
readStream.pipe(writeStream)
// 数据读取完成监听,即拷贝完成
readStream.on('end', function () {
console.log('拷贝完成')
})
Прочитав этот код, я обнаружил, что копирование кажется очень простым, создавая читаемый поток данных.readStream
, Доступный для записи поток данныхwriteStream
, а затем напрямую черезpipe
По каналам проходят данные. Этот вид копирования с использованием потока имеет гораздо более высокую производительность, чем реализация чтения-записи файлового хранилища, поэтому, когда вы столкнетесь с потребностями файловых операций, постарайтесь оценить, нужно ли вам его использовать.stream
выполнить.
Базовая реализация некоторых интерфейсных инструментов упаковки
Некоторые из самых горячих前端打包构建工具
, на всем протяженииnode.js
Процесс написания, упаковки и сборки должен быть процессом частых манипуляций с файлами, неотделимым отstream
, например, сейчас популярнееgulp
, Заинтересованные друзья могут взглянуть на исходный код.
Вид потока
-
Readable Stream
читаемый поток данных -
Writeable Stream
доступный для записи поток данных -
Duplex Stream
Двунаправленный поток данных, может читать и писать одновременно -
Transform Stream
Преобразовывать поток данных, доступный для чтения и записи, и может преобразовывать (обрабатывать) данные (обычно не используется)
Предыдущие статьи были посвящены первым двум потокам данных для чтения и потокам данных для записи. Четвертый поток обычно не используется. Если он вам нужен, выполните поиск в Интернете. Далее я объясню третий поток данных, дуплексный поток.
Duplex Stream
Двунаправленный, как для чтения, так и для записи.Duplex streams
В то же время понялReadable
а такжеWritable
интерфейс.Duplex streams
Примеры включают
tcp sockets
zlib streams
-
crypto streams
Я не использовал дуплексные потоки в своем проекте, вы можете обратиться к этой статье за некоторым содержимым дуплексного потока.Дуплексный поток NodeJS Stream
В чем недостатки стрима
- использовать
rs.pipe(ws)
способ записать файл вместо помещения содержимого rsappend
Перейти к задней части ws, но напрямую перезаписать исходное содержимое ws содержимым rs - Завершенные/закрытые потоки нельзя использовать повторно, поток данных необходимо создать заново
-
pipe
Метод возвращает целевой поток данных, напримерa.pipe(b)
Возврат - b, поэтому обратите внимание на то, является ли объект, который вы слушаете, правильным при прослушивании события. - Если вы хотите прослушивать несколько потоков данных одновременно и используете
pipe
метод объединения потоков данных, вы должны написать: Пример кода:
data
.on('end', function() {
console.log('data end');
})
.pipe(a)
.on('end', function() {
console.log('a end');
})
.pipe(b)
.on('end', function() {
console.log('b end');
});
Общая библиотека классов для потока
-
event-stream Похоже на функциональное программирование
-
awesome-nodejs#streamsЭто также хорошая сторонняя библиотека для потоковой передачи. Заинтересованные партнеры могут заглянуть на github.
Суммировать
После прочтения этой статьи у вас появилось определенное представление о потоке и вы знаете, что у узла все еще есть идеальное решение для обработки файлов. Эта бумага показывает три раза水桶管道流转图
, Трижды произнесите то, что вы всегда хотите, и надейтесь, что друзья это запомнят.
- Каково конкретное содержание потокового потока данных? двоичный или
string
тип или что-то еще, какую пользу приносит этот тип для стрима? - Водопровод на схеме ковшовой трубы, т.е.
pipe
Когда срабатывает функция? При каких обстоятельствах осуществляется переадресация сенсорного потока? Каков основной механизм? Приведенные выше вопросы (разделенные на две статьи из-за объема статьи) будут обсуждаться в моемstream
Вторая статья объяснит подробно.
Так много, чем можно поделиться сегодня.Если вы заинтересованы в общем контенте, вы можете подписаться на официальную учетную запись «Руководство по развитию программиста» или присоединиться к группе технического обмена, чтобы обсудить его вместе.
Присоединяйтесь к нам, чтобы учиться вместе!
группа обмена обучением узлов
Если группа обмена состоит из 100 человек, она не может автоматически присоединиться к группе.Пожалуйста, добавьте учетную запись WeChat помощника группы: узел [coder_qi] Note, и он автоматически втянет вас в группу.