利用`go` `channel`實現限流量控制,原理:設置一個緩沖通道,設置訪問中間鍵,當用戶請求連接時判斷channel里面長度是不是大于設定的緩沖值,如果沒有就存入一個值進入channel,如果大于緩沖值,channel自動阻塞。當用戶請求結束的時候,取出channel里面的值。
如果想限制用戶HTTP請求進行速率限制可以參考 https://github.com/didip/tollbooth 這個中間鍵
目錄:
-videos
--ce.html
-limiter.go
-main.go
main.go文件代碼:
```go
package main
import (
"log"
"net/http"
"text/template"
"time"
"github.com/julienschmidt/httprouter"
)
type middleWareHandler struct {
r *httprouter.Router
l *ConnLimiter
}
//NewMiddleWareHandler ...
func NewMiddleWareHandler(r *httprouter.Router, cc int) http.Handler {
m := middleWareHandler{}
m.r = r
m.l = NewConnLimiter(cc)
return m
}
func (m middleWareHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if !m.l.GetConn() {
defer func() { recover() }()
log.Panicln("Too many requests")
return
}
m.r.ServeHTTP(w, r)
defer m.l.ReleaseConn()
}
//RegisterHandlers ...
func RegisterHandlers() *httprouter.Router {
router := httprouter.New()
router.GET("/ce", ce)
return router
}
func ce(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
//為了演示效果這塊設置了等待
time.Sleep(time.Second * 100)
t, _ := template.ParseFiles("./videos/ce.html")
t.Execute(w, nil)
}
func main() {
r := RegisterHandlers()
//里面的參數2為設置的最大流量
mh := NewMiddleWareHandler(r, 2)
http.ListenAndServe(":9000", mh)
}
```
limiter.go文件代碼
```go
package main
import (
"log"
)
//ConnLimiter 定義一個結構體
type ConnLimiter struct {
concurrentConn int
bucket chan int
}
//NewConnLimiter ...
func NewConnLimiter(cc int) *ConnLimiter {
return &ConnLimiter{
concurrentConn: cc,
bucket: make(chan int, cc),
}
}
//GetConn 獲取通道里面的值
func (cl *ConnLimiter) GetConn() bool {
if len(cl.bucket) >= cl.concurrentConn {
log.Printf("Reached the rate limitation.")
return false
}
cl.bucket <- 1
return true
}
//ReleaseConn 釋放通道里面的值
func (cl *ConnLimiter) ReleaseConn() {
c := <-cl.bucket
log.Printf("New connction coming: %d", c)
}
```
videos/ce.html文件代碼
```go
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
歡迎訪問www.5lmh.com
</body>
</html>
```