12.10.2 服务端设置超时时间

在这小节,您将学习如何在服务端超时连接。您需要这样做,因为有时客户端结束 HTTP 连接的时间比预期的要长得多。这通常由于俩个原因而发生:第一个原因是客户端软件有 bug,第二个原因是服务进程正经历攻击!

serverTimeOut.go 源码文件中实现了这个技巧,并分四部分介绍。

serverTimeOut.go 的第一部分如下:

package main

import (
    "fmt"
    "net/http"
    "os"
    "time"
)

func myHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Serving: %s\n", r.URL.Path)
    fmt.Fprintf("Served: %s\n", r.Host)
}

serverTimeOut.go 的第二部分代码如下:

func timeHandler(w http.ResponseWriter, r *http.Request) {
    t := time.Now().Format(time.RFC1123)
    Body := "The current time is:"
    fmt.Fprintf(w, "<h1 align=\"center\">%s</h1>", Body)
    fmt.Fprintf(w, "<h2 align=\"center\">%s</h2>n", t)
    fmt.Fprintf(w, "Serving: %s\n", r.URL.Path)
    fmt.Printf("Served time for :%s\n", r.Host)
}

serverTimeOut.go 的第三段代码如下:

func main() {
    PORT := ":8001"
    arguments := os.Args
    if len(arguments) == 1 {
        fmt.Printf("Listening on http://0.0.0.0%s\n", PORT)
    } else {
        PORT = ":" + arguments[1]
        fmt.Printf("Listening on http://0.0.0.0%s\n", PORT)
    }

    m := http.NewServeMux()
    srv := &http.Server {
        Addr: PORT,
        Handler: m,
        ReadTimeout: 3 * time.Second,
        WriteTimeout: 3 * time.Second,
    }

在这个例子中,我们使用 http.Server 结构, 它的字段支持两类超时。第一个叫 ReadTimeout,第二个叫 WriteTimeoutReadTimeout 字段的值定义读取整个请求,包括消息体的最大持续时间。

WriteTimeout 字段的值定义超时写入响应之前的最大持续时间。简单说,这是从请求头读取结束到响应写入结束的时间。

serverTimeOut.go 的剩余代码如下:

    m.HandleFunc("/time". timeHandler)
    m.HandleFunc("/", myHandler)

    err := srv.ListenAndServe()
    if err != nil {
        fmt.Println(err)
        return
    }
}

我们现在执行 serverTimeOut.go,使用 nc(1) 与之交互。

$ go run serverTimeOut.go
Listening on http://0.0.0.0:8001

nc(1) 部分(在这个例子中作为一个虚拟 HTTP 客户端),您应该发出下一个命令来连接到 serverTimeOut.go :

$ time nc localhost 8001

real 0m3.012s
user 0m0.001s
sys  0m0.002s

由于我们没有发出任何命令,HTTP 服务器结束了连接。time(1) 程序的输出验证了服务器关闭连接所用时间。

Last updated