-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdoor.go
More file actions
77 lines (68 loc) · 1.48 KB
/
door.go
File metadata and controls
77 lines (68 loc) · 1.48 KB
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
package server
import (
"net/http"
"sync"
)
// doorHandler 实现了 http.Handler 接口, 对活动的 http.Request 计数, 安全关闭.
type doorHandler struct {
http.Handler
notify chan bool
mux sync.Mutex
count int
stop bool
io bool
}
/*
NewDoor 返回可安全关闭的 http.Handler.
参数:
hh 是要包裹的 http.Handler, 安全关闭后通知 notify 通道.
io 指示具体访问通道的方向:
- true 表示 input, c.notify <- true
- false 表示 output, <-c.notify
*/
func NewDoor(hh http.Handler, notify chan bool, io bool) *doorHandler {
d := &doorHandler{
Handler: hh,
notify: notify,
}
return d
}
// http.Handler 接口
func (c *doorHandler) ServeHTTP(res http.ResponseWriter, req *http.Request) {
c.mux.Lock()
if c.stop {
c.mux.Unlock()
res.WriteHeader(http.StatusServiceUnavailable)
return
}
c.count++
c.mux.Unlock()
defer c.out()
c.Handler.ServeHTTP(res, req)
}
func (c *doorHandler) out() {
c.mux.Lock()
c.count--
if c.stop && c.count == 0 {
if c.io {
go func() { c.notify <- true }()
} else {
go func() { <-c.notify }()
}
}
c.mux.Unlock()
}
// 通知doorHandler开始阻止请求, 此后所有的请求都会被 StatusServiceUnavailable.
// 所有活动请求都完成后通知 notify 通道.
func (c *doorHandler) Stop() {
c.mux.Lock()
c.stop = true
c.mux.Unlock()
}
// Count 返回活动的 http.Request 数量
func (c *doorHandler) Count() (count int) {
c.mux.Lock()
count = c.count
c.mux.Unlock()
return
}