本文参考资料
高并发系统之限流特技:http://blog.csdn.net/g_hongjin/article/details/51649246
RateLimit--使用guava来做接口限流:http://blog.csdn.net/jiesa/article/details/50412027
秒杀:http://www.infoq.com/cn/articles/solution-to-the-architecture-of-spike-system
背景
2月22日10点负责的一个项目异常增多,服务几近不可用,并引发雪崩,造成其他项目也不可用。对日志进行分析后发现,服务调用量激增了10倍,最后经过扩容解决了问题,影响时间将近20分钟。事故原因:上游系统一个服务站点出现故障,导致大量请求过来,随后出现线程连接数爆满且出现很多请求超时,当调用方发现超时会不停的重试3次,这时候请求数瞬时成倍增长。
求索
流量激增,犹如暴雨导致河流流量增多,可能会超过大坝的防洪库容,需要泄洪保护大坝不被冲毁;也犹如家里的保险控制,一旦使用大功率的电器,保险有可能跳闸,保护电路不被烧毁。我们系统中如果有保险控制或防洪大坝,非预期的请求过大也不致于引起的系统瘫痪,系统可以拒绝或者或者引流,这就是所谓的限流。
常用限流算法
常用算法有漏桶算法和令牌桶算法
令牌桶算法:
令牌桶算法是一个存放固定容量令牌的桶,按照固定速率往桶里添加令牌。
a. 按特定的速率向令牌桶投放令牌
b.桶中最多存放b个令牌,当桶满时,新添加的令牌被丢弃或拒绝;
c.当1请求到达,将从桶中删除1个令牌,接着处理请求;
d.如果桶中的令牌不足,则不会删除令牌,且该请求将被限流(要么丢弃,要么缓冲区等待)
漏桶算法:
漏桶算法的描述如下:
1.一个固定容量的漏桶,按照常量固定速率流出水滴;、
2.如果桶是空的,则不需流出水滴;
3.可以以任意速率流入水滴到漏桶;
4.如果流入水滴超出了桶的容量,则流入的水滴溢出了(被丢弃),而漏桶容量是不变的。
实践
应用级限流:nignx中limit_conn模块,
Tomcat的Connector几种参数:
- acceptCount:如果Tomcat的线程都忙于响应,新来的连接会进入队列排队,如果超出排队大小,则拒绝连接;
- maxConnections:瞬时最大连接数,超出的会排队等待;
- maxThreads:Tomcat能启动用来处理请求的最大线程数,如果请求处理量一直远远大于最大线程数则可能会僵死。
编程级别:
- 限流某个接口的总并发/请求数
=================================
try { if(atomic.incrementAndGet() > 限流数) { //拒绝请求 } //处理请求 } finally { atomic.decrementAndGet(); }
=================================
2.限流某个接口的时间窗请求数
=================================
LoadingCachecounter = CacheBuilder.newBuilder() .expireAfterWrite(2, TimeUnit.SECONDS) .build(new CacheLoader () { @Override public AtomicLong load(Long seconds) throws Exception { return new AtomicLong(0); } }); long limit = 1000; while(true) { //得到当前秒 long currentSeconds = System.currentTimeMillis() / 1000; if(counter.get(currentSeconds).incrementAndGet() > limit) { System.out.println("限流了:" + currentSeconds); continue; } //业务处理 }
3. 平滑限流某个接口的请求数(令牌桶和漏桶实践)
RateLimiter使用实践