我有一个运行基本 HTTP 服务器并接受 TCP 连接的应用程序。
基本伪代码如下:
package main
import (
"log"
"net"
"net/http"
)
func main() {
// create serve HTTP server.
serveSvr := http.NewServeMux()
serveSvr.HandleFunc("/", handler())
// create server error channel
svrErr := make(chan error)
// start HTTP server.
go func() {
svrErr <- http.ListenAndServe(":8080", serveSvr)
}()
// start TCP server
go func() {
lnr, err := net.Listen("tcp", ":1111")
if err != nil {
svrErr <- err
return
}
defer lnr.Close()
for {
conn, err := lnr.Accept()
if err != nil {
log.Printf("connection error: %v", err)
continue
}
// code to handle each connection
}
}()
select {
case err := <-svrErr:
log.Print(err)
}
}
我在单独的 goroutine 中运行两个服务器,我需要一种方法来在其中一个失败时优雅地关闭它们。例如;如果 HTTP 服务器出错,我该如何返回并关闭 TCP 服务器/执行任何清理工作?
最佳答案
首先保留对 http 服务器和 tcp 监听器的引用,以便您稍后可以关闭它们。
创建单独的错误 channel ,以便您知道哪个路径返回了错误,并对它们进行缓冲,以便发送始终可以完成。
要确保在退出之前完成您想要尝试的任何清理,您可以将 WaitGroup 添加到服务器 goroutines。
我对你的例子的简单扩展可能是这样的:
var wg sync.WaitGroup
// create HTTP server.
serveSvr := http.NewServeMux()
serveSvr.HandleFunc("/", handler())
server := &http.Server{Addr: ":8080", Handler: serveSvr}
// create http server error channel
httpErr := make(chan error, 1)
// start HTTP server.
wg.Add(1)
go func() {
defer wg.Done()
httpErr <- server.ListenAndServe()
// http cleanup
}()
tcpErr := make(chan error, 1)
listener, err := net.Listen("tcp", ":1111")
if err != nil {
tcpErr <- err
} else {
// start TCP server
wg.Add(1)
go func() {
defer wg.Done()
defer listener.Close()
for {
conn, err := listener.Accept()
if err != nil {
if ne, ok := err.(net.Error); ok && ne.Temporary() {
// temp error, wait and continue
continue
}
tcpErr <- err
// cleanup TCP
return
}
// code to handle each connection
}
}()
}
select {
case err := <-httpErr:
// handle http error and close tcp listen
if listener != nil {
listener.Close()
}
case err := <-tcpErr:
// handle tcp error and close http server
server.Close()
}
// you may also want to receive the error from the server
// you shutdown to log
// wait for any final cleanup to finish
wg.Wait()
关于http - 优雅地关闭多台服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43473411/