面试题答案
一键面试背压产生的原因
在Node.js Stream流处理中,背压产生于可读流产生数据的速度快于可写流消费数据的速度。当可写流的缓冲区已满,而可读流仍在快速生成数据时,数据无处存放,就会出现背压问题。例如,从网络读取大量数据(可读流)并写入文件(可写流),如果网络速度快但磁盘写入速度慢,就容易产生背压。
代码层面处理背压的方法
1. 使用 pipe
方法自动处理背压
pipe
方法会自动处理背压问题,它会暂停可读流,直到可写流准备好接收更多数据。
const fs = require('fs');
const http = require('http');
const server = http.createServer((req, res) => {
const readableStream = fs.createReadStream('largeFile.txt');
const writableStream = res;
readableStream.pipe(writableStream);
});
server.listen(3000, () => {
console.log('Server running on port 3000');
});
在上述代码中,fs.createReadStream
创建的可读流通过 pipe
方法连接到 res
可写流,pipe
会自动管理背压。
2. 手动处理背压
通过监听可读流的 data
事件和可写流的 drain
事件来手动处理背压。
const fs = require('fs');
const http = require('http');
const server = http.createServer((req, res) => {
const readableStream = fs.createReadStream('largeFile.txt');
const writableStream = res;
let paused = false;
readableStream.on('data', (chunk) => {
if (paused) {
// 如果可写流缓冲区已满,将数据缓存到内存中
// 这里为简单示例,实际应用可能需要更复杂的缓存策略
return;
}
const writeResult = writableStream.write(chunk);
if (!writeResult) {
paused = true;
readableStream.pause();
}
});
writableStream.on('drain', () => {
paused = false;
readableStream.resume();
});
readableStream.on('end', () => {
writableStream.end();
});
});
server.listen(3000, () => {
console.log('Server running on port 3000');
});
在这个示例中,当 write
方法返回 false
时,说明可写流缓冲区已满,暂停可读流。当可写流触发 drain
事件时,表明缓冲区有空间了,恢复可读流。这样就能手动有效地处理背压,确保数据稳定传输和处理。