GO使用chan实现简单漏桶限流器
漏斗算法思想:
将所有请求先存到一个桶里。若此刻桶容量没满,表示当前请求是可以访问资源。若满了,则拒绝服务。
同时桶会以固定速率取出桶里的请求来处理
根据算法思想:
我们可以使用go的带有缓存的chan来实现简单的限流器:
先讲述一下大概的思路:
使用gin,配合中间件,在中间件内进行限流处理
上代码:
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"io/ioutil"
"log"
"net/http"
)
var q chan struct{}
func init() {
// 缓冲chan的容量是3 (桶的容量为3)
q = make(chan struct{}, 3)
}
func main() {
go func() {
r := gin.Default()
r.Use(Middleware())
r.GET("/q", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"mag": "get"})
return
})
_ = r.Run(":8050")
}()
// 模仿请求
for {
res, err := http.Get("http://localhost:8050/q")
if err != nil {
fmt.Println(err)
return
}
robots, err := ioutil.ReadAll(res.Body)
res.Body.Close()
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s \n", robots)
}
}
func Middleware() gin.HandlerFunc {
return func(c *gin.Context) {
fmt.Println(len(q))
if len(q) == 3 { // 如果等于3意味着达到最大值,直接返回重试
c.JSON(http.StatusOK, gin.H{"msg": "稍后重试!"})
return
}
// 如果通过上面的if,此处会向chan写入一个空结构体,占用一个位置,可以根据业务设置相关的结构体
q <- struct{}{}
c.Next() // 使用gin的.Next函数,让当前请求调用下一handler继续执行下去
<- q // 当handler全部执行完之后,释放一个位置
}
}