Tab*_*ayi 5 tcp go server-timing
我有一个客户端和服务器。服务器处理请求超过2秒。但客户没有那么多时间。它需要在1秒内得到响应。这就是为什么它响应
获取“http://localhost:8888”:超出上下文截止时间(等待标头时超出 Client.Timeout)恐慌:运行时错误:无效的内存地址或 nil 指针取消引用
问题?如何更改 server.go 以便正确恢复所有错误并且端点始终可用? 请注意,客户端调用的端点应尽快处理请求,并在完成后立即返回 200 OK。
客户端.go
package main
import (
"fmt"
"log"
"net/http"
"time"
)
func main() {
c := &http.Client{Timeout: 2 * time.Second}
res, err := c.Get("http://localhost:8888")
if err != nil {
log.Println(err)
}
var r []byte
_, err = res.Body.Read(r)
fmt.Println(string(r))
}
Run Code Online (Sandbox Code Playgroud)
服务器.go
package main
import (
"fmt"
"io"
"net/http"
"time"
)
func slowHandler(w http.ResponseWriter, req *http.Request) {
time.Sleep(2 * time.Second)
io.WriteString(w, "I am slow!\n")
}
func main() {
srv := http.Server{
Addr: ":8888",
Handler: http.HandlerFunc(slowHandler),
}
if err := srv.ListenAndServe(); err != nil {
fmt.Printf("Server failed: %s\n", err)
}
}
Run Code Online (Sandbox Code Playgroud)
您可以通过实现恢复中间件来从恐慌中恢复,例如:
defer func() {
if err := recover(); err != nil {
log.Println("recovered from panic", err)
fmt.Fprintf(w, "recovered from panic")
}
}()
Run Code Online (Sandbox Code Playgroud)
您可以使用这篇有用的文章作为指南https://www.nicolasmerouze.com/middlewares-golang-best-practices-examples
编辑
您可以创建自定义中间件来处理自定义处理程序超时
func timeOutMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
done := make(chan bool)
ctx, cancelFunc := context.WithTimeout(r.Context(), time.Second*1)
defer cancelFunc()
go func() {
next.ServeHTTP(w, r)
close(done)
}()
select {
case <-done:
return
case <-ctx.Done():
w.WriteHeader(http.StatusOK)
w.Write([]byte(`{"message": "handled time out"}`))
}
})
}
Run Code Online (Sandbox Code Playgroud)
为了使其工作,您需要与客户端同步,因为如果客户端设置较低的超时,那么将永远不会得到正确的响应,或者在服务器设置非常低的超时的情况下,这也可能发生。
还要完全读取响应字节,请使用此
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
Run Code Online (Sandbox Code Playgroud)