1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
package main
import (
"context"
"fmt"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"golang.org/x/sync/errgroup"
)
type helloHandler struct {
ctx context.Context
name string
}
func (h *helloHandler) ServeHTTP(
w http.ResponseWriter,
r *http.Request,
) {
w.Write([]byte(fmt.Sprintf("Hello from %s", h.name)))
}
func newHelloServer(
ctx context.Context,
name string,
port int,
) *http.Server {
mux := http.NewServeMux()
handler := &helloHandler{ctx: ctx, name: name}
mux.Handle("/", handler)
httpServer := &http.Server{
Addr: fmt.Sprintf(":%d", port),
Handler: mux,
}
return httpServer
}
func main() {
// HERE
// setup context and signal handling
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
defer cancel()
quit := make(chan os.Signal, 1)
signal.Notify(quit, os.Interrupt, syscall.SIGTERM)
defer signal.Stop(quit)
g, ctx := errgroup.WithContext(ctx)
// start servers
server1 := newHelloServer(ctx, "server1", 8080)
g.Go(func() error {
log.Println("server 1 listening on port 8080")
if err := server1.ListenAndServe();
err != http.ErrServerClosed {
return err
}
return nil
})
server2 := newHelloServer(ctx, "server2", 8081)
g.Go(func() error {
log.Println("server 2 listening on port 8081")
if err := server2.ListenAndServe();
err != http.ErrServerClosed {
return err
}
return nil
})
// handle termination
select {
case <-quit:
break
case <-ctx.Done():
break
}
// gracefully shutdown http servers
cancel()
timeoutCtx, timeoutCancel := context.WithTimeout(
context.Background(),
10*time.Second,
)
defer timeoutCancel()
log.Println("shutting down servers, please wait...")
server1.Shutdown(timeoutCtx)
server2.Shutdown(timeoutCtx)
// AND THIS
// wait for shutdown
if err := g.Wait(); err != nil {
log.Fatal(err)
}
log.Println("a graceful bye")
}
|