流量激增不宕机,服务限流系统架构解密
今天我们来探索一下在分布式系统架构中的另一个常用的设计:服务限流。那么,什么是「服务限流」呢?
解释「服务限流」之前,我们来看一下前些时间网上很火的一个段子,说的是新浪微博的一名工程师正在家里办婚礼,突然接到公司的电话要紧急处理线上流量激增的问题,那天应该是某当红明星突然在微博上公布恋情,微博流量突增好几倍,导致系统功能出现不稳定,用户访问不畅。然后这名工程师就只好晾开新娘,在婚礼现场穿着西装打开笔记本调试代码了。
当时这名工程师内心肯定是崩溃的:为啥要在今天公布恋情!等我把系统的扩容和服务限流机制做好先啊。
哈哈,看完了段子,基本上服务限流的作用也就明白:
「服务限流」其实是指当系统资源不够,不足以应对大量请求,即系统资源与访问量出现矛盾的时候,为了保证有限的资源能够正常服务,因此我们对系统按照预设的规则进行流量限制或功能限制的一种方法。
一、为什么要做服务限流设计
再举一个我们生活中的例子:一些热门的旅游景点,往往对每日的旅游参观人数有严格的限制,比如北京的故宫、欢乐谷等,每天只卖固定数目的门票,如果去的晚了,可能当天的票就已经卖完,当天就无法进去游玩,即使进去,排队也能排到你怀疑人生。
为什么旅游景点要做这样的限制呢?多卖一些门票多赚一些钱岂不是更好?
其实对于旅游景点而言,她们也很无奈,因为景点的服务资源有限,每日能服务的人数也有限,一旦放开限制,景点的工作人员就会不够用,卫生情况也得不到保障,安全也存在隐患,超密集的人群也会严重影响游客体验。但由于景区名气大,来游玩的旅客络绎不绝,远超出了景区的承载能力,因此景区只好做出限制每日人员流量的举措。
同理,在IT软件行业中,系统服务也是这样。
如果你的系统理论是时间单位内可服务100W用户,但是今天却突然来了300W用户,由于用户流量的随机性,如果不限流,很有可能这300W用户瞬间就压垮了系统,导致所有人都得不到服务。
因此为了保证系统至少还能为100W用户提供正常服务,我们需要对系统进行限流设计。
有人可能会想,既然会有300W用户来访问,那为啥系统不干脆设计成能足以支撑这么大量用户的集群呢?
这是个好问题。如果系统是长期有300W的用户来访问,肯定是要做上述升级的,但是常常面临的情况是,系统的日常访问量就是100W,只不过偶尔有一些不可预知的特定原因导致短时间的流量激增,这个时候,公司往往出于节约成本的考虑,不会为了一个不常见的尖峰来把我们的系统扩容到最大的尺寸。
二、服务限流应该怎么做
1、限流模式
对系统服务进行限流,一般有如下几个模式:
熔断
这个模式需要系统在设计之初,就把熔断措施考虑进去。当系统出现问题时,如果短时间内无法修复,系统要自动做出判断,开启熔断开关,拒绝流量访问,避免大流量对后端的过载请求。系统也应该能够动态监测后端程序的修复情况,当程序恢复稳定时,可以关闭熔断开关,恢复正常服务。
服务降级
将系统的所有功能服务进行一个分级,当系统出现问题,需要紧急限流时,可以把不是那么重要的功能进行降级处理,停止服务,这样可以释放出更多的资源供给核心功能的去用。
例如在电商平台中,如果突发流量激增,可临时将商品评论、积分等非核心功能进行降级,停止这些服务,释放出机器和CPU等资源来保障用户正常下单,而这些降级的功能服务可以等整个系统恢复正常后,再来启动,进行补单/补偿处理。除了功能降级以外,还可以采纳不直接操作数据库,而全部读缓存、写缓存这样的方式作为临时降级方案。
延迟处理
这个模式需要在系统的前端设置一个流量缓冲池,将所有的请求全部缓冲进这个池,不立即处理。然后后端真正的业务处理程序从这个池中取出请求依次处理,常见的可以用队列模式来实现。这就相当于用异步的方式减少了后端的处理压力,但是当流量较大时,后端的处理能力有限,缓冲池里的请求可能处理不及时,会有一定程度延迟。
特权处理
这个模式需要将用户进行分类,通过预设的分类,让系统优先处理需要高保障的用户群体,其它用户群的请求就会延迟处理或者直接不处理。
2、限制方法
那在实际项目中,对访问流量的限制,可采用如下几种技术方法:
熔断技术
熔断的技术可以重点参考Netflix的开源组件Hystrix的做法,主要有三个模块:熔断请求判断算法、熔断恢复机制、熔断报警。
Hystrix参考链接:https://github.com/Netflix/Hystrix
计数器方法
系统维护一个计数器,来一个请求就加1,请求处理完成就减1,当计数器大于指定的阈值,就拒绝新的请求。
基于这个简单的方法,可以再延伸出一些高级功能,比如阈值可以不是固定值,是动态调整的。另外,还可以有多组计数器分别管理不同的服务,以保证互不影响等。
队列方法
就是基于FIFO队列,所有请求都进入队列,后端程序从队列中取出待处理的请求依次处理。基于队列的方法,也可以延伸出更多的玩法来,比如可以设置多个队列以配置不同的优先级。
令牌桶方法
首先还是要基于一个队列,请求放到队列里面。但除了队列以外,还要设置一个令牌桶,另外有一个脚本以持续恒定的速度往令牌桶里面放令牌,后端处理程序每处理一个请求就必须从桶里拿出一个令牌,如果令牌拿完了,那就不能处理请求了。我们可以控制脚本放令牌的速度来达到控制后端处理的速度,以实现动态流控。
三、服务限流的注意事项
我们在做服务限流的时候,还是有一些原则和事项需要注意的:
● 实时监控:系统必须要做好全链路的实时监控,才能保证限流的及时检测和处理。● 手动开关:除系统自动限流以外,还需要有能手动控制的开关,以保证随时都可以人工介入。
● 限流的性能:限流的功能理论上是会在一定程度影响到业务正常性能的,因此需要做到限流的性能优化和控制。
四、总结
系统故障常常都是不可预测且难以避免的,因此作为系统设计师的我们,必须要提前预设各种措施,以应对随时可能出现的系统风险。
原文发布时间为:2018-11-14
本文作者:不止思考的技术
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
4.5管道实现机制和模拟构建管道「深入浅出ASP.NET Core系列」
希望给你3-5分钟的碎片化学习,可能是坐地铁、等公交,积少成多,水滴石穿,谢谢关注。 管道实现机制 要了解管道的实现机制,我们必须要深入框架的源码,幸亏微软开源了,我们可以访问GitHub的地址来下载源码。 git clone后,我们打开工程,进入Microsoft.AspNetCore.Http项目搜索ApplicationBuilder类(如下图),RequestDelegate是中间件的核心,而ApplicationBuilder是接收多个RequestDelegate的集合,所以解析ApplicationBuilder是了解整个管道实现的重要内容。而ApplicationBuilder里有两个重要的方法Build和Use也是我们关注的焦点。 Use方法 我们看下Use方法的参数是一个委托,该委托接收一个RequestDelegate参数,返回一个RequestDelegate,而_components.Add(middleware);是什么呢?我们看下这个全局变量的定义: _components就是一个IList列表容器,也就是说Use方法做的事情非常简单,就是不断的...
- 下一篇
深入理解Java中的fail-fast和fail-safe
什么是快速失败(fail-fast)和安全失败(fail-safe)?它们又和什么内容有关系。以上两点就是这篇文章的内容,废话不多话,正文请慢用。 我们都接触 HashMap、ArrayList 这些集合类,这些在 java.util 包的集合类就都是快速失败的;而java.util.concurrent 包下的类都是安全失败,比如:ConcurrentHashMap。 快速失败(fail-fast) 在使用迭代器对集合对象进行遍历的时候,如果 A 线程正在对集合进行遍历,此时 B 线程对集合进行修改(增加、删除、修改),或者 A 线程在遍历过程中对集合进行修改,都会导致 A 线程抛出 ConcurrentModificationException 异常。 具体效果我们看下代码: 执行后的效果如下图: 为什么在用迭代器遍历时,修改集合就会抛异常时? 原因是迭代器在遍历时直接访问集合中的内容,并且在遍历过程中使用一个 modCount 变量。集合在被遍历期间如果内容发生变化,就会改变 modCount 的值。 每当迭代器使用 hashNext()/next() 遍历下一个元素之前,都会检...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS6,CentOS7官方镜像安装Oracle11G
- SpringBoot2整合Redis,开启缓存,提高访问速度
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Hadoop3单机部署,实现最简伪集群
- MySQL8.0.19开启GTID主从同步CentOS8
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果