Golang1.8.1:TimeoutHandler不影响多路复用器。

huangapple go评论91阅读模式
英文:

Golang1.8.1: TimeoutHandler doesn't affect multiplexer

问题

我有这段代码,它将http/s请求重定向到登录页面,除了TimeoutHandler没有效果,我的意思是会话在3秒后不会超时:

func main() {
    mux := http.NewServeMux()
    rh := http.RedirectHandler("http://10.130.0.10:820/login", 307)
    mux.Handle("/", rh)
    tmux := http.TimeoutHandler(mux, time.Second*3, "Timeout!")
    go http.ListenAndServe("10.130.0.10:818", tmux)
    go http.ListenAndServeTLS("10.130.0.10:821", "server.pem", "server.key", tmux)
    var input string
    fmt.Scanln(&input)
    fmt.Println("done")
}

任何建议都将不胜感激。

英文:

I have this code which redirect http/s requests to login page, it works except TimeoutHandler has no effect, I mean the sessions don't timeout after 3 seconds:

func main(){

        mux := http.NewServeMux()
        rh := http.RedirectHandler("http://10.130.0.10:820/login", 307)
        mux.Handle("/", rh)
        tmux := http.TimeoutHandler(mux, time.Second*3, "Timeout!")
        go http.ListenAndServe("10.130.0.10:818", tmux)
        go http.ListenAndServeTLS("10.130.0.10:821", "server.pem", "server.key", tmux)
        var input string
        fmt.Scanln(&input)
        fmt.Println("done")
}

any advice will be appreciated.

答案1

得分: 0

http.TimeoutHandler并不用于在一定时间后使会话过期。相反,它用于限制处理程序的执行时间,即如果给定的时间已过,它将向HTTP客户端返回503 Service Unavailable。以下是一个示例:

func handlerNoTimeout(w http.ResponseWriter, r *http.Request) {
    // 这个处理程序需要1秒钟才能完成,不会超时
    time.Sleep(1 * time.Second)
    w.Write([]byte("处理程序正常"))
}

func handlerTimeout(w http.ResponseWriter, r *http.Request) {
    // 这个处理程序需要4秒钟才能完成。
    // 在完成之前,它将超时,
    // 将向客户端发送503响应+给定的消息(即Timeout!)
    time.Sleep(4 * time.Second)
    w.Write([]byte("处理程序超时(永远不会执行)"))
}

func main() {

    mux := http.NewServeMux()
    rh := http.RedirectHandler("http://10.130.0.10:820/login", 307)
    mux.Handle("/", rh)
    mux.HandleFunc("/timeout", handlerTimeout)
    mux.HandleFunc("/notimeout", handlerNoTimeout)
    tmux := http.TimeoutHandler(mux, time.Second*3, "超时!")
    go http.ListenAndServe(":818", tmux)
    go http.ListenAndServeTLS(":821", "server.pem", "server.key", tmux)
    var input string
    fmt.Scanln(&input)
    fmt.Println("完成")
}

如果访问/timeout,您将得到带有超时消息的503,但如果访问/notimeout,HTTP响应将是200 OK

会话是由服务器存储的状态,而不是需要时间完成的处理步骤/任务/作业。除非您在后台定义一个函数/方法/处理程序,定期监视会话创建时间,并且如果给定的时间过去,将其标记为过期,否则会话不会过期。

在您的代码中,如果重定向处理程序(即登录处理程序)需要超过3秒钟,它将超时。

英文:

The http.TimeoutHandler is not for making session expired after a certain time. Instead, it's used to limit execution time of a handler, i.e. if given time is elapsed, it will return 503 Service Unavailable to HTTP client. Below is an example of such usage:

func handlerNoTimeout(w http.ResponseWriter, r *http.Request) {
    //This handler takes 1 second to finished, won't timeout
    time.Sleep(1 * time.Second)
    w.Write([]byte("Handler OK"))
}

func handlerTimeout(w http.ResponseWriter, r *http.Request) {
    //This handler takes 4 seconds to finished.
    //Before finished, it will timeout, 
    //503 response will be sent to client + given message (i.e. Timeout!)
    time.Sleep(4 * time.Second)
    w.Write([]byte("Handler timeout (never executed)"))
}

func main() {

    mux := http.NewServeMux()
    rh := http.RedirectHandler("http://10.130.0.10:820/login", 307)
    mux.Handle("/", rh)
    mux.HandleFunc("/timeout", handlerTimeout)
    mux.HandleFunc("/notimeout", handlerNoTimeout)
    tmux := http.TimeoutHandler(mux, time.Second*3, "Timeout!")
    go http.ListenAndServe(":818", tmux)
    go http.ListenAndServeTLS(":821", "server.pem", "server.key", tmux)
    var input string
    fmt.Scanln(&input)
    fmt.Println("done")
}

If your access /timeout, you will get 503 with timeout message, but if you access /notimeout, the http response will be 200 OK.

A session is a state stored by the server, not a processing steps/task/job which may needs time to finish. A session won't expired unless you define a function/method/handler in background, watch the session creation time regularly, and if given time elapsed, mark it as expired.

In your code, it will timeout if redirect handler (i.e. login handler) needs more than 3 seconds.

答案2

得分: 0

我搞清楚了,我必须使用ReadTimeout和WriteTimeout,这里是一个可工作的示例。

func main() {
    mux := http.NewServeMux()
    rh := http.RedirectHandler("http://10.103.0.10:8020/login", 307)
    mux.Handle("/", rh)
    s := &http.Server{
        Addr:         "10.103.0.10:818",
        Handler:      mux,
        ReadTimeout:  5 * time.Second,
        WriteTimeout: 5 * time.Second,
    }
    ss := &http.Server{
        Addr:         "10.103.0.10:821",
        Handler:      mux,
        ReadTimeout:  5 * time.Second,
        WriteTimeout: 5 * time.Second,
    }
    go s.ListenAndServe()
    go ss.ListenAndServeTLS("server.pem", "server.key")

    var input string
    fmt.Scanln(&input)
    fmt.Println("done")
}

谢谢。

英文:

I figured it out, I had to use ReadTimeout and WriteTimeout instead, here is a working example.

func main(){
        mux := http.NewServeMux()
        rh := http.RedirectHandler("http://10.103.0.10:8020/login", 307)
        mux.Handle("/", rh)
        s := &http.Server{
	        Addr:		"10.103.0.10:818",
	        Handler:        mux,
	        ReadTimeout:    5 * time.Second,
	        WriteTimeout:   5 * time.Second,
        }
        ss := &http.Server{
	        Addr:		"10.103.0.10:821",
	        Handler:        mux,
	        ReadTimeout:    5 * time.Second,
	        WriteTimeout:   5 * time.Second,
        }
        go s.ListenAndServe()
        go ss.ListenAndServeTLS("server.pem", "server.key")

        var input string
        fmt.Scanln(&input)
        fmt.Println("done")
    }

Thank you.

huangapple
  • 本文由 发表于 2017年5月29日 16:43:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/44238153.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定