赞
踩
对于业务系统来说高并发就是支撑「海量用户请求」,QPS 会是平时的几百倍甚至更高。
如果不考虑高并发的情况,即使业务系统平时运行得好好的,并发量一旦增加就会频繁出现各种诡异的业务问题,比如,在电商业务中,可能会出现用户订单丢失、库存扣减异常、超卖等问题。
限流是服务降级的一种手段,顾名思义,通过限制系统的流量,从而实现保护系统的目的。
合理的限流配置,需要了解系统的吞吐量,所以,限流一般需要结合容量规划和压测来进行。
当外部请求接近或者达到系统的最大阈值时,触发限流,采取其他的手段进行降级,保护系统不被压垮。常见的降级策略包括延迟处理、拒绝服务、随机拒绝等。
常见的限流方式,比如Hystrix适用线程池隔离,超过线程池的负载,走熔断的逻辑。在一般应用服务器中,比如tomcat容器也是通过限制它的线程数来控制并发的;也有通过时间窗口的平均速度来控制流量。常见的限流纬度有比如通过Ip来限流、通过uri来限流、通过用户访问频次来限流。
一般限流都是在网关这一层做,比如Nginx、Openresty、kong、zuul、Spring Cloud Gateway等;也可以在应用层通过Aop这种方式去做限流。
一般来说,我们进行限流时使用的是单位时间内的请求数,也就是平常说的 QPS,统计 QPS 最直接的想法就是实现一个计数器。
计数器法是限流算法里最简单的一种算法,我们假设一个接口限制 100 秒内的访问次数不能超过 10000 次,维护一个计数器,每次有新的请求过来,计数器加 1。
这时候判断,
相信大家都知道有一个弊端:如果我在单位时间100s内的前10s,已经通过了10000个请求,那后面的990s,只能眼巴巴的把请求拒绝,我们把这种现象称为“突刺现象”
计数器策略进行限流,可以从单点扩展到集群,适合应用在分布式环境中。
单点限流使用内存即可,如果扩展到集群限流,可以用一个单独的存储节点,比如 Redis 或者 Memcached 来进行存储,在固定的时间间隔内设置过期时间,就可以统计集群流量,进行整体限流。
计数器策略还有有一个很大的缺点,对临界流量不友好,限流不够平滑。
假设这样一个场景,我们限制用户一分钟下单不超过 10 万次,现在在两个时间窗口的交汇点,前后一秒钟内,分别发送 10 万次请求。也就是说,窗口切换的这两秒钟内,系统接收了 20 万下单请求,这个峰值可能会超过系统阈值,影响服务稳定性。
对计数器算法的优化,就是避免出现两倍窗口限制的请求,可以使用滑动窗口算法实现,感兴趣的同学可以去了解一下。
下面的代码里使用 AtomicInteger 作为计数器,可以作为参考:
public class CounterLimiter {
//初始时间
private static long s
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。