什么是流式回复
在http中,流式回复(Streaming Response)是一种服务器向客户端连续发送一系列消息的通信模式。这种模式特别适用于数据量大或数据生成是连续的场景,例如实时数据传输、大文件传输、实时事件通知等。流式回复可以提高数据传输的效率,减少等待时间,并允许客户端逐步处理接收到的数据,而不是等待所有数据一次性到达。
简单来说就是像人一下,一个字一个字的说。
简单例子
package main
import (
"encoding/json"
"fmt"
"net/http"
)
func helloHandler(w http.ResponseWriter, r *http.Request) {
// 开启一个雨刷器
flusher := w.(http.Flusher)
data := "我是第一"
jsonByte, _ := json.Marshal(data)
if _, err := fmt.Fprintf(w, "event: %s\ndata: %s\n\n", "error", string(jsonByte)); err != nil {
_, _ = fmt.Fprintf(w, "event: %s\ndata: %s\n\n", "error", err)
return
}
//将缓冲区的数据发送给客户端
flusher.Flush()
data = "我是第二"
jsonByte, _ = json.Marshal(data)
if _, err := fmt.Fprintf(w, "event: %s\ndata: %s\n\n", "error", string(jsonByte)); err != nil {
_, _ = fmt.Fprintf(w, "event: %s\ndata: %s\n\n", "error", err)
return
}
flusher.Flush()
return
}
func main() {
http.HandleFunc("/", helloHandler)
fmt.Println("Server is running at http://localhost:8080/")
if err := http.ListenAndServe(":8080", nil); err != nil {
fmt.Println("Failed to start server:", err)
}
}
刷新器接口由 ResponseWriters 实现,它允许 HTTP 处理程序将缓冲数据刷新到客户端。
默认的 HTTP/ 1.x 和 HTTP/ 2 ResponseWriter 实现支持刷新器,但 ResponseWriter 包装器可能不支持。处理程序应始终在运行时测试此功能。
请注意,即使对于支持 Flush 的 ResponseWriter,如果客户端通过 HTTP 代理连接,则缓冲的数据在响应完成之前可能不会到达客户端。
如何工作的
-
设置响应格式:你的代码中使用了 fmt.Fprintf 来格式化发送给客户端的数据。这里使用了SSE的标准格式,即每个事件以 event: 开头,后跟 data: 和实际的数据内容,最后以两个换行符结束。
-
发送数据:你的代码中发送了两次数据,每次发送前都将数据转换为JSON格式,并通过 fmt.Fprintf 写入到响应中。
-
立即刷新:通过 flusher.Flush() 立即将缓冲区的数据发送给客户端,使得客户端可以即时接收并处理这些数据。