MST

星途 面试题库

面试题:Node.js 网络通信性能优化之流的应用

假设你正在处理一个大文件的网络传输任务,使用 Node.js 的流(Stream)来优化性能。请描述如何合理使用可读流(Readable Stream)和可写流(Writable Stream),并写出关键代码示例,同时说明这样做如何提升网络通信性能。
30.2万 热度难度
前端开发Node.js

知识考点

AI 面试

面试题答案

一键面试

合理使用可读流和可写流

  1. 可读流(Readable Stream):用于从大文件中按块读取数据,而不是一次性将整个文件读入内存。通过设置适当的 highWaterMark(缓冲区大小),控制每次读取的数据量,避免内存占用过高。当数据可读时,触发 data 事件,将数据块传递给可写流。
  2. 可写流(Writable Stream):负责将从可读流接收到的数据块写入网络连接(例如 http.ServerResponse 或网络套接字)。可写流也有 highWaterMark 属性,当写入缓冲区已满时,需要暂停可读流,防止数据丢失。当可写流缓冲区有空间时,触发 drain 事件,此时可以恢复可读流。

关键代码示例

以下是一个简单的示例,使用 fs.createReadStream 创建可读流,http.ServerResponse 作为可写流来实现大文件的网络传输:

const http = require('http');
const fs = require('fs');

const server = http.createServer((req, res) => {
  const readableStream = fs.createReadStream('largeFile.txt');
  readableStream.on('data', (chunk) => {
    // 如果可写流缓冲区已满,暂停可读流
    if (res.write(chunk) === false) {
      readableStream.pause();
    }
  });
  readableStream.on('end', () => {
    res.end();
  });
  res.on('drain', () => {
    // 可写流缓冲区有空间,恢复可读流
    readableStream.resume();
  });
});

const port = 3000;
server.listen(port, () => {
  console.log(`Server running on port ${port}`);
});

提升网络通信性能的原因

  1. 减少内存占用:通过按块读取和写入数据,避免一次性将整个大文件加载到内存中,降低了内存使用量,使系统能够处理更大的文件而不会因内存不足崩溃。
  2. 流量控制:利用可写流的 drain 事件和可读流的 pauseresume 方法,实现了流量控制。当网络传输速度较慢,可写流缓冲区满时,暂停可读流,防止数据堆积在内存中;当缓冲区有空间时,恢复可读流,保证数据持续传输,提高了网络通信的稳定性和效率。
  3. 异步处理:流的操作是基于事件驱动的异步操作,不会阻塞主线程,使得 Node.js 可以在传输文件的同时处理其他请求,提高了服务器的整体性能和并发处理能力。