gpt4 book ai didi

http.Server Serve 方法在立即调用 Shutdown 时挂起

转载 作者:IT王子 更新时间:2023-10-29 01:41:22 30 4
gpt4 key购买 nike

我对 Go 的 http.Server 有问题,我将其嵌入到一个应该控制服务器启动和关闭的结构中。该结构如下所示:

type HTTPListen struct {
Consumers []pipeline.Consumer
Cfg HTTPListenConfig
Srv *http.Server
Logger log.Logger
wg *sync.WaitGroup
mu sync.Mutex
state State
}

问题是,在我的测试代码中,我调用了我的结构的 Start() 方法(它又在 http.Server 上运行 Serve() 方法) ,检查几个变量,然后调用 Stop(),关闭服务器,然后等待 http.Server 退出(返回 err 来自 Serve() 方法。

现在,由于某种原因,当我尝试在启动后立即关闭服务器时,Serve() 方法似乎只是卡在 WaitGroup.Wait() 上.当我添加一个短暂的暂停(尝试 100 毫秒),或者使用竞争检测器运行测试时,它工作得很好。

不确定这是否重要,但是在调用 Serve()Shutdown() 之间没有传入请求。

编辑: link to a playground minimal example .如果注释掉 time.Sleep 调用,程序将挂起。

两种方法的相关代码如下:

func (h *HTTPListen) Start() error {

h.Logger.Log("msg", "starting HTTPListen input")

addr := h.Cfg.ListenAddr
ln, err := net.Listen("tcp", addr)
if err != nil {
h.Logger.Log("msg", "failed to create listener on tcp/"+addr+": "+err.Error())
h.setState(StateFailed)
return err
}

h.wg.Add(1)
go func() {

defer h.wg.Done()
err := h.Srv.Serve(ln)
h.Logger.Log("msg", "HTTP server stopped: "+err.Error())

}()

h.setState(StateStarted)
h.Logger.Log("msg", "HTTPListen input started")

return nil

}

停止方法:

func (h *HTTPListen) Stop() error {

h.Logger.Log("msg", "stopping HTTPListen input")

ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()

if err := h.Srv.Shutdown(ctx); err != nil {
h.Logger.Log("msg", "HTTP server shutdown deadline expired")
}

h.wg.Wait()

h.setState(StateStopped)
h.Logger.Log("msg", "HTTPListen input stopped")

return nil
}

日志输出:

kwz@cyclone ~/s/stblogd> go test -v ./pkg/pipeline/input/ -run TestHTTPListen_StartStop
=== RUN TestHTTPListen_StartStop
msg="starting HTTPListen input"
msg="HTTPListen input started"
msg="stopping HTTPListen input"
... hangs indefinitely

使用竞争检测器运行测试时的日志输出:

kwz@cyclone ~/s/stblogd> go test -race -v ./pkg/pipeline/input/ -run TestHTTPListen_StartStop
=== RUN TestHTTPListen_StartStop
msg="starting HTTPListen input"
msg="HTTPListen input started"
msg="stopping HTTPListen input"
msg="HTTP server stopped: http: Server closed"
msg="HTTPListen input stopped"
--- PASS: TestHTTPListen_StartStop (0.00s)
PASS
ok stblogd/pkg/pipeline/input 1.007s

我很想对测试进行短暂的延迟,然后结束测试,但我想知道为什么它会这样。

最佳答案

这是一个已知问题,请参阅此线程:

https://github.com/golang/go/issues/20239

希望他们能尽快修复它,但现在听起来在你的测试中添加一个短暂的延迟是最简单的解决方案——它可能不会在现实世界中使用太多,因为你不会在这么短的时间内触发关机开始。

关于http.Server Serve 方法在立即调用 Shutdown 时挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45751869/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com