Go 防止超过上下文截止时间(等待标头时超过Client.Timeout)HTTP 200 OK错误

Go 防止超过上下文截止时间(等待标头时超过Client.Timeout)HTTP 200 OK错误,go,tcp,server-timing,Go,Tcp,Server Timing,我有一个客户端和服务器。服务器处理请求的时间超过2秒。但客户并没有这么多时间。它需要在1秒内得到响应。这就是为什么它的反应是 得到“http://localhost:8888“:超出上下文截止日期(等待标头时超出Client.Timeout) 死机:运行时错误:无效内存地址或零指针取消引用 问题? 如何更改server.go以正确恢复所有错误 端点始终可用吗? 注意客户端正在调用的端点应尽快处理请求,并在完成后立即返回200 OK 客户机,开始 package main import (

我有一个客户端和服务器。服务器处理请求的时间超过2秒。但客户并没有这么多时间。它需要在1秒内得到响应。这就是为什么它的反应是

得到“http://localhost:8888“:超出上下文截止日期(等待标头时超出Client.Timeout) 死机:运行时错误:无效内存地址或零指针取消引用

问题? 如何更改server.go以正确恢复所有错误 端点始终可用吗? 注意客户端正在调用的端点应尽快处理请求,并在完成后立即返回200 OK

客户机,开始

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))
}
server.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)
    }
}

您可以通过实施恢复中间件从恐慌中恢复,例如:

defer func(){
如果错误:=recover();错误!=nil{
Println(“从恐慌中恢复”,错误)
fmt.Fprintf(w,“从恐慌中恢复”)
}
}()
您可以使用这篇有用的文章作为指导

编辑

您可以创建自定义中间件来处理自定义处理程序超时

func timeOutMiddleware(下一个http.Handler)http.Handler{
返回http.HandlerFunc(func(w http.ResponseWriter,r*http.Request){
完成:=制作(陈波)
ctx,cancelFunc:=context.WithTimeout(r.context(),time.Second*1)
延迟取消func()
go func(){
next.ServeHTTP(w,r)
结束(完成)
}()
挑选{

case通过实现恢复中间件,您可以从恐慌中恢复,例如:

defer func(){
如果错误:=recover();错误!=nil{
Println(“从恐慌中恢复”,错误)
fmt.Fprintf(w,“从恐慌中恢复”)
}
}()
您可以使用这篇有用的文章作为指导

编辑

您可以创建自定义中间件来处理自定义处理程序超时

func timeOutMiddleware(下一个http.Handler)http.Handler{
返回http.HandlerFunc(func(w http.ResponseWriter,r*http.Request){
完成:=制作(陈波)
ctx,cancelFunc:=context.WithTimeout(r.context(),time.Second*1)
延迟取消func()
go func(){
next.ServeHTTP(w,r)
结束(完成)
}()
挑选{

案例啊,我的错,不是服务器恐慌是客户端,因为您正在读取一个由于超时而产生的nil响应,在您的示例中,客户端从未从服务器获得响应,因此,r是nil和恐慌。现在可以做两件事:-客户端错误处理
如果出错,ok:=err.(net.error);ok&&err.timeout(){
-服务器处理程序超时
处理程序:http.TimeoutHandler(http.HandlerFunc(slowHandler),1*time.Second,“我超时!\n”),
此服务将返回503,但超时完成后将立即返回。让我们假设此服务是公共服务,它需要不可预测的时间,并且可能有许多客户端。有些客户端可以再分配1秒。在这种情况下,您的代码不起作用,我不确定您所说的是否可能,这是我唯一能想到的about out是在请求中接收一个参数/头,然后根据该参数调整上下文超时,否则您无法知道客户端超时设置是什么。不幸的是,您无法从请求头中获取客户端超时。我的意思是客户端在处理之前需要知道的自定义头/参数,这不是服务器死机king是客户机,因为由于超时,您正在读取一个nil响应,在您的示例中,客户机从未从服务器获得响应,因此,r是nil和panic。现在您可以做两件事:-客户机错误处理
如果出错,ok:=err.(net.error);ok&&err.timeout(){
-服务器处理程序超时
处理程序:http.TimeoutHandler(http.HandlerFunc(slowHandler),1*time.Second,“我超时!\n”),
此服务将返回503,但超时完成后将立即返回。让我们假设此服务是公共服务,它需要不可预测的时间,并且可能有许多客户端。有些客户端可以再分配1秒。在这种情况下,您的代码不起作用,我不确定您所说的是否可能,这是我唯一能想到的about out是在请求中接收一个参数/头,然后根据该参数调整上下文超时,否则您无法知道客户端超时设置是什么。不幸的是,您无法从请求头获取客户端超时。我指的是客户端需要事先知道的自定义头/参数