我是Go语言的新手。
我正在编写一个Web应用程序,我需要服务器等待活动请求发出后再关闭。
我写了一个处理程序,等待5秒钟回答。如果我发出请求并停止服务器(在5秒钟之前),则会收到“无法连接”错误。
有没有一种方法可以停止监听新请求并等待活动请求完成?
这是我的例子
func main() {
log.Infof("Starting (PID %d)...", os.Getpid())
stop := make(chan os.Signal, 1)
signal.Notify(stop, syscall.SIGTERM)
signal.Notify(stop, syscall.SIGINT)
listenAt := "127.0.0.1:8000"
r := newRouter()
h := &http.Server{Addr: listenAt, Handler: r}
go func() {
log.Info("Serving on http://", listenAt)
if err := h.ListenAndServe(); err != nil {
log.Fatal(err)
}
}()
<-stop
log.Info("Stoping ...")
h.Shutdown(context.Background())
log.Info("Bye :)")
}
示例处理程序
func handler(w http.ResponseWriter, r *http.Request) {
time.Sleep(5 * time.Second)
log.Info("new request")
fmt.Fprintf(w, "Hola!")
}
完整示例@ https://gist.github.com/nachopro/d80fa71ae49527e1ddcaf359b4ff488b
答案 0 :(得分:1)
感谢这个blog entry和他们的例子,我找到了这个issue和他们的solution。我看到我的问题与net / http模块无关!
真正的问题是log.Fatal(err)
中的go func()
,将其更改为log.Info(err)
不会中止关机过程。
go func() {
log.Info("Serving on http://", listenAt)
if err := h.ListenAndServe(); err != nil {
// log.Fatal(err)
log.Info(err)
}
}()
答案 1 :(得分:0)
一种方法是通过以下方式将最大连接数限制为1:
l, err := net.Listen("tcp", ":8000")
if err != nil {
log.Fatalf("Listen: %v", err)
}
defer l.Close()
l = netutil.LimitListener(l, 1)
log.Fatal(http.Serve(l, nil))
另一种方法是使用全局变量:
package main
import (
"net/http"
"sync/atomic"
"fmt"
)
var toggle *int32
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
func handler(w http.ResponseWriter, r *http.Request) {
val := atomic.LoadInt32(toggle)
if val != 0 {
fmt.Fprintln(w, "Not Valid!")
w.WriteHeader(http.StatusForbidden)
return
}
atomic.StoreInt32(toggle, 1)
// do stuff
w.WriteHeader(http.StatusOK)
}
func init (){
atomic.StoreInt32(toggle, int32(0))
}
**请注意,两种方法都适用于单节点服务器,不适用于分布式系统,为此,解决方案是使用Redis等缓存服务器。