-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhttp_service.go
131 lines (109 loc) · 2.53 KB
/
http_service.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
package goginx
import (
"context"
"log"
"net"
"net/http"
"runtime"
"sync"
"syscall"
"time"
)
const (
PRE_SIGNAL = iota
POST_SIGNAL
STATE_INIT
STATE_RUNNING
STATE_SHUTTING_DOWN
STATE_TERMINATE
)
var (
runningServerReg sync.RWMutex
DefaultReadTimeOut time.Duration
DefaultWriteTimeOut time.Duration
DefaultMaxHeaderBytes int
DefaultHammerTime time.Duration
)
func init() {
DefaultHammerTime = 30 * time.Second
}
type httpServer struct {
http.Server
goginxListener net.Listener
wg sync.WaitGroup
state uint8
lock *sync.RWMutex
}
func NewHttpServer(addr string, handler http.Handler) *httpServer {
runningServerReg.Lock()
defer runningServerReg.Unlock()
srv := &httpServer{
wg: sync.WaitGroup{},
state: STATE_INIT,
lock: &sync.RWMutex{},
}
srv.Server.ReadTimeout = DefaultReadTimeOut
srv.Server.WriteTimeout = DefaultWriteTimeOut
srv.Server.MaxHeaderBytes = DefaultMaxHeaderBytes
srv.Server.Handler = handler
return srv
}
func (srv *httpServer) Serve() error {
defer log.Println(syscall.Getpid(), "Serve() returning...")
srv.setState(STATE_RUNNING)
err := srv.Server.Serve(srv.goginxListener)
log.Println(syscall.Getpid(), "Waiting for connections to finish...", err)
srv.wg.Wait()
srv.setState(STATE_TERMINATE)
log.Println(syscall.Getpid(), "Waiting for connections to finished")
return err
}
func (srv *httpServer) getState() uint8 {
srv.lock.RLock()
defer srv.lock.RUnlock()
return srv.state
}
func (srv *httpServer) setState(st uint8) {
srv.lock.Lock()
defer srv.lock.Unlock()
srv.state = st
}
func (srv *httpServer) Shutdown() {
if srv.getState() != STATE_RUNNING {
return
}
srv.setState(STATE_SHUTTING_DOWN)
go srv.hammerTime(DefaultHammerTime)
//srv.SetKeepAlivesEnabled(false)
//err := srv.goginxListener.Close()
ctx, _ := context.WithTimeout(context.TODO(), DefaultHammerTime)
err := srv.Server.Shutdown(ctx)
if err != nil {
log.Println(syscall.Getpid(), "http server shutdown error:", err)
} else {
log.Println(syscall.Getpid(), srv.goginxListener.Addr(), "http server shutdown.")
}
}
func (srv *httpServer) hammerTime(d time.Duration) {
defer func() {
if r := recover(); r != nil {
log.Println("WaitGroup at 0", r)
}
}()
if srv.getState() != STATE_SHUTTING_DOWN {
return
}
time.Sleep(d)
log.Println("[STOP - Hammer Time] Forcefully shutting down parent")
//err := srv.Server.Close()
//if err != nil {
// log.Println("http server close err. %s", err)
//}
for {
if srv.getState() == STATE_TERMINATE {
break
}
srv.wg.Done()
runtime.Gosched()
}
}