我报名参与金石方案1期挑战——分割10万奖池,这是我的第1篇文章,点击查看活动概况

前语

在咱们的日常开发中, 常用的中间件有很多, 今日来讲一下怎么集成限流中间件, 它能够很好地用约束并发拜访数来维护体系服务, 防止体系服务溃散, 资源占用过大乃至服务器溃散从而影响到其他应用!

分布式版

简介

一般咱们的服务会一起存在多个进程, 也就是负载来保证服务的功能和稳定性, 那么就需要走一个一致的限流, 这个时分就需要借助咱们的老朋友-redis, 来进行分布式限流;

算法

漏桶算法

即一个水桶, 进水(承受恳求)的速率不限, 出水(处理恳求)的速率是一定的, 假如出水的速率小于进水的速率, 就会造成水桶溢出(也就是拒绝恳求);
主要是从出口约束, 以固定的速率控制拜访速度, 缺陷是难以应对突发恳求;

依靠库

github.com/go-redis/re…

完成

下面是一个简略的完成, 对 /v1/hello接口进行每分钟2次的速率约束

// RateLimitConf 速率装备, 答应多长时间经过多少次.
type RateLimitConf struct {
	Limit int64
	Timer time.Duration
}
// exampleLimiterMap 接口恳求速率装备, 建议放入redis/数据库同步本地缓存.
var exampleLimiterMap = map[string]RateLimitConf{
	"/v1/hello": {Limit: 2, Timer: time.Minute},
}
// LimiterMiddle 分布式限流中间件.
func LimiterMiddle(ctx iris.Context) {
	var (
		uri    = ctx.Request().RequestURI
		client = redis.NewClusterClient()
		key    = uri
	)
	conf, ok := exampleLimiterMap[uri]
	if ok {
		limiter := redis_rate.NewLimiter(client)
		if _, _, b := limiter.Allow(key, conf.Limit, conf.Timer); !b {
			r, _ := httpcode.NewRequest(ctx, nil)
			r.Code(httpcode.TooManyReq, fmt.Errorf("req rate limit"), nil)
			return
		}
	}
	ctx.Next()
}

注意

  1. 接口速率装备假如需要进行实时装备, 则建议将装备写入数据库, 然后刷新到本地缓存/存到redis;
  2. 假如需要对设备/ip/用户进行接口约束拜访, 则将 key加上唯一标志即可;

单机版

简介

这个就只适用于单个服务进程的限流, 比方个人搭的一些小网站之类的;

算法

令牌桶算法

即也是一个桶, 按照设定的速率往桶里放令牌, 10s二十次即1s放两个令牌(答应处理两次恳求), 然后恳求来之后有必要从桶里取出来令牌才能够进行处理, 没有令牌则挑选拒绝或等候;
主要是从进口约束, 答应一定量的突发恳求(即桶内所有的令牌);

依靠库

golang.org/x/time/rate

完成

下面是一个简略的完成, 对 /v1/hello接口进行每分钟2次的速率约束


// exampleStandAloneLimiterMap 单机接口恳求速率装备.
var exampleStandAloneLimiterMap = map[string]*rate.Limiter{
	"/v1/hello": rate.NewLimiter(rate.Every(time.Minute), 2),
}
// StandAloneLimiterMiddle 单机限流中间件.
func StandAloneLimiterMiddle(ctx iris.Context) {
	var (
		uri = ctx.Request().RequestURI
	)
	limiter, ok := exampleStandAloneLimiterMap[uri]
	if ok {
		if b := limiter.Allow(); !b {
			r, _ := httpcode.NewRequest(ctx, nil)
			r.Code(httpcode.TooManyReq, fmt.Errorf("req rate limit"), nil)
			return
		}
	}
	ctx.Next()
}

结语

上面的代码均摘自我开发的一个开源项目中, 主要是一个Go的规范项目布局, 封装了一些常用的组件, 有兴趣的朋友能够了解一下, 新手极易上手;