我试图在一个更大的程序中追踪一个问题并写下这个小测试程序来帮助解决它。
如果我启动一个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
答案 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>