服务端设置超时时间

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

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

serverTimeOut.go 的第一部分如下:

  1. package main
  2. import (
  3. "fmt"
  4. "net/http"
  5. "os"
  6. "time"
  7. )
  8. func myHandler(w http.ResponseWriter, r *http.Request) {
  9. fmt.Fprintf(w, "Serving: %s\n", r.URL.Path)
  10. fmt.Fprintf("Served: %s\n", r.Host)
  11. }

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

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

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

  1. func main() {
  2. PORT := ":8001"
  3. arguments := os.Args
  4. if len(arguments) == 1 {
  5. fmt.Printf("Listening on http://0.0.0.0%s\n", PORT)
  6. } else {
  7. PORT = ":" + arguments[1]
  8. fmt.Printf("Listening on http://0.0.0.0%s\n", PORT)
  9. }
  10. m := http.NewServeMux()
  11. srv := &http.Server {
  12. Addr: PORT,
  13. Handler: m,
  14. ReadTimeout: 3 * time.Second,
  15. WriteTimeout: 3 * time.Second,
  16. }

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

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

serverTimeOut.go 的剩余代码如下:

  1. m.HandleFunc("/time". timeHandler)
  2. m.HandleFunc("/", myHandler)
  3. err := srv.ListenAndServe()
  4. if err != nil {
  5. fmt.Println(err)
  6. return
  7. }
  8. }

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

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

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

  1. $ time nc localhost 8001
  2. real 0m3.012s
  3. user 0m0.001s
  4. sys 0m0.002s

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