美图架构平台团队的主要工作,是给业务提供技术支撑,保障业务的稳定性;在减少故障方面,架构团队和 SRE 团队有比较紧密的配合和较多的实践。此前美图 SRE 团队也在 TakinTalks 稳定性社区分享了故障治理方面的经验和实践;今天换个角度,从架构团队视角,围绕压测平台的搭建,分享美图 2.409 亿月活用户的稳定性保障经验。
作者介绍
美图系统研发技术专家-陈潮兵
TakinTalks 社区专家团成员,2018 年加入美图,系统研发技术专家。目前在美图负责 Java 基础组件和配置中心、压测平台等服务,同时负责内容中台、订阅中台等中台项目。积极参与公司的架构演进,在服务高可用、稳定性保障方面有一定的经验和积累。
温馨提醒:本文约 5000 字,预计花费 8 分钟阅读。
后台回复 “交流” 进入读者交流群;
背景
起因:全年最严重的故障
2019 年的跨年夜,我们的业务出现了严重故障——由于对节假日的流量预估不足,跨年夜当天,美图核心服务出现了稳定性问题,整个故障持续了接近 2 个小时,是美图全年唯一的一次 A 级故障。
改进:加速压测平台建设
故障的原因有很多方面,根本原因我认为是当时对于节假日流量的增长没有做好预案,导致流量突增时,一些基础资源出现了瓶颈,进而导致大面积故障。在后面的故障复盘里,我们除了做链路优化和性能优化之外,还推进了一项措施,即通过线上压测来保障我们的节假日场景,做到故障的提前发现和跟进。
效果:可靠性被大规模验证
在那之后,每次大型节假日之前,我们都会进行线上服务压测,包括 2019 年的美图业务整体上云,我们也是依赖线上压测,在云上部署新服务后拷贝 IDC 的真实流量去压测,提前发现并修复了很多稳定性问题,最终我们的上云进展非常顺利。也就是,从跨年夜故障后,我们的服务再也没有出现过类似的问题了。
上面案例讲到了我们在稳定性方面的重要利器,即美图自研搭建的压测平台,我将结合一些搭建思路和压测实践给大家详细介绍。
一、压测要满足哪些业务诉求?
上面图里 9 月 10 号这天是今年的中秋节,可以看到这天我们服务的 QPS 比平常大了好几倍。美图公司有一个很重要的特点,就是节假日的流量特别大,比如说元旦、端午、中秋、国庆等节假日,节假日流量的峰值是日常流量峰值的好几倍,因为在节假日大家会有更多的照片美化、视频美化的需求。
下面是美图日常的流量情况。
大家可以看到在非节假日的时候,我们日常的场景也会存在流量突增的问题,但是整个时间其实就没有节假日那么长,它可能持续半小时左右,这种一般是由运营活动带来的。
所以美图的业务场景,总结来讲有两个,一个是节假日流量比日常大好几倍,第二个是日常流量存在突增的问题。
针对节假日流量大,日常流量突增的业务特点,要怎么去保障业务的稳定性呢?我们是通过压测来模拟复现这类场景,然后提前发现系统瓶颈,推动业务优化。
1.1 真实流量压测
在考虑如何做压测的时候,我们面临了一个问题——要采用哪种方式来进行压测?搭建一套拟真的环境,还是在真实环境上直接压测?我们的考量点是这样的——
首先,线上服务之间的依赖很复杂,调用链路众多,搭建拟真环境的难度其实是比较高的,投入会比较大。
然后,如果搭建了拟真环境,就需要在多套环境之间保证环境之间的一致性。
其次,就算能保证多套环境上部署的代码一致,但是实际上不同环境的时间还是会有差异,比如说服务依赖的网关、底层资源等等,都是会存在差异。
最后,如果只在拟真环境压测,压测成功没有问题,那线上就没有其他问题吗?这个答案其实也是否定的。
所以主要是出于拟真环境的搭建成本和维护成本,我们最后选择拷贝真实流量直接压测真实环境,基于真实流量拷贝回放是可以解决线上已有服务的压测问题的。
1.2 场景化压测
当然真实流量拷贝只能解决已有服务的压测问题,对于还未上线的服务是怎么做的?这种情况下我们一般是通过自己编排场景的需求,就是自己去编排压测场景,去构造压测流量来进行压测,我们会把这种称之为场景化压测。
所以我们的诉求是除了真实流量压测之外,还有场景化压测的需求。之前真实流量压测(拷贝线上真实流量做回放),这部分主要是由运维团队负责,自定义编排压测场景(场景化压测)主要由测试团队负责。
二、之前的压测是怎么进行的?
2.1 早期流量回放压测实践
首先是早期的流量拷贝回放的场景,下面图里是我们之前的做法。
这种压测方法,虽然可以简单地满足业务需求,但是压测过程中的主要步骤,都需要人工介入。
比如拷贝流量,需要运维先梳理这次要压哪个服务,然后找到对应服务的域名、对应域名的负载均衡机器是什么,再去起一个流量拷贝的服务,之后还要看好时间,定期去关掉这个服务,再把拷贝的流量文件做保存。在压测的时候,需要根据压测计划,手动申请施压机来进行扩容。如果压测过程中遇到压力不稳的问题,需要人工介入排查,人工去定位是什么问题导致的。
更要命的是,在压测过程中,如果被压服务出现了性能瓶颈,那这时候需要运维及时介入来停止压测。如果业务本身有降级手段还好,万一业务对应的降级措施,这时候只能依赖运维介入来做降级,那就很依赖运维的及时响应,如果运维响应不那么及时,可能就会导致因为压测造成了线上故障。
2.2 早期测试部门业务压测流程
对于自定义编排压测场景的压测,下面图里展示了我们之前的做法。
这块之前主要是测试团队负责,对于测试同学来说,首先他们需要去编辑压测脚本,然后在压测时,测试需要自己去申请施压机,然后在施压机上部署脚本去执行压测,压测结束之后他们还要自己去收集一些压测数据,观察被压服务有什么问题,有什么告警等等。整个过程其实对于测试同学来说比较复杂,执行一次压测的成本很大。
三、压测平台目标解决哪些问题?
针对早期的这些压测方法,我们总结了当时在压测方面的一些痛点,主要有下面几点——
压测的全部流程都需要人工介入,不管是在拷贝流量,或者施压机申请,压力调节,包括遇到问题怎么排查,以及最后整理报告,这些都需要人工介入。
因为人工介入的成本高,自动化程度其实就很低,压测效率低导致没办法去开展常态化的压测,所以之前一般是在大型节假日之前,我们才会做大规模的线上压测,日常没办法开展压测,因为太耗人力了。
除了压测效率的问题,我们其实还面临稳定性的问题。压测过程中我们经常会遇到压力不稳的问题,这类问题的定位比较困难。
所以总结来讲,我们有成本、效率、稳定性相关的问题,我们期望通过建设压测平台来进行优化,对于要建设的压测平台,我们有三个重要的目标——保证系统稳定性、提升效率、控制成本。
四、搭建压测平台的核心是什么?
上面说了我们期望去建设压测平台来解决我们的痛点,那下面我将会给大家介绍我们怎么去搭建压测平台。
4.1 压测流程
从系统搭建的角度,我们回顾一下压测的主要流程。
我认为压测流程主要有三个,在这三个流程中,我认为施压的部分是搭建压测平台的核心,因为它属于中间的部分,串联了压测的其他模块。
4.2 压测核心-施压机
4.2.1 选型前的思考
我会给大家介绍在施压机选型方面的一些考量点,首先在进行施压机选型时,我们考虑了几个问题——
-
施压机要具备哪些能力?
-
到底是要自研还是要借鉴社区的开源工具?
-
要怎么去面临技术选型的问题?
4.2.2 施压机能力
对于施压机的能力,结合压测场景,我梳理了我们认为施压机要支持的一些核心的功能。
支持 RPS/VU 压测模式:RPS 模式其实就是每秒请求数,VU 是指的是虚拟用户模式。简单讲一下这两个模式就是, RPS 模式是可以精准地控制服务打出来的压力,可以控制压测平台每秒打出来多少请求。这种模式一般是用在服务端的性能优化。比如说这个中秋节,要压的是日常的峰值的三倍或五倍,设定好压测目标之后,我们会设计好一些压测梯度,通过 RPS 模式来进行压测。VU 模式是指的虚拟用户模式,一般是用来探测系统的最大的并发数,就是系统能支持多少并发量,这种一般是用在客户端应用多一些,主要是用在客户端应用的一些压测。
支持不同压测协议:比如我们有 HTTP 的压测需求,同时也在做服务化的建设,所以还会有 RPC 的压测需求, DBA 团队、运维团队他们也有诉求,希望能够直接去压测 MySQL 和 Redis 实例,所以也有压测基础资源的需求,就需要压测平台能够支持不同的压测协议。
支持串联场景压测:对于测试团队来讲,他们一般是要自己去定义压测场景,所以需要支持一些串联场景的压测,就比如先登录再购买等等,会希望能串联起来做压测。
支持压测结果断言:对测试同学来说,他们还希望压测完去设置断言,即需要知道运行的结果对不对。
支持压测数据上报:我们需要知道施压机和被压服务的状态,所以我们需要能够支持把压测数据上报到监控平台。
支持压力调节:可以根据施压目标动态调节施压机的压力。
支持压测启停:对于施压机,我们需要能够控制施压机什么时候启动、什么时候停止。
4.2.3 选型机考量及对比维度
在选型时,我们主要会基于开发成本、扩展性、维护性这三方面来做对比。
对于施压机我们有比较多的功能诉求,在业界已经有比较成熟的实践,所以没有必要重复造轮子,所以我们着重考虑社区已有的工具来建设压测平台。我们挑选了一些社区活跃度高,且在业界有相关实践的压测工具来进行学习对比。
我们从开发语言、是不是支持分布式压测、能不能支持场景编排、能不能支持流量复制/回放、有没有压测报告、压测性能等等方面来做考量。
从上面的这个表格,能看到匹配度这几个都满足;团队熟悉度方面,测试团队基本之前都是用 JMeter 压测,JMeter 的开发语言跟团队技术栈匹配,JMeter 支持自己开发插件,业界也有一些公司有类似成功的案例,所以对于美图公司来讲,我们最终选型了 JMeter 作为施压机。
我们选型的时候就会发现 JMeter 其实存在一些问题,比如它的分布式部署成本高、施压机监控不完善、脚本维护不方便等等。而对于这些问题,我也会介绍我们是怎么去解决的。
4.3 其他关键问题
除了施压机之外,搭建压测平台其实还要考虑一些其他的关键问题。
首先是单机压力的调节问题,我们使用 JMeter 作为施压引擎,在 JMeter 之上去封装施压机,提供类似施压机启停、压力调节这些能力,通过这些能力来控制施压机的行为。
对于刚才上面有提到 JMeter 施压机分布式能力弱的问题,我们是自研调度中心来解决,后面也会给大家介绍在这方面的一些实践。
另外 JMeter 实际上有提供压测报告,但是 JMeter 监控告警能力比较弱,我们基于美图的监控平台,通过改造 JMeter 上报压测指标,来实现监控数据的打通。
对于分布式的压测来讲,会面临施压机的扩缩容问题,单机一定会有瓶颈,那么是一次性扩容好还是按需扩容、怎么去扩容?这里我们是去对接容器平台。美图有一些基础设施,而容器平台它恰好就能解决这种扩容缩容的问题,我们就把这些能力交给容器平台来做,只要去对接他们就好了。
JMeter 它的流量拷贝能力弱,这一块怎么做?我们选型了 GoReplay 来拷贝流量。选 GoReplay 主要是因为使用简单,组件性能高,GoReplay 在拷贝流量时,对负载均衡影响很小。
五、压测平台架构是怎么设计的?
我们把美图的压测平台整体是分成了四部分,首先有一个管理模块,我们把它称之为 PTS-WEB。这个管理模块里面主要有两个功能,一个是配置的管理功能,它能管理各种任务,比如流量拷贝的任务,或者是压测场景的任务、定时的任务,这些都由管理模块管理。
第二个是它会负责任务的调度。比如触发流量录制、触发压测都是由这个管理模块来触发的。这个管理模块底层数据会存储在 MySQL 和 Memcached 中,压测报表和流量文件,会存储在 OBS 中,服务底层会依赖容器平台,这个是管理模块的主要结构。
为了解决流量拷贝的问题,我们在 GoReplay 上封装了一个 Agent, 把它称为 GoReplay Agent ,是在 GoReplay 上提供了管理能力,可以通过这个 Agent 方便地控制什么时候启动流量拷贝任务,拷贝哪些流量、哪些端口、拷多久、什么时候停等等,都是在 GoReplay Agent 实现的。最后拷贝完的流量,需要去做协议的转换,最后上传到存储服务里,这些都是通过 Agent 实现。
那有了流量之后,在压测的过程中我们怎么做?在启动压测的时候,每一个压测场景的执行其实都是会起一个压测集群来负责。压测集群包括了两部分,一个是调度中心,一个是施压集群。这个调度中心我们称之为 PTS-Master ,施压集群里边的每一个施压节点,我们把它称之为 PTS-Slave,它就对应了施压机,然后 PTS-Master 对应调度中心,调度中心是用来管理一组施压机,这个是大概的一个关系。我们底层压测引擎这一部分用了 JMeter 的能力,在这个施压机之上,我们封装了像快速启停、快速调整压力的这些能力。
同时,施压机这边会去跟监控告警系统对接,通过施压机上报压测指标,上报到监控报警中心。施压机会给调度中心上报节点信息,会上报它的健康状态、预期的压力是多少、当前实际压力多少等等,然后会由调度中心来负责整个压测任务的压力调节,这个就是压测平台的一个主要的模块。
(美图压测平台展示-创建压测)
(美图压测平台展示-发起压测)
(美图压测平台展示-发起压测)
以上是美图压测平台的部分页面展示,那么在实际操作中——
1、GoReplay 如何和 JMeter 结合?
2、平台中需要开发哪些插件来辅助?
3、实操中遇到了哪些问题以及如何解决?
更多内容欢迎点击“阅读原文”,进入「TakinTalks 稳定性社区」,观看完整版视频内容。
了解更多美图压测平台细节,欢迎扫码进入「读者交流群」,和老师实时互动。
六、个人总结
最后我用两个词来概括搭建压测平台的最主要的经验——
第一个是合作共赢,要跟兄弟团队合作做资源的整合。
第二个是拥抱社区,上面我们很多的经验,是借鉴了社区的一些优秀的方案和实践,我们在社区的方案上去自研并做自己的优化。
如果能拥抱社区,基于前人的基础上搭建平台,能让我们少走很多的弯路。
回复【2202】获取讲师课件
回复【交流】进入读者交流群
声明:本文由公众号「TakinTalks 稳定性社区」联合社区专家共同原创撰写,如需转载,请后台回复“转载”获得授权。
本文来自投稿,不代表TakinTalks稳定性技术交流平台立场,如若转载,请联系原作者。