分布式系统限流面试
Q.E.D 人气:0引言
前面讲了系统中的降级熔断设计和对 Hystrix 组件的功能了解,关于限流降级还有一个比较重要的知识点就是限流算法。
如果你面试的是电商相关公司,这一块就显得更加重要了,秒杀、抢购等场景,需有一种手段来限制这些场景的并发/请求量,手段就是限流。
没有配置限流,如果遇到上游系统频繁调用,会导致下游系统被击垮。
配置了限流,但是限流算法不合理,会导致正常访问被拒绝,所以限流算法不能乱用,要充分评估系统是否需要限流,如果要限流,流量大小如何评估。
1、面试官:
哪些场景系统使用了限流?为什么要使用限流?
问题分析:这个问题比较简单,所有访问频繁的服务都可以做限流,相比公司内部运营系统,用户加起来不过十几个,这种系统就没必要限流了。
答:限流呀,无非就是秒杀活动,或者容易被爬虫爬的信息类页面,以及系统核心服务,这些都需要做限流,比如大众点评首页,因为推荐了一些高质量店铺信息,经常被同行或者门户类公司的爬虫爬取信息,这个时候我们就要对首页做限流操作。秒杀活动,系统核心高QPS服务,都需要考虑限流。
使用限流的目的就是我们不能轻易被别人干倒,要7x24h保证服务正常,同时,限流也是为了我们的下游系统不会轻易被我们拖垮,流量合理放行。
2、面试官:
那你了解哪些常用限流算法?
答:常用的限流算法就3种:
1.计数器方法:
固定时间窗口,比如1min/1h,设置一个计数器统计单位时间内一个请求的访问量,超过计数器最大值,可以让请求放入等待队列 or 直接拒接访问,这种方法简单粗暴,但是易造成突刺现象。
2.漏斗算法:
可以理解成一个固定容量的漏桶,不管流量多还是少,我都按照常量固定速率流出水滴,如果流入水滴超出了桶的容量,就让水溢出。这种算法优点是稳定速率,缺点是无法面对突发流量。
3.令牌桶算法:
让每次请求调用需要先获取令牌,只有拿到令牌,才有机会继续执行,否则选择等待可用的令牌,或者直接拒绝。优点是系统发放令牌的速率是可变的,能够面对突发流量,缺点是有点复杂。
具体使用哪种算法,要根据具体业务场景,比如系统时候会有突发流量,调用方重要程度等,如果调用方不是很重要,为了顾全大局,直接放调用方稍后重试。
3、面试官:
那具体这值该如何评估,说到现在我还是不知道限流到底要怎么设置,可以给我一点经验方法吗?
(我继续…)
对于核心服务限流的值可以通过以下方法来设置合理的值:
- 观察评估法:系统总该有QPS监控系统吧,看看流量环比最大值,最小值,平均值,这就是很好的参考,总不能我一拍脑袋设置一个250上去。
- 压力测试法:找QA,半夜业务低峰期,看看系统能承受的最大QPS。
同时,限流还有和重试、降级、熔断等作为组合方法一起使用。
深入分析
于具体使用的技术和工具并不是重点,还有人说我也不用Guava,也不用Thread sleep,更不用Hystrix,我用Nginx,前系统最前端同样可以做限流,方案可行,条条大路通罗马。
使用线程池实现:
@SpringBootTest @RunWith(SpringRunner.class) public class RejectTest { @Test public void testReject() { for (int i = 0; i < 25; ++i) { new Thread(() -> // do something )).start(); } // 防止主线程提前结束执行 TimeUtils.sleep(50); } }
借助Guava实现:
RateLimiter rateLimiter = RateLimiter.create(20.0); boolean token = rateLimiter.tryAcquire(); if (token) { System.out.println("pass"); } else { System.out.println("refuse"); }
总结
我认为学习限流最重要的点是掌握解决问题的思路,至于具体使用的技术和工具并不是重点,还有人说我也不用Guava,也不用Thread sleep,更不用Hystrix,我用Nginx,前系统最前端同样可以做限流,方案可行,条条大路通罗马。
加载全部内容