全链路压测流量模型

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了全链路压测流量模型相关的知识,希望对你有一定的参考价值。

参考技术A 现在全链路越来越火,各大厂商也纷纷推出了自己的全链路压测测试方案。特别是针对全链路压测流量模型,各家方案都有所不同。最近我看了一些这方面的资料,有一些感悟。分享给大家。

全链路压测流量模型的梳理呢,这里就先不讲了,各家公司自有司情在。因为主要是全链路压测模型的实现,其实实现也对应了流量模型的梳理结果。

业界常用的三种方一种:是基于业务模型的实现,一种是基于真实流量的录制回放,最后一种是灰度分流。

这个是一种比较常用的方式。首先要对公司业务模型进行梳理,也就是说对公司的业务链路进行梳理。这里的业务链路可能会比较复杂,不是像很多案例中到的了就非常流行畅的一条链路,中间很有可能会出现各种各样的支路。如果图图形化展示的话,某一条链路应该就是一个树形结构。树形结构的开始是用户的入口页一般就是入口页面的登陆,或者说是首页接口。树形结构的右侧是用户的出口,这里根据业务模型不同,用户的出口会非常的多,所以大多数来时候来讲,这就是一个分叉的树形结构。

要对这样的流量模型进行实现。是比较困难的。首先要梳理出这样的业务模型,就不太容易,再加上接口的相互调用啊,数据之间的相互依赖又可能是复杂程度增加一个量级。所以一般的实现方式就是做归拢。将比较复杂的树形结构简单化,或者干脆将以个业务联络分解成n个列有链路。然后分别实现。最终将流量汇聚,就变成了整个业务链路的流量模型实现。

在业务模型实现这个方向,各家都有不同的实现方式啊,基本上就分为工具以及脚本实现。我自己不怎么用工具做过接口的性能测试,全都是使用java和groovy脚本去实现的。首先,我会实现一个基于接口的业务测试框架,将每一个接口封装成一个方法。接口的参数即是这个方法的参数。然后将每一个用户封装成一个对象。将用户的各种信息变成这个对象的属性。然后用户在请求不同的接口的时候对用户的属性进行赋值这样就达到了一个参数传递的目的。然后通过调用不同的方法,我们就可以实现对不同接口的请求。通过控制参数或者说接口请求的频率,我们就可以达到控制当前用户。在整个业务链的走向。

基于流量录制和回放,这个是最容易实现的方式。也是最容易贴近真实情况的方式。哦,我接触到的主要有一个回放模型,就是用golang语言写的goreply。go语言的性能是非常好的,用于性能测试足够满足用户的需求。大多数公司都会选择在原生引擎的基础上做一些封装。然后对对业务进行一些兼容,最主要的还是适配流量来源。通常流量的来源是通过日志文件来获取的,但是我看行业内也有通过一些固定的流量存储分析引擎去完成。这里的技术我不是太熟,也就不多分享啦。

我觉得基于流量录制回放这种模式有一个比较难以解决的问题:流量的不可见性。一般来说,录制流量会非常大。介于几十万上百万之间。这么规模大的流量,是很难对他进行可视化的。常遇到的一个问题,就是对于一些请求量非常小的接口。录制的时候可能会录丢。还有一种就是录制流量的时间范围不会太广。那么录制出来的流量文件只能反映录制时的流量模型,并不能反映其他录制时间段的流量模型。如果某个服务的流量是根据时间变化的。那么就需要对多个时间段都录制流量,然后进行合并。由于流量的不可见性,所以对流量的模型进行分析,就会显得比较麻烦。

这是我在某个会议上看到大佬分享的一个方案。灰度大家听的可能比较多的是灰度发布。就是将服务或者app更新范围限制在某些一批人,或者说某个地理范围。这里讲的灰度分流,其实核心上差不多,就是将线上的一部分流量转到某些机器上。以实现对这些机器所在服务的一些压测。这种方案。基于线上流量完成,所以几乎不需要测试。投入过多的资源进行开发实现。这种方案有点儿基于业务模型和基于流量录制取了一个中间态。既能保证流量的真实有效性。又可以避免开发测试脚本带来的负担。

这种方式对于公司的架构,主或者说是分流的实现来说,技术难度是比较高的。因为他用的全都是用户的真实数据,所以一旦出现问题的话,这个问题影响范围不太可控,而且比较严重。对于接收灰度分流流量的机器来说,压测流量完全真实。但是他也无法避免基于流量录制,回放同样的问题。就是流量的不可见性以及流量与时间可能存在于一个关联关系并不是线性的。甚至这一点流量的灰度分流还不如流量的录制与回放。我想这也是。我身边接触到的公司,都没有采用这种方案的原因吧。

从流量打标到机器打标 - 达达全链路压测探索与实战


  • 1. 背景

  • 2. 全链路压测核心设计

    • 2.1 业界全链路压测

    • 2.2 达达全链路压测

    • 2.3 压测平台

  • 3. 全链路压测落地

    • 3.1 链路梳理

    • 3.2 优化预案设定

    • 3.3 精细化压测模型构建

    • 3.4 压测预热

    • 3.5 压测复盘

  • 4. 总结与收益

  • 作者简介


1. 背景


达达集团是 2014年在上海成立的本地即时配送平台, 过去7年中稳步前进; 2020年双11大促时, 日配送完成单量突破 1000万; 单量的增长需要稳定性的保障, 全链路压测在达达稳定性保障中扮演着重要角色,本文将阐述达达全链路压测的核心设计与落地。



2. 全链路压测核心设计


2.1 业界全链路压测


达达原压测方案是: 搭建一套跟线上 1:1 的压测环境, 在这套环境中进行压测, 此方案技术难度低, 实现简单, 但弊端也明显: 人力及机器成本随着生产环境规模的变大而变大; 于是我们调研了业界主流的 【流量打标】方案, 该方案原理是: 在请求的流量(HTTP,RPC,MQ)上打标, 所打的标示随着请求在各个服务之间流转, 从而使得压测流量与线上流量隔离; 在数据隔离这块:


  • DB 层: 使用 影子库/影子表 隔离数据。

  • Cache 层: 使用 影子缓存 隔离数据;。

  • MQ 层: 使用 影子队列 隔离数据。

从流量打标到机器打标 - 达达全链路压测探索与实战

图: 流量打标


 但这个方案适用于中间件统一的场景;而达达内部使用了各种类型的中间件, 比如 ORM 就有 Mybatis, Hiberante, JPA, 版本也不一致; 并且存在大量异构程序, 有 Java 的, 有Python 的; 若要实现【流量打标】方案, 势必会有大量业务改造, 因此我们放弃此方案。


2.2 达达全链路压测


在分析达达自身架构特点后, 我们在 2019年一季度研发了基于【机器打标】的压测方案 (数据使用 影子DB&Redis&MQ 隔离)。


从流量打标到机器打标 - 达达全链路压测探索与实战

图: 机器打标


以下是实现此方案的流程:


  • 机器抽象化: 所有 DB&Redis&ES 机器抽象成一个一个节点; 节点信息如下图。

  • 机器信息注册到注册中心: 所有节点信息注册到注册中心。

  • 服务接入链路治理SDK: 所有服务接入 "链路治理SDK", "链路治理SDK" 具有根据链路路由请求的能力。


从流量打标到机器打标 - 达达全链路压测探索与实战

图: 节点信息


节点信息说明:


  • cloud_name: 资源名称, 全局唯一, 一个资源可包含多个节点, 比如 mysql_cluster001 就可以包含一个主节点, 多个从节点。

  • node_name: 节点名称, 全局唯一, 通常使用 host+port。

  • host: host 信息。

  • port: 端口信息。

  • role: 角色, w: 写节点, r: 读节点。

  • dada_type: 资源类别, 有 mysql, redis, es 等。

  • data_link: 链路类别, 有 benchmark(压测), base(生产)。


方案中最重要的是 "链路治理SDK", 它的职责是: 根据链路类别路由请求流量; 如下图所示: 


从流量打标到机器打标 - 达达全链路压测探索与实战

图: 链路治理SDK


它的启动流程如下: 


  1. 注册服务节点信息。

  2. 根据本机的链路类别, 获取对应链路的存储节点信息。

  3. 根据存储节点信息, 建立起 DB,Redis, MQ 连接。


最终线上环境, 在机器维度形成两条链路, 处理生产流量的生产链路和处理压测流量的压测链路。


方案比较


下图是对【流量打标】【机器打标】的比较, 两种方案都有优缺点, 达达从安全及系统改造成本出发, 最终选择了【机器打标】方案。

从流量打标到机器打标 - 达达全链路压测探索与实战

图: 方案比较


2.3 压测平台


原压测方案使用 jmeter 进行压测, jmeter 属于老牌压测工具, 稳定性高且支持分布式; 但在压测场景复杂时,使用不够灵活; 达达的压测多数为复杂场景压测, 所以我们放弃原方案, 转而基于 jmeter 内核开发自己的压测平台; 以下是压测平台的整体架构:

从流量打标到机器打标 - 达达全链路压测探索与实战

图: 压测平台架构


主要由以下几个核心模块构成:


  • 前端服务: 提供 压测任务填写, 压测任务启动/停止, 压测结果展示等功能。

  • 压测任务解析器: 主要负责压测任务的解析, 存储。

  • 压测引擎: 负责将压测任务调度到执行器上执行 (定时执行 & 立即执行)。

  • 压测结果处理器: 负责对压测接口返回值解析, 统计, 异常处理, 并生成报表。


新压测平台的优势在于: 具有可视化的操作界面, 压测结果实时动态产出; 研发人员在压测平台配置 "发压性能参数", "造数据脚本" 就能直接执行。

从流量打标到机器打标 - 达达全链路压测探索与实战

图: 压测平台操作界面


压测引擎在施压时, 对应压测结果 (TPS&响应&错误率) 会实时展示到前端界面。


从流量打标到机器打标 - 达达全链路压测探索与实战

图: 压测平台结果输出



3. 全链路压测落地


整个全链路压测的落地分成: 压测前, 压测中, 压测后:


从流量打标到机器打标 - 达达全链路压测探索与实战

图: 压测落地方案


其中 压测前 有三个关键点: 压测链路梳理, 优化预案设定, 精细化压测模型。


3.1 链路梳理


链路的梳理非常重要, 它决定着压测链路需要部署哪些服务, 压测时哪些服务需要被关注。


以前达达通过人肉的方式梳理链路, 但是这种方案效率低, 不准确, 工作量大, 且当生产环境链路变更时, 我们不能即时感知到;  后面引入 APM(PinPoint), APM 有梳理链路的功能。


从流量打标到机器打标 - 达达全链路压测探索与实战

图: 链路梳理


但此方案还是没解决: "实时感知链路变更" 的问题; 为此我们在开发环境拉了条链路, 定时发请求以检测是否链路通畅; 若链路依赖有变化, 我们就能立刻知道。


3.2 优化预案设定


俗话说: 不打无准备之战, 压测就是为了提前发现高负载时系统可能出现的性能隐患, 那如何解决性能隐患呢? 通常在压测之前我们会准备一些性能优化预案, 常用预案如下:


  • 线程池/连接池 打满: 扩容线程池大小(服务CPU未超过阈值时) / 扩容业务服务。

  • Mysql 主从延迟: Mysql BinLog 调优 -> 升级机器配置 -> 垂直拆库 -> 水平拆库。

  • Redis 带宽打满: 带宽自动扩容。

  • MQ 消息堆积: 扩容消费消息的服务方。


因过去几年的业务的发展, 导致生产环境数据库单表单库的数据量一直在增长, 达达物流系统多次碰到 Mysql 主从延迟 ; 目前最常用的优化方案是  "Mysql BinLog 调优",  此方案主要调优以下两个参数:


  • binlog_group_commit_sync_delay: 表示事务提交后, 等待多少时间, binlog 再同步到磁盘, 默认0, 表示不等待(单位微秒)。

  • binlog_group_commit_sync_no_delay_count: 表示等待多少事务提交后, binlog 再同步到磁盘。


但此调优方案也有弊端: 参数调优后, 接口响应会有一定提升(如下图); 所以调优时需考虑业务能否容忍接口响应的上升。


从流量打标到机器打标 - 达达全链路压测探索与实战

图: 接口响应上升


3.3 精细化压测模型构建


随着业务的发展, 压测模型也在不断演进迭代中; 从一开始 "使用虚拟骑士, 单一按照接口TPS目标值压测"  到现在 "模拟生产活跃骑士, 引入时间&空间因素 构建压测模型", 模型越发精准。模型分成两类:


  • 数据模型: 骑士数据, 商户数据, 订单数据。

  • 流量模型: 订单下发, 配送履约。


从流量打标到机器打标 - 达达全链路压测探索与实战

图: 压测模型


数据模型: 



流量模型:


业界常用 【流量回放】方案, 将大促时生产环境的流量存储下来, 然后在压测环境进行回放。


从流量打标到机器打标 - 达达全链路压测探索与实战

图: 流量回放


此方案适用于读接口的压测, 但是达达的业务场景复杂, 主流程接口多写少读; 所以直接使用此方案肯定不行。


从流量打标到机器打标 - 达达全链路压测探索与实战

图: 业务主流程


鉴于不能直接使用【流量回放】, 达达选择了【人工构造流量】。影响构造流量真实性主要有两大因素: 时间, 空间。


时间:


在时间上, 达达一天有三个高峰期: 早&午&晚高峰, 每个高峰期 各个接口处于不同状态:


  • 早高峰: 发单, 接单, 订单详情 的请求量处于高峰, 其他接口请求量一般。

  • 午&晚高峰: 订单详情, 取货, 完成 的请求量处于高峰, 其他接口请求量一般。


图: 主流程接口请求量分布


所以压测时, 达达根据业务接口三个高峰期的特点, 设计两个压测场景(午高峰与晚高峰接口状态类似, 合并成一个压测场景), 进行压测。


空间:


在空间上, 订单与骑士不均匀的分布在各地, 有些区域人多单少, 有些区域人少单多, 而对系统影响最大的是人多单多的热点区域。


图: 订单热力分布


达达有个 查看周围X公里订单 的接口, 这个接口的性能跟 热点区域的个数, 每个热点区域内的单量, 每个热点区域内的运力 关系比较大; 为了搞清这几点, 我们分析大促时生产的流量, 根据 geohash 把全国划分成一个个正方形区域, 统计每个正方形区域内的订单及运力; 最后再在压测环境还原并放大。



然后就是 压测中, 主要有这几块: 接口验证, 压测预热, 压测实施, 性能指标观察, 性能问题记录。其中压测预热非常重要, 它决定了压测结果的准确性。


3.4 压测预热


早期每次压测得到的接口响应都比生产环境慢一点, 后面发现: 生产环境的部分数据是热数据, 而压测环境全是冷数据, 这导致压测刚开始进行时, 接口响应偏高, 等过了一分钟后, 响应逐渐降低并趋于平稳; 后面引入压测预热, 使得压测环境的数据, 部分是热数据, 部分是冷数据, 以达到跟生产环境数据一致的效果。



最后就是 压测后; 压测后主要是: 压测报告的生成, 性能隐患定位与优化, 系统容量预估, 压测复盘。下面说一下压测复盘。


3.5 压测复盘


每次的大促复盘, 都能找到下次压测优化的方向; 复盘中最重要的是: 比较 生产与压测环境的 接口TPS&响应,中间件核心指标; 通过这些数据的比较来验证并优化 压测模型。



4. 总结与收益


全链路压测从 2019年一季度立项, 已经历了 4次大促压测考验, 并且完成了目标; 而在全链路压测实施的过程中, 我们认为有三大关键:


  • 流量的隔离: 基于【流量打标】, 达达研发出【机器打标】的隔离方案, 使得压测流量与生产流量完全隔离。 

  • 数据的隔离: 基于安全考虑, 达达选择 影子库, 影子缓存, 影子队列, 从而实现生产与压测数据的彻底隔离; 得益于这一点, 压测的实施在白天/晚上随时可进行。

  • 精细化压测模型构建: 压测模型是否跟生产环境相近, 直接影响了压测结果的准确性; 我们参考生产环境大促高峰期的流量, 从时间&空间维度分析, 制作出与大促时相近的压测流量, 从而保证数据模型的真实性。


整个项目的收益也非常明显, 具体从以下两方面分别来看:


  • 稳定性: 目前连续两年大促, 全链路压测每次都能挖掘出10 多项性能隐患, 从而保障了大促的平稳度过。

  • 效率: 相比原先搭建一套独立压测环境的方案, 现在的方案在机器成本上降低 40%, 人效上提升 65%。


当然此方案还有待提升的点, 比如 成本问题; 目前从安全角度出发, 达达通过影子库/缓存实现数据的隔离, 但影子库相比影子表方案机器成本高, 那如何在 安全与成本之间找到平衡, 是压测优化的方向; 另外, 除了挖掘系统隐患点, 全链路压测能否给 "智能运力调度" "运力的合理配置" 提出更多建议, 这也是我们思考的。



作者简介


  • 徐建康: 达达集团高级工程师, 2018年加入达达集团, 负责 达达 2019年&2020年 4次大促压测, 目前投入到 达达智配 项目中, 致力于为即时配送行业提供优质的软件。

  • 顾宝碗: 达达集团架构师, 2019年加入达达集团, 负责 微服务治理,数据源高可用等模块。

  • 张鹏: 达达集团高级测试工程师, 2018年加入达达集团, 负责达达即时配送的测试。



达达集团目前还处于高速成长期, 欢迎对技术有追求的同学加入, 可发送简历至: tuijian@imdada.cn, 邮件标题: 姓名-上海物流-Java高级开发工程师/资深测试工程师



以上是关于全链路压测流量模型的主要内容,如果未能解决你的问题,请参考以下文章

全链路压测:逼近业务真实模型安全隔离常态化

有赞全链路压测实战

有赞全链路压测实战

全链路压测:系统整体容量保障的“核武器”

全链路压测最佳实践

阿里巴巴的全链路压测