SSE流式响应遇到的问题记录

  • 给定的接口是POST请求,请求时需要携带参数

解决方案:

使用@microsoft/fetch-event-source这个库中的fetchEventSource来发送带请求体的POST请求。示例代码:

import { fetchEventSource } from '@microsoft/fetch-event-source';


    const handleSubmit = async () => {
        //提交之前将机器人上次回答内容存储到消息列表中
        if (text.length > 0) {
            setMessages((prevMessages) => [...prevMessages, { sender: 'chatbot', text: text.join('') }]);
            setText([]);
        }
        if (inputValue.length === 0) {
            return message.error('请输入您的问题!')
        }
        setLoading(true);
        setMessages((prevMessages) => [...prevMessages, { sender: 'You', text: inputValue }]);
        fetchEventSource('/chatapi/chat/chat',
            {
                method: 'POST',
                withCredentials: true,
                headers: {
                    "Content-Type": 'application/json',
                },
                body: JSON.stringify({
                    "query": inputValue,
                    "conversation_id": "",
                    "history_len": -1,
                    "history": messages.length > 1 ? messages.slice(-2).map((item) => {
                        return {
                            'role': item.sender === 'chatbot' ? 'assistant' : 'user',
                            'content': item.text
                        }
                    }) : [],
                    "stream": true,
                    "model_name": "chatglm3-6b",
                    "temperature": 0.7,
                    "max_tokens": 0,
                    "prompt_name": "default"
                }),
                async onopen(response) {
                    console.log('open');
                },
                async onmessage(event) {
                    // console.log(event.data);
                    setText(revMessages => [...revMessages, parseJsonWithNumberValidation(event.data).text])
                },
                onerror(error) {
                    console.info(error);
                    setSysMsg(error)
                },
                onclose() {
                    console.log('close');
                    setInputValue('');
                    setLoading(false);
                }
            }
        )
    };

参考:https://www.cnblogs.com/HTLucky/p/17326459.html

  • 直接请求服务接口能够正常流式响应,中间经过1层或多层代理之后,无法流式响应,而是一次性将响应结果给到前端。

解决方案:

配置nginx代理,支持SSE

http {
    ...

    server {
        ...

        location /sse {
            proxy_http_version 1.1;
            proxy_set_header Connection "";
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

            # SSE 连接时的超时时间
            proxy_read_timeout 86400s;
            
            # 取消缓冲
            proxy_buffering off;

            # 关闭代理缓存
            proxy_cache off;
            
            # 禁用分块传输编码
            chunked_transfer_encoding on;
            
            # 反向代理到 SSE 应用的地址和端口
            proxy_pass http://backend-server;
        }

        ...
    }

    ...
}

  • 如果中间经过了N层代理,有WAF或者CDN这些时,将所有代理的请求头添加上

X-Accel-Buffering 这个参数值是no。我的理解是只有请求真实接口的那一层代理不用加这个参数,前面的N-1层代理都需要添加上这个参数。

  location /path {
      ...
      add_header X-Accel-Buffering "no";
      ...
  }

问题类型如同:https://github.com/chatchat-space/Langchain-Chatchat/issues/1712

参考:解决SSE流被Nginx缓存的问题_nginx sse-CSDN博客

  • 关于X-Accel-Buffering参数的解释:

`X-Accel-Buffering` 是一个特殊的请求头参数,用于控制反向代理服务器(如Nginx)与后端服务器之间的数据缓冲行为。

当客户端发送请求到反向代理服务器时,反向代理服务器会将请求转发至后端服务器处理,并将后端服务器返回的响应传递给客户端。在这个过程中,反向代理服务器可以选择是否缓冲响应数据。

`X-Accel-Buffering` 请求头参数用于向反向代理服务器传递缓冲设置指令,具体含义如下:

- 如果 `X-Accel-Buffering` 的值为 "yes",表示反向代理服务器应该启用缓冲,将响应数据完全接收后再传递给客户端。这样可以提高性能,特别是对于大型响应或响应时间较长的情况。

- 如果 `X-Accel-Buffering` 的值为 "no",表示反向代理服务器应禁用缓冲,即实时将后端服务器返回的数据传递给客户端。这对于实时性要求较高的应用场景可能更为合适。

需要注意的是,`X-Accel-Buffering` 请求头参数的作用需要在反向代理服务器的配置中进行解释和生效。例如,在 Nginx 中,可以通过配置 `proxy_buffering` 指令来控制缓冲行为,并根据 `X-Accel-Buffering` 的值进行相应的设置。

总结起来,`X-Accel-Buffering` 请求头参数用于指示反向代理服务器是否缓冲响应数据,提供更好的性能或实时性,具体行为取决于反向代理服务器的配置和实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值