-
Notifications
You must be signed in to change notification settings - Fork 3
/
grace.go
138 lines (121 loc) · 3.07 KB
/
grace.go
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package graceful
import (
"log"
"net"
"os"
"syscall"
"time"
)
const (
// path env to given child proc
EnvWorker = "ENV_WORKER"
EnvWorkerVal = "1"
EnvOldWorkerPid = "ENV_OLD_WORKER_PID"
)
var (
defaultWatchInterval = time.Second
defaultReloadSignals = []syscall.Signal{syscall.SIGHUP, syscall.SIGUSR1, syscall.SIGUSR2}
defaultStopSignals = []syscall.Signal{syscall.SIGKILL, syscall.SIGTERM, syscall.SIGINT}
defaultMaxConnectionNumber int64 = 10000
)
// Grace server
type Grace struct {
opt *option
addr Address
services []*service
}
type service struct {
addr Address
startFunc func(net.Listener) error
shutdownFunc func() error
}
// tcp address
type Address struct {
addr string
network string //tcp, unix
}
// NewAddress
func NewAddress(addr, network string) Address {
return Address{addr, network}
}
// New return Grace
func New(opts ...Option) *Grace {
option := &option{
watchInterval: defaultWatchInterval,
stopSignals: defaultStopSignals,
reloadSignals: defaultReloadSignals,
enableConnectionLimit: false,
maxConnectionNumber: defaultMaxConnectionNumber,
}
for _, opt := range opts {
opt(option)
}
return &Grace{
opt: option,
services: []*service{},
}
}
// RegisterService can register multi addr port like http and https
func (g *Grace) RegisterService(addr Address, startFun func(ln net.Listener) error, shutdownFun func() error) {
g.services = append(g.services, &service{
addr: addr,
startFunc: startFun,
shutdownFunc: shutdownFun,
})
}
// Run grace
func (g *Grace) Run() error {
if isWorker() {
log.Printf("[info]Worker here, pid=%v", syscall.Getpid())
worker := &worker{
opt: g.opt,
stopCh: make(chan struct{}),
listeners: make([]net.Listener, 0, len(g.services)),
services: g.services,
}
return worker.run()
}
log.Printf("[info]master here, pid=%v", syscall.Getpid())
master := &master{
addr: g.addr,
opt: g.opt,
workerExit: make(chan error),
}
return master.run(g.services)
}
func isWorker() bool {
return os.Getenv(EnvWorker) == EnvWorkerVal
}
type option struct {
watchInterval time.Duration
reloadSignals []syscall.Signal
stopSignals []syscall.Signal
enableConnectionLimit bool
maxConnectionNumber int64
}
type Option func(o *option)
// WithWatchInterval, worker watch master, if master down, we exit worker.
func WithWatchInterval(timeout time.Duration) Option {
return func(o *option) {
o.watchInterval = timeout
}
}
// WithWatchInterval set reload signals
func WithReloadSignals(reloadSignals []syscall.Signal) Option {
return func(o *option) {
o.reloadSignals = reloadSignals
}
}
// WithWatchInterval set stop signals
func WithStopSignals(stopSignals []syscall.Signal) Option {
return func(o *option) {
o.stopSignals = stopSignals
}
}
// WithConnectionLimit set connection limit
func WithConnectionLimit(enable bool, limit int64) Option {
return func(o *option) {
o.enableConnectionLimit = enable
o.maxConnectionNumber = limit
}
}