限速/限流

背景: 系统及业务如何在高并发大流量下生存,扛不住压力怎么办,屈服么?当然不能,饭碗可就不保了。加机器!机器不够怎么办?业务降级,系统限流!正所谓「他强任他强,清风拂山岗;他横任他横,明月照大江」,降级和限流是大促保障中必不可少的神兵利器,丢卒保车,以暂停边缘业务为代价保障核心业务的资源,以系统不被突发流量压挂为第一要务。

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,指定用户等。如果想要实现自己更轻量级的限流,该开源项目也是一个非常好的参照。

更多内容请关注每日编程,每天进步一点。