关于集群问题限流的一点思路
问题是我们需要做一个统一的限流层,而这个限流层肯定不是单机可以完成,必定是一个多级多机的集群来处理。
因此肯定会涉及到共享存储的事情。我们一般都使用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个分组。