限速/限流
背景: 系统及业务如何在高并发大流量下生存,扛不住压力怎么办,屈服么?当然不能,饭碗可就不保了。加机器!机器不够怎么办?业务降级,系统限流!正所谓「他强任他强,清风拂山岗;他横任他横,明月照大江」,降级和限流是大促保障中必不可少的神兵利器,丢卒保车,以暂停边缘业务为代价保障核心业务的资源,以系统不被突发流量压挂为第一要务。
Tollbooth 用于限速HTTP请求的通用中间件。它是通过令牌桶实现的。官方地址为 ,感兴趣的可以自行阅读源代码。
普及知识,令牌桶是一种常见用于控制速率的控流算法,原理:
每秒会有 r 个令牌被放入桶中,即每 1 / r 秒向桶中放入一个令牌。
一个桶最多可以存放 b 个令牌。当令牌被放入桶时,若桶已满,则令牌被直接丢弃。
当一个 n 字节的数据包抵达时,消耗 n 个令牌,然后放行之。
若桶中的令牌不足 n ,则该数据包要么被缓存要么被丢弃。
令牌桶
快速了解Tollbooth:
package main
import (
“github.com/didip/tollbooth”
“net/http”
“time”
)
func Hello Handle r(w http.ResponseWriter, req *http. Request ) {
w.Write([] byte (“Hello, World!”))
}
func main() {
// Create a request limiter per handler.
http.Handle(“/”, tollbooth.LimitFuncHandler(tollbooth.NewLimiter(1, nil ), HelloHandler))//创建一个每秒一个请求的limiter
http.ListenAndServe(“:12345”, nil)
}
其中,tollbooth.NewLimiter(r,b)的两个参数r表示每秒请求数,b表示桶容量。
接下来看
如何根据请求的远程IP、路径、方法、自定义标头和基本的auth用户名的速率限制。
lmt := tollbooth.NewLimiter(1, nil)
lmt = tollbooth.NewLimiter(1, &limiter.ExpirableOptions{DefaultExpirationTTL: time.Hour})
lmt.SetMethods([]string{“GET”, “POST”})
lmt.SetHeader(“X-Access-Token”, []string{“abc123”, “xyz098”})
……
结合httprouter示例:
package main
import (
“time”
“log”
“github.com/didip/tollbooth”
“github.com/didip/tollbooth_httprouter”
“github.com/julienschmidt/httprouter”
)
Index(w http.ResponseWriter, r *http.Request, _ httprouter. Params ) {
fmt.Fprint(w, “Welcome!\n”)
}
func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
fmt.Fprintf(w, “hello, %s!\n”, ps.ByName(“name”))
}
func main() {
router := httprouter.New()
// Create a limiter struct.
limiter := tollbooth.NewLimiter(1, time.Second, nil)
// Index route without limiting.
router.GET(“/”, Index)
// Hello route with limiting.
router.GET(“/hello/:name”,
tollbooth_httprouter.LimitHandler(Hello, limiter),
)
log.Fatal(http.ListenAndServe(“:8080”, router))
}
小结: Tollbooth 实现原理简单,可以搭配gin,fasthttp,httprouter使用,实现方法多元化,支持ip,指定用户等。如果想要实现自己更轻量级的限流,该开源项目也是一个非常好的参照。
更多内容请关注每日编程,每天进步一点。