微服务-服务限流-开发实战
学习思路
各种限流方式应用场景及优缺点
具体实现
一、各种限流方式应用场景及优缺点
限流:在了解了系统的负荷之后,如果访问流量超过负荷那么将导致服务整体被压垮,为保证服务可用预防突发流量,在流量到达设置指标时允许摒弃部分以保证服务运行正常
总流量限流:一般以服务资源为标准,在有限资源的基础上设置最高上限;如:在服务器数量、配置一定的条件下,通过压测等手段设置系统访问阈值
按用户或客户端Ip限流:可防止同一ip或同一用户下恶意操作,可以统计正常情况下用户的平均访问频率设置阈值
接口级别限流:在单接口上限制;防止系统资源被某个接口全用完毕,导致其他接口不可用,跟线程池隔离原理类似
应用场景及优缺点
总流量限流:主要在网关层/Nginx层做,优点:可以设置上限,有效保护系统稳定,缺点:依赖于下游资源,如果资源变更需要动态调整
按用户、ip等限流:主要在网关做,优点:主要限制个人、低级的恶意刷,缺点:不能控制总量,多ip刷一个接口也可以刷死服务
按接口限流:主要用于抢购类接口定制开发,优点:可以根据不同接口单独设置,可有效隔离接口资源,缺点:代码浸入,局限性高,总资源不能有效保护,但如果真的遇到资源不足的时候基本已经做服务横向扩容了
实际应用上
在Nginx或者网关做总流量限流,防止恶意攻击
在抢购类接口按ip或者用户做定制开发;当然我们也可以在网关层进行拦截(只需要简单配置)
二、具体实现方式
原理分析
1、令牌桶算法
解释:
系统按照恒定的速率往桶里放入token
桶满时溢出放弃
新请求来时可拿取一个或多个token
如果没有token拒绝请求
获取的时候可以获取多个token从而应对突发流量
2、漏铜算法
解释
流量以任意的速度流入桶中
当桶内流量满时溢出
流量以均衡的速度漏出
桶内没有流量时流不出(拒绝访问)
可见这里有两个变量,一个是桶的大小,支持流量突发增多时可以存多少的水(burst),另一个是水桶漏洞的大小(rate)。
因为漏桶的漏出速率是固定的参数,所以,即使网络中不存在资源冲突(没有发生拥塞),漏桶算法也不能使流突发(burst)到端口速率.因此,漏桶算法对于存在突发特性的流量来说不能很好解决
3、计数器
这个就比较粗糙了,但往往我们一般都用粗糙的
利用atomic包里的对象进行原子++
redis的原子++
总归一个思路:设置两个变量,一个记录时间,一个记录次数,在规定的时间内达到这个次数就认为该限流了
二、代码实战
实现思路
自定义注解在Controller方法用
基于AOP拦截注解上属性,限流策略可自定义
使用线程池异步执行
运用redis+lua实现原子操作
看一下代码结构: