← Node / Backend Course

BACKEND ADVANCED · 143

Streams / Backpressure:資料不一定要一次全部放進 Memory

Request body、檔案、network response 都可能是逐塊到達的資料流。Stream 讓程式邊讀邊處理;backpressure 則避免 producer 比 consumer 快太多把 memory 撐爆。

Learning outcomes

1. 一次全部讀 vs stream

const file =
  await readFile(
    "huge.csv"
  );

整個檔案先進 memory。對巨大資料不一定合適。

const stream =
  createReadStream(
    "huge.csv"
  );

資料分 chunks 到達,可逐段處理。

2. Backpressure

fast producer→ chunksslow consumer→ pressureflow control

如果 consumer 跟不上,stream system 需要暫停/調節 producer,而不是無限堆 buffer。

3. pipeline

await pipeline(
  createReadStream(
    "courses.csv"
  ),
  transformCourses(),
  createWriteStream(
    "report.csv"
  )
);

Pipeline 讓資料流與 error propagation 更集中。

4. Byte stream、Object mode 與 Transform

Node stream 可以處理 bytes/strings,也能在 object mode 傳 JavaScript values。Transform stream 同時是 readable 與 writable:收到 chunk 後轉換,再把新 chunk 往下游送。

source
  .pipe(parser)
  .pipe(transformer)
  .pipe(destination);

真正 production code 還要處理 source error、transform error、destination error;這也是為什麼 pipeline() 比手工串很多 pipe() 更容易建立統一 failure boundary。

5. Backpressure 不只是記憶體問題

當 downstream 變慢,buffer 增長也會提高 latency,甚至讓 process 被 OOM killer 終止。高流量 server 要觀察 throughput、buffer、memory 與 response latency,而不是只看「最後有沒有傳完」。

Project checkpoint:Course export

Course API 新增大型 CSV export,不先把十萬筆全部串成一個 giant string,而是逐步產生 response stream。

Knowledge check

  1. 為什麼大檔案 readFile 可能是 memory 問題?
  2. backpressure 解的是 producer/consumer 哪種不平衡?
  3. HTTP request body 為什麼本質上適合 stream model?
  4. 設計一個 CSV export pipeline。