Golang反向代理中流传输正常但刷新功能失效问题

Golang反向代理中流传输正常但刷新功能失效问题 内容类型:[text/event-stream]

效果与未使用 re.flush 时相同,大约缓冲200字节后才发送给客户端,看起来是每3秒刷新一次。以下是代码,我该如何让它每50毫秒刷新一次?

for i := 0; i < 100; i++ {
    io.Copy(mw, originServerResponse.Body)
    err := rc.Flush()
    if err != nil {
        fmt.Println(err)
    }
    time.Sleep(50 * time.Millisecond)
}

更多关于Golang反向代理中流传输正常但刷新功能失效问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

为什么不尝试添加一个缓冲区层呢?将50毫秒内需要的数据放入缓冲区,然后一次性发送。

bs := new(bytes.Buffer) // 替换为一个大小受限的缓冲区 !!!
	go func() {
		// 做一些操作...
		_, _ = io.Copy(bs, originServerResponse.Body)
	}()
	tr := time.NewTicker(50 * time.Millisecond) // 如果使用定时器,记得重置
	for {
		// 如果有上下文,使用 select
		<-tr.C
		_, _ = io.Copy(rc, bs)
		rc.Flush()
	}

更多关于Golang反向代理中流传输正常但刷新功能失效问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在反向代理流传输中,rc.Flush() 可能无法正常工作,因为 io.Copy 会持续读取直到遇到错误或 EOF。对于 text/event-stream,你需要逐行或分块读取并手动刷新。以下是修改后的代码示例:

// 使用 bufio.Scanner 逐行读取并刷新
scanner := bufio.NewScanner(originServerResponse.Body)
for scanner.Scan() {
    line := scanner.Bytes()
    mw.Write(line)
    mw.Write([]byte("\n"))
    
    // 强制刷新到客户端
    if f, ok := mw.(http.Flusher); ok {
        f.Flush()
    }
    
    time.Sleep(50 * time.Millisecond)
}

if err := scanner.Err(); err != nil {
    fmt.Println("读取错误:", err)
}

或者使用固定缓冲区大小读取:

// 设置较小的缓冲区实现更频繁的刷新
buf := make([]byte, 32) // 32字节缓冲区
for {
    n, err := originServerResponse.Body.Read(buf)
    if n > 0 {
        mw.Write(buf[:n])
        
        // 立即刷新
        if f, ok := mw.(http.Flusher); ok {
            f.Flush()
        }
    }
    
    if err != nil {
        if err != io.EOF {
            fmt.Println("读取错误:", err)
        }
        break
    }
    
    time.Sleep(50 * time.Millisecond)
}

确保你的 ResponseWriter 实现了 http.Flusher 接口:

type MyResponseWriter struct {
    http.ResponseWriter
}

func (mrw *MyResponseWriter) Write(p []byte) (int, error) {
    n, err := mrw.ResponseWriter.Write(p)
    if flusher, ok := mrw.ResponseWriter.(http.Flusher); ok {
        flusher.Flush()
    }
    return n, err
}

然后在处理器中使用:

func handler(w http.ResponseWriter, r *http.Request) {
    mrw := &MyResponseWriter{ResponseWriter: w}
    // 使用 mrw 进行后续操作
}

这些修改可以确保数据每50毫秒刷新一次,而不是等待缓冲区填满。

回到顶部