HTTP服务器读取 - 写入超时和服务器端事件

问题描述 投票:0回答:3

server := &http.Server{Addr: addr, ReadTimeout: 10 * time.Second, WriteTimeout: 10 * time.Second, Handler: s.mainHandler(), }

Handler:

func sseHandler(w http.ResponseWriter, r *http.Requests) { f, ok := w.(http.Flusher) if !ok { http.Error(w, "Streaming not supported!", http.StatusInternalServerError) log.Println("Streaming not supported") return } messageChannel := make(chan string) hub.addClient <- messageChannel notify := w.(http.CloseNotifier).CloseNotify() w.Header().Set("Content-Type", "text/event-stream") w.Header().Set("Cache-Control", "no-cache") w.Header().Set("Connection", "keep-alive") for i := 0; i < 1440; { select { case msg := <-messageChannel: jsonData, _ := json.Marshal(msg) str := string(jsonData) fmt.Fprintf(w, "data: {\"str\": %s, \"time\": \"%v\"}\n\n", str, time.Now()) f.Flush() case <-time.After(time.Second * 60): fmt.Fprintf(w, "data: {\"str\": \"No Data\"}\n\n") f.Flush() i++ case <-notify: f.Flush() i = 1440 hub.removeClient <- messageChannel } } }

	

ReadTimeout
定义必须从中读取或写回客户的整个请求的持续时间。这些超时适用于基础连接(
http://golang.org/src/pkg/net/http/http/server.go?s = 15704:15902
go
3个回答
5
投票
提出这一点,如果您每个请求需要自定义超时,则需要在处理程序中实现它们。在您的代码中,您已经在使用超时来完成工作,因此这是在处理程序开始时创建一个

WriteTimeout

,继续检查(在处理程序本身,甚至通过它传递)并在必要时停止请求。这实际上使您可以更精确地控制超时,因为
time.After
只有在尝试编写响应时才会触发(例如,如果将超时设置为10秒,并且需要一分钟的时间才能准备响应,那么在任何写入之前,您都不会遇到任何错误,直到完成作业后,您将浪费资源50秒钟)。从这个角度来看,我认为只有当您的响应准备很快就准备就绪时,我认为
WriteTimeout本身是好的,但是当网络变得非常慢时(或客户故意停止接收数据)时,您希望脱离连接。 在库中有一个小的辅助功能,它的行为与

WriteTimeout

相似,但是如果响应花费比预定义的时间更长的情况,则会寄回503错误。您可以使用它来设置类似于每个处理程序类似的行为,例如:

http.TimeoutHandler
这个看起来非常方便,但是我发现一个会影响您的代码的缺点:
WriteTimeout

WriteTimeout

通过package main import ( "log" "net/http" "time" ) type Handler struct { } func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { time.Sleep(3*time.Second) // This will return http.ErrHandlerTimeout log.Println(w.Write([]byte("body"))) } func main() { h := &Handler{} http.Handle("/t1", http.TimeoutHandler(h, 1*time.Second, "")) http.Handle("/t2", http.TimeoutHandler(h, 2*time.Second, "")) http.ListenAndServe(":8080", nil) }

没有实现。如果需要的话,您可以深入研究the the the the the the the the the the tumplentation
如何解决超时问题,以提出类似但增强的解决方案。
HTTP处理程序的超时时间是按服务器指定的:
http.ResponseWriter

http.TimeoutHandler
。 GO
http.CloseNotifier

之后,

HTTP响应troller
提供了对
ReadTimeout
接口未处理的扩展每个重新要求功能的访问。
响应式控制器类型提供了一种更清晰,更可发现的添加perhandler控件的方法。 GO 1.20中还添加了两个这样的控件是WriteTimeout


0
投票
,它们允许每次重新读取截止日期。

样本
http.ResponseWriter

您可以使用ResponseController重置截止日期。
代码更改的列表将为

在for循环之前初始化响应控制器。 SetReadDeadline


在冲洗之前,block block,用代码段重置写入截止日期

SetWriteDeadline

注:您也可以用响应控制器冲洗而不是初始化单独的冲洗器。 

0
投票
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.