限流器

简介

缓存、降级和限流是高并发系统时有三把利器。

限流(限制并发/请求量),它的目的是通过对并发访问/请求进行限速或者一个时间窗口内的请求进行限速来保护系统,如果请求达到上限值,服务端可以采取拒接服务、排队或等待、降级。

限流算法

常见的限流算法有: 令牌桶、漏桶。

漏桶

漏桶(Leaky Bucket)算法思路很简单,水(请求)先进入到漏桶里,漏桶以一定的速度出水(接口有响应速率),当水流入速度过大会直接溢出(访问频率超过接口响应速率),然后就拒绝请求,可以看出漏桶算法能强行限制数据的传输速率。

令牌桶

令牌桶算法(Token Bucket)和 Leaky Bucket 效果一样但方向相反的算法,更加容易理解。随着时间流逝,系统会按恒定 1/QPS 时间间隔(如果QPS=100,则间隔是10ms)往桶里加入 Token (想象和漏洞漏水相反,有个水龙头在不断的加水),如果桶已经满了就不再加了。新请求来临时,会各自拿走一个Token,如果没有Token可拿了就阻塞或者拒绝服务。

使用

Vine 的 wrapper 可以实现限流器功能:

package main

import (
	"context"

	pb "github.com/vine-io/examples/wrapper/pb"
	ub "github.com/vine-io/plugins/wrapper/ratelimiter/uber"
	"github.com/vine-io/vine"
	log "github.com/vine-io/vine/lib/logger"
)

type hello struct{}

func (h hello) Echo(ctx context.Context, request *pb.Request, response *pb.Response) error {
	response.Result = request.Name
	return nil
}

func main() {
	handler := ub.NewHandlerWrapper(1000)

	s := vine.NewService(
		vine.Name("helloworld"),
		vine.WrapHandler(handler),
	)

	s.Init()

	pb.RegisterHelloHandler(s.Server(), &hello{})

	if err := s.Run(); err != nil {
		log.Fatal(err)
	}
}

最后修改 September 8, 2021: ratelimiter (135eecd)