分享一个大牛的人工智能教程。零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请点击http://www.captainbed.net
什么是全链路压测
基于实际的生产业务场景、系统环境(生产环境),模拟海量的用户请求和数据对整个业务链(通常是核心业务链)进行压力测试,并持续调优的过程。
为什么要做全链路压测
原因在于真实的业务场景下,每个系统的压力都比较大,而系统之间是有相互依赖关系的,单机压测没有考虑到依赖环节压力都比较大的情况,会引入一个不确定的误差。这就好比,我们要生产一个仪表,每一个零件都经过了严密的测试,最终把零件组装成一个仪表,仪表的工作状态会是什么样的并不清楚。
全链路压测解决什么问题
解决在业务场景越发复杂化、海量数据冲击下系统整个业务链的可用性、服务能力的瓶颈等问题。
面对的问题点以及解决方案
一句话的全链路压测方案
在线上环境,针对全业务核心链路,在有流量干预的情况下,以数据隔离的方式仿真真实用户行为进行压测
业务模型梳理
首先应该将核心业务和非核心业务进行拆分,确认流量高峰针对的是哪些业务场景和模块,针对性的进行扩容准备。
数据模型构建
数据的真实性和可用性:从生产环境完全移植一份当量的数据包,作为压测的基础数据;然后基于基础数据,通过分析历史数据增长趋势,预估当前可能的数据量。
数据脱敏
数据隔离:为了避免造成脏数据写入,需要将压测数据隔离处理,通过落入影子库、mock对象等手段,来防止数据污染。
压测工具选型
使用分布式压测的手段来进行用户请求模拟,目前有很多的开源工具可以提供分布式压测的方式,比如JMeter、nGrinder、Locust等。
可以基于这些压测工具进行二次开发,由Contorller机器负责请求分发,Agent机器进行压测,然后测试结果上传Contorller机器。考虑到压测量较大的情况下回传测试结果会对agent本身造成一定资源占用,可以考虑异步上传。
压测环境
生产环境
系统容量规划
首先应该对单个接口单个服务进行基准测试,得到一个基准线,然后进行分布式集群部署,通过Nginx负载均衡。
至于扩容,要考虑到服务扩容和DB资源扩容,以及服务扩容带来的递减效应。
在大流量冲击情况下,可以考虑队列等待、容器锁、长连接回调、事务降级等方式来解决。
容量规划一般分为四个阶段:
-
业务流量预估阶段:通过历史数据分析未来某一个时间点业务的访问量会有多大;
-
系统容量评估阶段:初步计算每一个系统需要分配多少机器;
-
容量的精调阶段:通过全链路压测来模拟用户行为,在验证站点能力的同时对整个站点的容量水位进行精细调整;
-
流量控制阶段:对系统配置限流阈值等系统保护措施,防止实际的业务流量超过预估业务流量的情况下,系统无法提供正常服务。
生产环境进行单台机器压力测试的方式主要分为4种:
- 模拟请求:通过对生产环境的一台机器发起模拟请求调用来达到压力测试的目的
- 复制请求:通过将一台机器的请求复制多份发送到指定的压测机器
- 请求转发:将分布式环境中多台机器的请求转发到一台机器上
- 调整负载均衡:修改负载均衡设备的权重,让压测的机器分配更多的请求
流量控制框架可以从三个纬度着手:运行状况、调用关系、流控方式。应用可以灵活的根据自己的需求,任意组合。
-
第一步,我们在程序入口给所有的方法都进行埋点;
-
第二步,我们把这些埋点方法的运行状态,调用关系统计记录下来;
-
第三步,我们通过从预设好的规则中心接收规则,来根据第二步中统计到的系统状态进行控制。
系统资源监控
现在有很多优秀的专业监控工具,比如Nmon、Zabbix,全链路监控工具Zipkin、PinPoint以及携程开源的全链路监控工具CAT。
或者可以针对需要,二次开发JVM自带的一些监控工具,做到实时全方位监控。
参数调优
压测之后肯定会发现大量的参数设置不合理,比如:内核网络参数调整(比如快速回收连接)、Nginx的常见参数调优、PHP-FPM的参数调整等,可查看资料解决。
缓存和数据库
- 重要业务是否有缓存
- Redis CPU过高可以重点看下是否有模糊匹配、短连接的不合理使用、高时间复杂度的指令的使用、实时或准实时持久化操作等。同时,可以考虑升级Redis到集群版
- 重要数据库随着压测的进行和问题的发现,可能会有索引不全的情况
压测流量标记
搭建Trace系统
全链路压测的设计方案
全链路压测的关键组件
-
数据工厂,负责造请求数据。
-
大流量下发器,产生很大的压力去压系统。
-
线上服务集群同时处理压测请求 + 正常请求。
-
压测流量落影子存储,正常流量落正常存储。
-
压测流量对于外部的依赖走 Mock 服务器,正常流量走正常外部集群。
-
水位检测,需要检测存储 + 线上应用服务器的健康度,并且能够干预流量下发。
数据工厂
数据工厂是压测的一个核心部件,主要由 Hive 表的集合 + 各种导入、导出脚本组成。
数据工厂的目的是保存压测需要准备的所有数据,数据需要做清洗。
影子存储的设计与路由能力
-
DB、路由方式由 RDS 提供,存储可以有两种方式:
-
影子表与正常表存在同样的 instance、不同的 schema 中。这个方案不需要增加额外的存储开销,相对更便宜,但是风险较高(把库压死了会影响线上业务)。
-
影子表与正常表存在不同的 instance、相同的 schema 中。这个方案相对较贵,需要额外搭建 DB 集群,但是安全性较高。
-
-
Redis:通过 key 值来区分。压测流量的 key 值加统一前缀,通过 Redis-Client 做路由。
-
HBase:通过命名空间做隔离。影子空间加前缀,提供统一的 HBase Client 做数据访问,由该 Client 做路由。
-
ES:通过 index 名字来区分。影子的索引统一加前缀,提供统一的 ES Client 做数据访问,由该 Client 做路由。
线上应用集群的变更
-
统一线上应用对于数据的访问(DB+ES+HBase+Redis),提供统一的 Client。
-
由于线上的应用都是服务化工程,远程调用时,必须具备压测流量的标记透传能力。
-
线上的少部分应用,需要访问第三方服务,比如:物流、支付。这些应用需要改造为压测的流量直接访问 mock 服务器。
分布式流量下发器设计与链路设计
可选用 Gatling 作为流量下发器实现。
数据文件的内容:每一种场景都有不同的数据文件,数据文件由场景相对应的多种 url 组合而成。
流量下发脚本的内容:流量下发脚本的核心是控制漏斗转化率,Gatling 提供天然的转化率配置脚本,用起来非常方便。
水位检测系统的能力设计
以实时计算的方式,一边采集各个应用系统的资源使用情况 + 接口耗时 + 业务正确率,一边向 Gatling 发送流量干预信号,以做到自动保护系统的目的。
如果时间有限,可以人肉查看实时监控界面的方式,人为去干预 Gatling 的流量下发情况。
全链路路压测的实施
这里会涉及到多个业务模块,涉及的团队会特别多。
可以把链路压测的实施分为以下几个阶段:
-
基础中间件开发,各种框架升级开发,压测器研究与脚本开发。
-
业务升级与线下验证(人工点击,数据落影子库)
-
业务升级与线上验证(人工点击,数据落影子库)
-
数据工厂数据准备。
-
小流量下发验证(用 gatling 下发,数据落影子库)
-
大流量量压测与系统扩容
压测过程中的重要细节与把控
流量爬升
全链路压测,目的一般是给扩容 / 优化做方向性的指导。可以采取阶段性的爬坡打流量,然后把系统的能力一段一段提升上去。
非核心链路进核心链路的问题
正常来说,非核心链路,在大促来临时不会扩大多少容量。当压测的压力增大时,很容易通过系统报警查到。
当发现这个问题的时候,一定要坚决要求业务方做系统改造,把非核心系统的强依赖去掉。解耦的技术有很多,需要根据不同的业务规则来选择方案。比如:业务降级、通过中间件解耦、异步化等。
上下游扩容 / 代码优化的选择
一般来说,在压测的过程中,当碰到压测流量不能再升高的时候,会有很多原因,比如:
-
下游的某些服务化工程的能力达到瓶颈了,导致网关 RT 值升高,拖累整个集群的 QPS 上不去。
-
网关应用自身的能力达到瓶颈。
-
中间件 / DB 能力达到瓶颈。
-
Job 的能力达到瓶颈,导致数据处理不够及时。
-
流量集中的页面,消耗了集群大量资源。
针对 2、3、4 这样的情况,我们的选择是毫不犹豫地加机器,代码优化的性价比较低。
针对第 1 种情况,需要做一些分析,如果这样的能力是在系统设计者的预期之内的,可以选择加机器,如果完全超乎意料的,一定需要通过程序优化来提升能力,否则加了资源,可能还是瓶颈。
针对第 5 种情况,一定要做的事情是静态化。因为这些流量集中页面,一般都是展示性质的。不管如何做应用内的优化,获得的能力提升远不如做静态化的收益大。