Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to stop http.ListenAndServe()

Tags:

go

I am using the Mux library from Gorilla Web Toolkit along with the bundled Go http server.

The problem is that in my application the HTTP server is only one component and it is required to stop and start at my discretion.

When I call http.ListenAndServe(fmt.Sprintf(":%d", service.Port()), service.router) it blocks and I cannot seem to stop the server from running.

I am aware this has been a problem in the past, is that still the case? Are there any new solutions?

like image 955
jim Avatar asked Sep 04 '16 18:09

jim


People also ask

How to stop http ListenAndServe golang?

WaitGroup in main(), call Add(1) on it and pass a pointer to it to startHttpServer() and call defer waitGroup. Done() at start of the goroutine that has a call to the ListenAndServe(). then just call waitGroup. Wait() at end of main() to wait for the goroutine to have finished its job.

How do I stop go service?

You can easily cancel by messaging us on WhatsApp, Facebook Messenger or using the Live Chat on our website. You can also visit one of our GO outlets.

Does ListenAndServe block?

ListenAndServe() is blocking, and in your scenario, there are two of them, then try to put one of them in a goroutine. The idea is to separate the execution of those two web server initialization statements into separate goroutine.


1 Answers

Regarding graceful shutdown (introduced in Go 1.8), a bit more concrete example:

package main  import (     "context"     "io"     "log"     "net/http"     "sync"     "time" )  func startHttpServer(wg *sync.WaitGroup) *http.Server {     srv := &http.Server{Addr: ":8080"}      http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {         io.WriteString(w, "hello world\n")     })      go func() {         defer wg.Done() // let main know we are done cleaning up          // always returns error. ErrServerClosed on graceful close         if err := srv.ListenAndServe(); err != http.ErrServerClosed {             // unexpected error. port in use?             log.Fatalf("ListenAndServe(): %v", err)         }     }()      // returning reference so caller can call Shutdown()     return srv }  func main() {     log.Printf("main: starting HTTP server")      httpServerExitDone := &sync.WaitGroup{}      httpServerExitDone.Add(1)     srv := startHttpServer(httpServerExitDone)      log.Printf("main: serving for 10 seconds")      time.Sleep(10 * time.Second)      log.Printf("main: stopping HTTP server")      // now close the server gracefully ("shutdown")     // timeout could be given with a proper context     // (in real world you shouldn't use TODO()).     if err := srv.Shutdown(context.TODO()); err != nil {         panic(err) // failure/timeout shutting down the server gracefully     }      // wait for goroutine started in startHttpServer() to stop     httpServerExitDone.Wait()      log.Printf("main: done. exiting") } 
like image 185
joonas.fi Avatar answered Sep 23 '22 02:09

joonas.fi