在观看慕课网的Go语言实战流媒体视频网站 ,里面有提高bucket token算法,也就是令牌桶算法,用于服务器限流。因为我刚好在做一个包含上传和下载的服务器接口,貌似会需要到这一块地方,就多加了一些了解,这里主要是将结果进行粘贴。

服务器限流介绍

服务治理之限流

来自 <https://blog.frognew.com/2017/06/rate-limiting.html>

如何测试服务器带宽?

来自 <https://www.zhihu.com/question/20561349>

简单的限流方法

贴上视频中老师写的方法(代码出处为老师视频)。

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
type ConnLimiter struct {
concurrentConn int
bucket chan int
}
// concurrentConn可以连接的数量,channel满了则
func NewConnLimiter(cc int) *ConnLimiter {
return &ConnLimiter{
concurrentConn: cc,
bucket: make(chan int, cc),
}
}

func (cl *ConnLimiter) GetConn() bool {
if len(cl.bucket) >= cl.concurrentConn {
log.Printf("Reached the rate limitation")
return false
}

cl.bucket <- 1
log.Printf("Successfully got connection")
return true
}

func (cl *ConnLimiter) ReleaseConn() {
c := <-cl.bucket
log.Printf("New connection coming: %d", c)
}

通过封装ServeHTTP方法,达到嵌入限流代码的目的。

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
type middleWareHandler struct {
r *httprouter.Router
l *ConnLimiter
}

//NewMiddleWareHandler def
func NewMiddleWareHandler(r *httprouter.Router, cc int) http.Handler {
m := middleWareHandler{}
m.r = r
m.l = NewConnLimiter(cc)
return m
}

func RegisterHandlers() *httprouter.Router {
router := httprouter.New()

router.GET("/videos/:vid-id", streamHandler)

router.POST("/upload/:vid-id", uploadHandler)

router.GET("/testpage", testPageHandler)

return router
}
// Handler最终会调用httprouter.Router接口方法中的ServeHTTP,这里对Go方法进行DIY封装
func (m middleWareHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if !m.l.GetConn() {
sendErrorResponse(w, http.StatusTooManyRequests, "Too many requests")
return
}

defer m.l.ReleaseConn()

// 调用router起作用ServeHTTP
m.r.ServeHTTP(w, r)
}

func main() {
r := RegisterHandlers()
mh := NewMiddleWareHandler(r, 2)
http.ListenAndServe(":9000", mh)
}

复杂的限流方法介绍

服务器下载限流操作(使用token bucket):

各种类似算法实现:

https://hustcat.github.io/rate-limit-example-in-go/

HTTP限速中间件:

https://github.com/didip/tollbooth

修改servefile来实现(用到https://github.com/juju/ratelimit):

https://stackoverflow.com/questions/29445173/how-to-limit-download-speed-with-go

使用包来实现:

https://www.0value.com/throttled--guardian-of-the-web-server

https://github.com/throttled/throttled