http.Server ListenAndServer然后即时关机不起作用

时间:2017-07-22 15:23:29

标签: http go

我试图在一个更大的程序中追踪一个问题并写下这个小测试程序来帮助解决它。

如果我启动一个http服务器,然后立即尝试关闭它,它就不会关闭并继续提供请求。我可以推断这种行为,但不能解决这个问题。我假设它是因为服务器在我尝试将其关闭之前还没有完全启动,因此关机失败并且启动继续,然后完成让它正常处理请求。 / p>

如何确保服务器处于可以在关闭之前关闭的状态?如果您在启动和停止服务器之间注释掉睡眠功能,您将看到它按预期工作。

package main

import (
    "context"
    "fmt"
    "io"
    "log"
    "net/http"
    "os"
    "os/signal"
    "time"
)

func main() {
    // stop on ^c
    quit := make(chan os.Signal)
    signal.Notify(quit, os.Interrupt)

    // router
    mux := http.NewServeMux()
    mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Println("serving request")
        io.WriteString(w, "Hello, world!\n")
    })

    // start server
    srv := &http.Server{Addr: ":8080", Handler: mux}
    go func() {
        if err := srv.ListenAndServe(); err != nil {
            log.Printf("listenAndServe failed: %v", err)
        }
    }()
    fmt.Println("server started")

    // time.Sleep(1 * time.Second)

    // gracefully stop server
    d := time.Now().Add(60 * time.Second)
    ctx, cancel := context.WithDeadline(context.Background(), d)
    defer cancel()
    if err := srv.Shutdown(ctx); err != nil {
        fmt.Println(err)
    }
    fmt.Println("server stopped")

    <-quit
}

只需运行此程序并访问http://localhost:8080即可。即使我们试图将其关闭,您也会看到它会继续提供请求。

程序的输出应为:

:; go run main.go
server started
server stopped
2017/07/22 16:17:11 serve failed: http: Server closed

而不是:

:; go run main.go
server started
server stopped
serving request
serving request
serving request

1 个答案:

答案 0 :(得分:1)

srv.ListenAndServe之后,您srv.Shutdown的来电可能会被呼叫,而且显然是在srv.ListenAndServe之后呼叫。您可以通过在调用ListenAndServe之前添加goroutine的日志记录来验证这一点。要在time.Sleep(1 * time.Second)之后调用时查看关闭是否有效,您可以取消注释Shutdown<-quit的典型用法是在func main() { // stop on ^c quit := make(chan os.Signal) signal.Notify(quit, os.Interrupt) // router mux := http.NewServeMux() mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { log.Println("serving request") io.WriteString(w, "Hello, world!\n") }) // start server srv := &http.Server{Addr: ":8080", Handler: mux} go func() { log.Println("server starting") if err := srv.ListenAndServe(); err != nil { log.Fatalf("listenAndServe failed: %v", err) } }() fmt.Println("server started") <-quit // gracefully stop server ctx, cancel := context.WithTimeout(context.Background(), 60 * time.Second) defer cancel() if err := srv.Shutdown(ctx); err != nil { log.Fatal(err) } log.Println("server stopped") }

之后立即调用它
<tr ng-repeat="person in management.users | filter: searchFilter | limitTo: management.limit">
            <td>{{ person.name }}</td>
            <td>{{ person.username }}</td>
            <td>{{ person.email }}</td>
        </tr>