关于集群问题限流的一点思路

问题是我们需要做一个统一的限流层,而这个限流层肯定不是单机可以完成,必定是一个多级多机的集群来处理。
因此肯定会涉及到共享存储的事情。我们一般都使用redis,但是其实redis涉及到单核上限的问题,其实更好的应该还是memcache,很多公司都改良过memecache也都开源出来的。

限流性能考量

现有的开源方案

网上有一堆关于nginx限流的文章。

主要看的就是
https://www.upyun.com/opentalk/417.html
https://blog.cloudflare.com/counting-things-a-lot-of-different-things/
http://nginx.org/en/docs/http/ngx_http_limit_req_module.html

用到的算法基本就两种,漏桶算法和令牌桶算法。

漏桶算法更关注的是一个速率的,而令牌桶算法就是更关注整体的容量。

现有方案的不足之处

但是当我们一个要限速每秒10万,这个时候我们不可能每来一个请求就去请求redis一下,这样不光是redis承受不了,整个网络IO更是如此,就算使用redis集群也有上限的。

所以我们的目标就是降低操作数据的次数。这样就可以降低网络IO和数据操作次数。

那现在的思路就是假设要限流10万次每秒。 我们将10万除以100,得到了1000次。每内部计数到1000次再通过网络去操作一下数据。

如上图所示的。但是这种做法就是不精确。最坏情况就是有4%的误差,也就是机器个数的百分比。这个看各自的需求吧,如果受不了那就改成千分比,不过那样操作次数就会多了点。

理论上是这样的,但是做起来就看看现在有没有现有的轮子,毕竟直接在nginx的代码里改有点难度,还是直接上lua版本的。

https://github.com/timebug/lua-resty-redis-ratelimit
https://github.com/upyun/lua-resty-limit-rate
https://github.com/upyun/lua-resty-sync

上面这3个都可以参考下,到底是redis操作还是直接内部sync可以再考虑。不一定redis的就比sync的好。

整体思路就是按照令牌桶的策略,我们更关注的是整体容量,间隔区间200ms还是100ms其实对于后端影响并不大。

但是这个是后端,后面还需要有个管理界面去做这个。

简单点的就用现有的Jenkins去完成,但是这个功能有限,仅有的就是查询下操作历史。现有状态什么都要从自己去实现下。

那就撸个管理后台。大体包含的功能如下

限流后台设计

限流维度

时间维度

  • 按秒
  • 按十秒
  • 按分钟
  • 按小时
  • 按天

api维度

  • method + 单个API
  • 单个API

访问来源维度

  • 访问IP
  • refer?

整体限流

每个API都有自己的上限标准。
然后每个rest也都有自己的上限标准。
给单个客户加的限流标准不能超过整体限流的100%,提示需要扩容。

客户限流

每个客户可以有10个限流标准。
限流标准不支持时间计划:比如12点是并发100, 23点是并发200这种标准。
限流维度支持多个维度关联,最少也要2个维度关联。

超了怎么样?

返回status 429,内容为(nginx rate limit)·
给支持和销售发对应邮件,提示该客户已经超了限流,需要购买提升现有限流标准。提示信息每小时发一次,防止邮件风暴。

展示

展示单个客户的限流规则
展示默认的限流规则
展示整个系统的限流和现有的剩余。

权限

这个就按照openldap的分组来就行了。就读写2个分组。