go net/http:服务器的Shutdown()方法不够优雅,

mo49yndu  于 2个月前  发布在  Go
关注(0)|答案(8)|浏览(51)

Http服务器在关闭时注册的函数在goroutine中被调用。它将被进程结束中断。

8iwquhpp

8iwquhpp1#

你好,@chenjie199234,

这就是Go的工作方式。当main goroutine存在时,程序就完成了。主goroutine不会等待其他goroutine结束。一旦你在main函数中调用了<-done触发后的return,主函数将返回,而不关心其他goroutine(在这种情况下,是你的回调函数)是否还有工作要做。

如果你想让main等待其他goroutine完成后再退出,你需要使用某种形式的同步机制。

我关闭这个评论,因为这不是一个Go的bug。

6pp0gazn

6pp0gazn2#

@ALTree 我遇到了相同的问题,我不确定它是否应该被关闭。
问题是 http.Server.Shutdown() 在返回之前没有等待与 http.Server.RegisterOnShutdown 注册的函数完成:

func (srv *Server) Shutdown(ctx context.Context) error {
	atomic.StoreInt32(&srv.inShutdown, 1)

	srv.mu.Lock()
	lnerr := srv.closeListenersLocked()
	srv.closeDoneChanLocked()
	for _, f := range srv.onShutdown {
		go f()
	}
	srv.mu.Unlock()

	ticker := time.NewTicker(shutdownPollInterval)
	defer ticker.Stop()
	for {
		if srv.closeIdleConns() {
			return lnerr
		}
		select {
		case <-ctx.Done():
			return ctx.Err()
		case <-ticker.C:
		}
	}
}

即使这是 Shutdown() 的预期行为(我不确定)——而且我认为文档应该更新以警告您在 RegisterOnShutdown() 中注册的函数可能在 Shutdown() 返回之前无法完成。

xdnvmnnf

xdnvmnnf3#

即使这是Shutdown()的预期行为(我不确定),但它并不直观,我认为文档应该更新以警告您使用RegisterOnShutdown()注册的函数可能在Shutdown()返回之前无法完成。
这也说得过去;我将再次打开此问题进行进一步调查(并可能将其转换为文档问题)。

ljo96ir5

ljo96ir54#

CC @bradfitz@tombergan

fumotvh3

fumotvh35#

调用onShutdown函数时,使用goroutine和WaitGroup可能有效,但并不直观。

eqoofvh9

eqoofvh96#

这个问题有任何更新吗?

2fjabf4q

2fjabf4q7#

你好!我在浏览net/http中的代码时发现了这个问题。我尝试了一下并编写了一个快速修复,但可能太复杂了。有兴趣修复这个问题吗?这个问题适合志愿者(新人)解决吗?

bqjvbblv

bqjvbblv8#

这里有另一个问题,如果你调用两次Shutdown,回调函数将在一个新的goroutine中被调用两次。

相关问题