字节跳动全链路压测(Rhino)的实践

1. 背景

随着公司业务的不断扩张,用户流量在不断提升,研发体系的规模和复杂性也随之增加。线上服务的稳定性也越来越重要,服务性能问题,以及容量问题也越发明显。

因此有必要搭建一个有效压测系统,提供安全、高效、真实的线上全链路压测服务,为线上服务保驾护航。

关于全链路压测的建设,业界已经有了非常多文章,但是涉及到具体的技术实现方面,却很少介绍。本文想通过梳理全链路压测系统从设计到落地的整个实践过程,来详细介绍全链路压测系统具体是如何设计,以及如何落地的。希望能从技术落地实践的角度,给同行业的同学一些参考和启发。

2. 解决方案

2.1 业内实践

全链路压测在业内已经有了广泛的实践,如阿里的 Amazon、PTS[1][2],美团的 Quake[3][4],京东的的 ForceBOT[5],高德的 TestPG[6]等等,都为我们提供丰富的实践经验,和大量优秀的技术方案。我们广泛吸收了各大互联网公司的全链路压测建设经验,并基于字节跳动业务需求,设计开发了一个全链路压测系统 Rhino。

2.1 架构图

Rhino 平台作为公司级的全链路压测平台,它的目标是对全公司所有业务,提供单服务、全链路,安全可靠、真实、高效的压测,来帮助业务高效便捷的完成性能测试任务,更精确评估线上服务性能&容量方面风险。

因此在 Rhino 平台设计之初,我们就定下以下目标:

  • 安全:所有压测都是在线上完成的,所以理论上所有的压测对线上用户都是有损的。压测平台将从服务状态,以及压测数据两方面去保证压测的安全性。

  • 高效:较少压测脚本编写成本,数据构造和压测监控成本,尽量自动化完成压测过程的各个阶段。

  • 准确:精确的压力控制,准确的链路压测监控,精确的压测报告结果,以及性能&容量数据。

  • 高覆盖:需要支撑公司内不同的业务线的压测需求,如搜索,广告,电商,教育,游戏等等。

Rhino 是一个分布式全链路压测系统,可以通过水平扩展,来实现模拟海量用户真实的业务操作场景,对线上各种业务进行全方位的性能测试。它主要分为控制中心(Rhino Master)模块,压测链路服务模块,监控系统模块,压测引擎模块,如图。(每一个模块都是由多个微服务来完成的。如下图每个实线图都代表一个微服务或多个微服务)。

3. 核心功能介绍

搭建全链路压测平台,最核心主要有:数据构造、压测隔离、链路治理、任务调度、压测熔断、压测引擎、压测监控等。下面我们将从这些方面详细介绍下,在 Rhino 平台中是如何设计和实现的。

3.1 数据构造

压测过程中数据构造是最重要,也是最为复杂的环节。压测数据的建模,直接影响了压测结果的准确性。

  • 对于服务性能缺陷扫描,性能调优,以及新上线服务,推荐构造 Fake 数据,来压测指定路径。

  • 对于线上容量规划,性能能力验证,以及性能 Diff,推荐使用线上真实流量,使压测结果更贴近真实情况。

  • 对于涉及到用户账号,用户登录态保持的情况,推荐使用压测专属测试账号,避免影响线上真实用户。

基础数据构造

为了高效的构造特定的 Fake 压测数据,Rhino 压测平台提供大量数据构造方式:

  • CSV 文件:按列分割数据,字段名取 CSV 文件第一行。数据读取方式是按行递增循环。如果一个压测任务会拆分成多个 Job,那么数据文件也会拆分,避免 Job 之间的数据重复。

  • 自增:变量类型均为数字类型。每次发压时+1,到最大值后从最小值循环使用。

  • 随机:变量类型均为数字类型。每次发压时随机生成。

  • 常量:Constant,可自定义为任意值。

压测账号

在压测过程中,有些压测请求需要进行登录,并保持会话;此外在很多压测请求中涉及到用户账号信息UserID,DeviceID等数据。用户账号的构造问题,一直是压测过程中非常棘手的问题。Rhino平台打通的用户中心,设置了压测专属的账号服务,完美地解决了压测过程中的登录态,以及测试账号等问题。具体流程和使用界面,如下图。

3.2 压测隔离

压测隔离中需要解决的压测流量隔离,以及压测数据的隔离。

压测流量隔离,主要是通过构建压测环境来解决,如线下压测环境,或泳道化/Set 化建设,将压测流量与线上流程完全隔离。优点是压测流量与线上流量完全隔离,不会影响到线上用户。缺点:机器资源及维护成本高,且压测结果需要经过一定的换算,才能得线上容量,结果准确性存在一定的问题。目前公司内压测都是在线上集群上完成的,线上泳道化正在建设中。

压测数据隔离,主要是通过对压测流量进行染色,让线上服务能识别哪些是压测流量,哪些是正常流量,然后对压测流量进行特殊处理,以达到数据隔离的目的。目前 Rhino 平台整体压测隔离框架如图。

压测标记

压测标记就是最常见的压测流量染色的方式。

  • 对于 RPC 协议,会在请求的头部中增加一个 Key:Value 的字段作为压测标记。

  • 对于 HTTP 和其他协议,会在请求头,自动注入一个 Stress 标记(Key-Value) 。

  • 压测标记 Key:Value,其中 key 是固定的 Stress_Tag 值,但是每个压测任务都有唯一的 Stress_Value 值,主要用于解决压测数据冲突,以及性能问题定位。

压测标记透传

目前公司内各个基础组件、存储组件,以及 RPC 框架都已经支持了压测标记的透传。其原理是将压测标记的 KV 值存入 Context 中,然后在所有下游请求中都带上该 Context,下游服务可以根据 Context 中压测标记完成对压测流量的处理。在实际业务中,代码改造也非常简单,只需要透传 Context 即可。

Golang 服务:将压测标记写入 Context 中。

Python 服务:利用 threading.local()存储线程 Context。

Java 服务:利用 ThreadLocal 存储线程 Context。

压测开关

为了解决线上压测安全问题,我们还引入了压测开关组件。

  • 每个服务每个集群,都有一个压测开关。只有打开压测开关时,压测流量才能流入到服务内,否则就会被底层微服务框架直接拒绝,业务层无感。

  • 在每个IDC区域,都

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值