最近看到一篇讲 backpressure 的文章,今天来聊一聊背压问题。
按照百度的说法
指运动流体在密闭容器中沿其路径(譬如管路或风通路)流动时,由于受到障碍物或急转弯道的阻碍而被施加的与运动方向相反的压力
简单来说,水箱入水多,出水少
在正式进入文章之前,务必要注意,
Producer 产出多 Consumer 来不及消费完
小到文件的 IO, 在请求到响应的整个生命周期,大到成白上千的数据计算任务,都会存在背压问题。
https://nodejs.org/en/docs/guides/backpressuring-in-streams/
NodeJS 团队分别测试了禁用和启用 backpressure 特性的情况下运行了这段脚本
const gzip = require("zlib").createGzip()
const fs = require("fs")
const inp = fs.createReadStream("The.Matrix.1080p.mkv")
const out = fs.createWriteStream("The.Matrix.1080p.mkv.gz")
inp.pipe(gzip).pipe(out)
不支持 backpressure 的情况首先带来的是内存的激增,其次是
对于 NodeJS 来说,选择了 Buffer 的手段
对于 客户端 -> 服务 A -> 服务 B
往往是在客户端与服务 A 之前加负载均衡,A 与 B 之间也加负载均衡
负载均衡也分为两种,服务端负载均衡以及客户端负载均衡。
大多是扩 buffer, 扩消费者。
之前写过弹幕类服务。其中对前后端的部分考虑点还是很有趣的。
在弹幕激增的情况下,弹幕列表不能瞬间挂掉。
对于用户发送的弹幕消息,后端做好用户的分组,然后针对每个用户做好弹幕限流。这样确保后端传给前端的弹幕事件是可接受范围内的。
然而,随着弹幕瞬时消息的激增,前端那边还是有点控不住了。
几轮讨论下来,判断出 UI 渲染是瓶颈。后端已经做好用户的分组和弹幕的限流。再做消息的合并必要性不是很大。
比如,瞬间接收 100 次弹幕事件。应该按照每秒进行合并弹幕批量前面 95 条弹幕接着渲染最后 5 条弹幕。
整个界面就看起来顺滑多了。
参考 https://steveholgado.com/rxjs-chat-app/