我有一个结构:
type MultiServer struct {
servers []*http.Server
}
func New(servers ...*http.Server) *MultiServer {
return &MultiServer{servers: servers}
}
func (m *MultiServer) ListenAndServe() error {
var g errgroup.Group
for _, s := range m.servers {
s := s
g.Go(s.ListenAndServe)
}
return g.Wait()
}
我希望如果其中一台服务器返回错误,ListenAndServe
将立即返回。因此,我将错误的端口传递给其中一台服务器:
func TestListenAndServe(t *testing.T) {
one := makeServer(":8080")
two := makeServer("::8080") // that is incorrect port
ms := New(one, two)
done := make(chan error)
go func() {
done <- ms.ListenAndServe()
}()
select {
case err := <-done:
if err == nil {
t.Fatal("error expected")
}
case <-makeTimeChan(5 * time.Second):
t.Fatal("timeout")
}
}
func makeServer(port string) *http.Server {
serveMux := http.NewServeMux()
hello := func(w http.ResponseWriter, req *http.Request) {
fmt.Fprintf(w, "hello\n")
}
serveMux.HandleFunc("/hello", hello)
return &http.Server{
Addr: port,
Handler: serveMux,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
}
}
func makeTimeChan(d time.Duration) <-chan time.Time {
t := time.NewTimer(d)
return t.C
}
如果我的MultiServer具有不止一台服务器,我将不断出现“超时”。我认为这与循环运行服务器有关,因为如果我将ListenAndServe
替换为:func (m *MultiServer) ListenAndServe() error {
var g errgroup.Group
for _, s := range m.servers {
_= s
g.Go(func(){ return errors.New("")})
}
return g.Wait()
}
一切都按预期进行。有人可以帮我弄清楚我在做什么错吗?
最佳答案
假设您正在使用http.ListenAndServe
和golang.org/x/sync/errgroup
:
Wait
。 Go
调用调用给定函数,如果该函数返回错误,则在组的上下文中调用cancel函数。但是,如果您没有调用WithContext
来创建一个具有上下文的组,则您有一个没有上下文的组,因此不会发生cancel()。 您的
eg.Wait()
调用等待两个ListenAndServe
调用返回。如果您具有取消功能并将其用于停止其他ListenAndServe
调用,那将有所帮助。参见How to stop http.ListenAndServe()。但是,您还需要一个WithContext
,这样您才能知道何时停止其他ListenAndServe
调用。请注意,一旦您拥有多个这样的对象,您将希望停止所有其他对象,而不仅仅是其他对象。
关于multithreading - 在错误组中运行多个服务器的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63933322/