<p>Currently I'm doing something like <a href="https://gist.github.com/fharding1/e5dc739ed795084746dc0900a3579692">this</a> which seems pretty ugly to me. Is there an easier way to run two HTTP servers at the same time with proper error handling?</p>
<hr/>**评论:**<br/><br/>comrade_donkey: <pre><p>That seems correct and clear, what bothers you about your code?</p></pre>Franke123: <pre><p>I was just wondering if there was a better way! I would rather not have to deal with channels and goroutines (even though I will obviously have to use goroutines since I'm running two servers at the same time). Maybe something in the stdlib? Seems like there's always a cleaner way to do things in Go.</p></pre>comrade_donkey: <pre><p>I'm not aware of anything in the stdlib that would do this. In fact, I like the way you wrote it.</p></pre>tgaz: <pre><p><a href="https://godoc.org/golang.org/x/sync/errgroup">errgroup</a> makes it slightly better and more correct (the last goroutine will block on the unbuffered <code>errch</code> the way your code is written):</p>
<pre><code>func run() error {
// ...
g, gctx := errgroup.WithContext(context.Background())
g.Go(func() error { return httpServer.ListenAndServe() })
g.Go(func() error { return httpsServer.ListenAndServeTLS(certFile, keyFile) })
<-gctx.Done()
httpServer.Close()
httpsServer.Close()
return g.Wait()
}
</code></pre>
<p><strong>EDIT</strong> no need for <code>WithContext</code>.</p>
<p><strong>EDIT</strong> as pointed out, <code>Wait</code> waits for all to return, so we need <code>WithContext</code>.</p></pre>planet12: <pre><p>From the x/sync/errgroup docs: "Wait blocks until all function calls from the Go method have returned, then returns the first non-nil error (if any) from them."</p>
<p>In the above, if one server started up fine but the other failed, g.Wait() would never return.</p></pre>tv64738: <pre><p>Yeah, you'd need to separate the listening and serving, and do something like</p>
<pre><code>g.Go(func() error { <-ctx.Done(); return httpListener.Close() }
g.Go(func() error { <-ctx.Done(); return httpsListener.Close() }
</code></pre></pre>tgaz: <pre><p>I think we could just do that in the run() goroutine, and just wait for context cancellation before <code>Wait</code>.</p></pre>Fitzoh: <pre><p>At risk of answering a different question, does that need to happen at the app level?</p>
<p>It might make more sense to just let the app listen on a single http port and use nginx/haproxy/whatever to terminate ssl and reverse proxy on multiple ports.</p></pre>Franke123: <pre><p>That's another thing I was considering doing, nginx reverse proxy. For a couple of reasons our team decided not to do it, but I would normally just go with that.</p></pre>janderssen: <pre><p>I created a "MulitListener" which implements the net.Listener interface {} and can listen to any number of configured ports, and accepts sockets (mix of ssl or non) when connections arrive, I then use this as follows :</p>
<p>err := httpServer.Serve(webServiceListeners).</p>
<p>I remember I had an issues of creating two seperate web servers using the same routing, which would either hang or panic, this was my solution to the problem and it works so far perfectly.</p></pre>gxti: <pre><p>Here's another approach with graceful shutdown: <a href="https://github.com/sassoftware/relic/blob/master/server/daemon/daemon.go" rel="nofollow">https://github.com/sassoftware/relic/blob/master/server/daemon/daemon.go</a></p></pre>Cvballa3g0: <pre><p>Here's what I came up with.. Create two listeners (tls & tcp) and serve them from the same http server struct.
Apply the error handling <a href="/u/tgaz" rel="nofollow">/u/tgaz</a> mentioned or try this package <a href="https://github.com/oklog/run" rel="nofollow">https://github.com/oklog/run</a>.</p>
<p><a href="https://play.golang.org/p/J_FyhWLbRx" rel="nofollow">https://play.golang.org/p/J_FyhWLbRx</a></p>
<pre><code> $ curl http://localhost:8080
hello from: http://localhost:8080
$ curl -k https://localhost:4343
hello from: https://localhost:4343
</code></pre></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传