Nginx配置不当导致的SSE推送事故Cloudprg2024/07/05 00:50:13阅读2分钟

场景

在实现SSE服务端流式传输时后,发生一件事情----输出的文字偶尔会出现合并传输的情况。一开始以黑盒测试的前提下,猜测是React useState高频使用导致状态合并问题。随后在控制台打印数据流,发现是数据本身合并,于是从nginx代理配置上寻找答案。

前缀

在看本文前先埋下几个问题:

  1. react自动批处理的机制?
  2. nginx的哪些配置会影响SSE推送的实施数据?

react自动批处理

  • react18简短提到所有的更新都会自动批处理,比如代码段存在一组更新则只会重渲染一次。
  • 实际上函数组件的useState是没有automatically merge的机制的。 类组件中的setState是有的。参考官文的解释
Note 注意 Unlike the setState method found in class components, useState does not automatically merge update objects. You can replicate this behavior by combining the function updater form with object spread syntax: 与类组件中 setState 的方法不同, useState 它不会自动合并更新对象。可以通过将函数更新程序窗体与对象扩展语法相结合来复制此行为: const [state, setState] = useState({}); setState(prevState => { // Object.assign would also work return {...prevState, ...updatedValues}; }); Another option is useReducer, which is more suited for managing state objects that contain multiple sub-values. 另一个选项是 useReducer ,它更适合管理包含多个子值的状态对象。

我不想批处理呢?

如果某个片段只是存在一个useState,但又担心频繁调用会被合批。那使用flushSync可以解决问题(不过在性能上会有损耗)

nginx配置sse要点

主要是配置三个属性来保证sse的 持久连接、数据实时、无需缓存。

  • proxy_buffering: none
  • cache-control: no-cache
  • conneciton: keep-alive

着重强调proxy_buffering这个属性,它在Nginx中的默认开启的,用于将数据积攒在缓冲区,直到缓冲区空间不足或到达特定数据量才发送给客户端。 这也是导致数据合批的主要原因。

结果

  1. nginx配置sse时要注意proxy buffering的禁用
  2. react函数组件中没有数据合批的机制
  3. useState不一定是更新sse推送数据流的最好方式,使用组件或者自研requestAnimationFrame也许能使交互效果更丝滑

参考文章

标签:
评论(0)
暂无评论
暂无评论
留言板