生成式AI领域的最新成果都在这里!抢 QCon 展区门票 了解详情
写点什么

有赞 11·11:全链路压测方案设计与实施详解

  • 2017-11-10
  • 本文字数:4940 字

    阅读完需:约 16 分钟

2017年双十一即将来临,对于买家来说是一年一度的购物狂欢,可是对于电商公司的技术人员来说,却是一年一次的大考。如何用更少的预算完成指定当前业务规模的流量高峰,是技术的永恒主题。

由 InfoQ 举办的 ArchSummit 全球架构师峰会即将于 12 月 8-11 日北京举行,大会与阿里巴巴合作策划了双 11 架构专场,并邀请了顶级技术专家担任出品人,设置了“新一代 DevOps”、“人工智能与业务应用”、“架构升级与优化”等 17 个热门话题,目前大会日程已出,欢迎前来讨论交流。

有赞在双十一之前完成了全链路压测方案,并把它用于大促的扩容和容量验证,取得了不错的成果。

在电商公司待过的技术同学都知道,在大促来临时,整个集群的最高峰压力将是正常时间的几十倍,最高峰持续的时间会特别短,然后回落到正常水平的几倍。所以,我们可能会自然而然地想到,把整个集群扩容几十倍的机器,在双十一当天应对几十倍的流量,然后第二天减至正常量,就可以完成大促的考验。事实情况是否真的这么简单?

大促保障的困难

用户购买商品的链路是一条很长很复杂的系统集群,中间会涉及到店铺、商品、会员、营销、交易、支付等 6 大核心模块,每个模块又会涉及到多个不同的服务化系统单元,我们把这一条骨干的链路就叫做核心链路。

大家都知道,双十一当天,真正爆增的其实是买家的购买量,像开店 / 商品上架等功能,其实并发量没什么变化。也就是说,真正的压力其实是在核心链路上面,如果把所有的系统都扩容几十倍,本身就是一个很大的浪费。正常来说,一个稍有规模的电商公司,日常有几千台机器维持正常的运转,本身就是一个较大的开销,如果突增几十倍的系统开销,对于公司的财务也是很大的压力。所以,一个较理想的方法,是只把核心链路的系统扩大几十倍的系统吞吐量,就可以达到目标。

困难一

大型的分布式系统其实错综复杂,公司需要维持成百上千的服务化系统。理论上来说, 只有少部分系统是核心链路的系统。但是在实际情况下,因为公司人员的关系,可能会把某些非核心系统,不知不觉加入到了核心链路中。所以,第一件要做的事情,就是把非核心系统从核心链路上剔除。

困难二

一般公司都会在线下搭建性能测试环境,在该环境下,我们的测试同学可 以借助一些测试工具,去压单机单接口的性能。假如,店铺的首页面,我们在性能测试环境下,得出单机单接口的 QPS 峰值是 500,这是否意味着, 要达到 10w 的 QPS,我只需要设置 200 台机器就可以了呢?答案当然是否定的。因为任何的页面接口都不是单独存在的,都会受到公共资源的制约,如:DB、Redis、MQ、网络带宽等。比如当店铺首页达到 10w QPS 的时候,商品详情页可能要达到 8w 的 QPS了,也会消耗公共资源。当公共资源的能力下降时,势必会影响所有的系统。所以,通过单机性能算出来的理论值,跟实际情况会相差很远。

困难三

正常来说,任何大促都会有业务目标,这个目标一般是拿 GMV 进行评估。但是我们在进行系统容量评估的时候,一般会想扩大多少台机器。那么 GMV 跟核心链路各个系统之间的机器数量的转化关系是什么样的?

困难四

做过大型分布式系统的同学,可能都知道一个事实,即整个集群的性能其实取决于接口的短板效应。而这个短板的接口,在正常的流量下,是不会显现出来的。只有集群的整体压力达到一定值的情况下,才会偶尔显现, 然后造成雪崩效应,拖累整个系统集群。所以,如何在大促之前找到这些短板,然后把它们一个一个优化,这件事情就显得非常重要。

困难五

应用系统的扩容相对而言是比较简单的,完成大促之后,可以很容易归还。但是 DB 等核心资源的扩容其实并不容易,而且资源不可能归还(数据不不可丢失)。

事实是检验真理理的唯⼀一标准,上面提到的五个困难,其实都可以用线上真实压测的办法去检验。业内大型电商公司,会用全链路压测的方案去指导扩容的进程,有赞也不例外。今年双十一,有赞用该方案完成了对核心链路20 倍的扩容,但是整个集群的规模只是扩大了了一倍多一点。

有赞全链路压测的设计方案

全链路压测的目标是让双十一要发生的事情提前发生,并验证在该情况下系统表现良好。做线上压测,有一个很重要的原则:线上系统是不允许有脏数据的。

有赞的压测设计方案,可以用几句简单的话做概括:

  • 压测流量落影子库,正常流量落正常库。
  • 压测不能把系统压崩溃。
  • 压测是模拟双十一流量最高峰时用户的购物行为,所以综合性的流量模型需要跟实际情况相符。

全链路压测的总体设计

有图有真相,我们先上图。

在上述图中,我们明显可以看到,全链路压测有几个关键部分:

  1. 数据工厂,负责造请求数据。
  2. 大流量下发器,产生很大的压力去压系统。
  3. 线上服务集群同时处理压测请求 + 正常请求。
  4. 压测流量落影子存储,正常流量落正常存储。
  5. 压测流量对于外部的依赖走 mock 服务器,正常流量走正常外部集群。
  6. 水位检测,需要检测存储 + 线上应用服务器的健康度,并且能够干预流量下发。

关键模块的设计方案

数据工厂设计

数据工厂是压测的一个核心部件,主要由 Hive 表的集合 + 各种导入、导出脚本组成。

数据工厂的目的是保存压测需要准备的所有数据,数据需要做清洗,比如:

  • 商品未下架
  • 商品的库存无限
  • 营销活动的信息有效,未过期
  • 店铺未关闭等等

场景的定义:场景的定义关系到数据的准备,正常来说,压测只会压随着买家人数暴增、系统的压力立即增加的场景,我们把这个场景涉及到的系统叫做“核心链路”。

影子存储的设计与路由能力

  1. DB、路由方式由 RDS 提供,存储可以有两种方式:
  • 影子表与正常表存在同样的 instance、不同的 schema 中。这个方案不需要增加额外的存储开销,相对更便宜,但是风险较高(把库压死了会影响线上业务)。
  • 影子表与正常表存在不同的 instance、相同的 schema 中。这个方案相对较贵,需要额外搭建 DB 集群,但是安全性较高。

我们选择的是第一个方案。
2. Redis:通过 key 值来区分。压测流量的 key 值加统一前缀,通过 Redis-Client 做路由。
3. HBase:通过命名空间做隔离。影子空间加前缀,提供统一的 HBase Client 做数据访问,由该 Client 做路由。
4. ES:通过 index 名字来区分。影子的索引统一加前缀,提供统一的 ES Client 做数据访问,由该 Client 做路由。

线上应用集群的变更

  1. 统一线上应用对于数据的访问(DB+ES+HBase+Redis),提供统一的 Client。
  2. 由于线上的应用都是服务化工程,远程调用时,必须具备压测流量的标记透传能力。
  3. 线上的少部分应用,需要访问第三方服务,比如:物流、支付。这些应用需要改造为压测的流量直接访问 mock 服务器。

全布式流量下发器设计与链路设计的能力

我们选用 gatling 作为我们的流量下发器实现。

数据文件的内容

每一种场景都有不同的数据文件,数据文件由场景相对应的多种 url 组合而成。比如:我们本次压测会压“无优惠的场景、秒杀场景、满减场景、拼团场景” 等等。无优惠的场景分为“店铺首页、商品详情页、加购物车页、下单页、支付页、支付成功页”等等。这个文件不涉及漏斗转化率。一般来说,一个数据文件很大(至少是 G 级别的)。所以我们的数据文件内容格式为:

  • 所有的数据⽂文件
    • 无优惠的场景数据文件
      • 场景集合 1
        - 店铺首页 URL
        - 商品详情页 URL
        - 加购物车页 URL
        - 下单页 URL
        - 支付页 URL
        - 支付成功页 URL
      • 场景集合 2
        - 店铺首页 URL
        - 商品详情页 URL
        - 加购物车页 URL
        - 下单页 URL
        - 支付页 URL
        - 支付成功页 URL
    • 秒杀场景数据文件
    • 满减场景数据文件
    • 拼团场景

流量下发脚本的内容

流量下发脚本的核心是控制漏斗转化率:

  1. 不同场景的流量配比。
  2. 每个场景下面,url 从上往下的漏斗转化率。

gatling 提供天然的转化率配置脚本,用起来非常方便。有兴趣的同学可以自行Google。

水位检测系统的能力设计

这个是一个很重要的模块,在项目启动之初,我们希望以实时计算的方式,一边采集各个应用系统的资源使用情况 + 接口耗时 + 业务正确率,一边向 gatling 发送流量干预信号,以做到自动保护系统的目的。由于时间关系,我们并未实现这一方案。取而代之的是人肉查看实时监控界面的方式,人为去干预 gatling 的流量下发情况。

全链路路压测的实施

如果实施过全链路压测的项目,大家都会有一个共同的感受:做基础的组件容易,让核心业务去完成相关的升级与验证工作很难。原因只有一个:需要用全链路压测的公司,业务规模都很大,涉及的团队会特别多。梳理理清楚庞大的业务,让所有的业务团队一起发力,本身就是一件很难的事情。

我们把链路压测的实施分为以下几个阶段:

  1. 基础中间件开发,各种框架升级开发,压测器研究与脚本开发。
  2. 业务升级与线下验证(人工点击,数据落影子库)
  3. 业务升级与线上验证(人工点击,数据落影子库)
  4. 数据工厂数据准备。
  5. 小流量下发验证(用 gatling 下发,数据落影子库)
  6. 大流量量压测与系统扩容

第 2、3、5 阶段,需要借助业务测试同学的力量;第 4 阶段,需要借助业务开发同学的力量;第 6 阶段,则需要借助业务团队 + 运维同学的力量。

由于每个阶段人员都不太一样,所以需要每一个阶段都组织不同成员的虚 拟小组,借助各个团队的力量完成相应的工作。

压测过程中的重要细节与把控

流量爬升的规律

正常来说,在大促之前做压测,目的一般是给扩容 / 优化做方向性的指导。

假设我们双十一需要扩大 20 倍的容量以应对高峰,那我一定不会一开始 就拿 20 倍的流量去压我们的系统,因为这样做的话,所有的系统都会在一瞬间就挂掉,这样没有任何意义。我们的做法是,阶段性的爬坡打流量,然后把系统的能力一段一段提升上去。

例如:

  1. 第一天,我们会以日常流量的最高峰为起始流量,然后爬坡到一个流量高峰 A,记为第一天的目标。在压测之前先做一次扩容。在压测中,碰到了某个瓶颈了,通过增加该系统的机器来提升能力。
  2. 第二天,我们以 A 为起始流量,然后再次爬坡到 B。同样压测前做扩容 + 压测中碰到瓶颈加机器。
  3. 以此类推,一直到最终流量达到目标流量为止。
  4. 每一天的压测,也需要以慢慢爬坡的方式提升流量。在爬坡的某个高度稳定 5 分钟,然后再次爬坡。稳定时间 5 分钟,爬坡时间 30 秒。

非核心链路进核心链路的问题

发现并解决这个问题,本身就是压测的目的之一。

正常来说,非核心链路,在大促来临时不会扩大多少容量。当压测的压力增大时,很容易通过系统报警查到。

当发现这个问题的时候,一定要坚决要求业务方做系统改造,把非核心系 统的强依赖去掉。解耦的技术有很多,需要根据不同的业务规则来选择方案。比如:业务降级、通过中间件解耦、异步化等。

上下游扩容 / 代码优化的选择

一般来说,在压测的过程中,当碰到压测流量不能再升高的时候,会有很多原因,我们碰到的情况有以下几种:

  1. 下游的某些服务化工程的能力达到瓶颈了,导致网关 RT 值升高,拖累整个集群的 QPS 上不去。
  2. 网关应用自身的能力达到瓶颈。
  3. 中间件 /DB 能力达到瓶颈。
  4. job 的能力达到瓶颈,导致数据处理不够及时。
  5. 流量集中的页面,消耗了集群大量资源,如:店铺首页、商品详情页等。

针对 2、3、4 这样的情况,我们的选择是毫不犹豫地加机器,代码优化的性价比较低。

针对第 1 种情况,需要做一些分析,如果这样的能力是在系统设计者的预期之内的,可以选择加机器,如果完全超乎意料的,一定需要通过程序优化来提升能力,否则加了资源,可能还是瓶颈。

针对第 5 种情况,一定要做的事情是静态化。因为这些流量集中页面,一般都是展示性质的。不管如何做应用内的优化,获得的能力提升远不如做静态化的收益大。

未来展望

全链路压测的方案有赞只是初试牛刀,我们已经看到了这个方案在提升 + 验证集群处理能力方面巨大的价值。当前,这个方案做得还较粗糙,存在一些问题:

  1. 压测只能在夜间做。
  2. 压测中需要有很多业务开发人员陪同。
  3. 链路规划复杂度太高。
  4. 压测控制台的稳定性还不够高。
  5. 水位检测与流量干预是通过肉眼观察监控来实现。

后续我们团队会继续投入大量精力去完善整个方案。希望可以将压测方案变成:

  1. 线上测试链路的机器人,实时检测线上系统的正确性,同时没有脏数据干扰。
  2. 测试同学手里的工具,做到流量压测常规化,开发同学不用陪同。
  3. 压测可以在白天进行,晚上熬夜毕竟不利于健康。
  4. 链路规划图形化,并与数据工厂结合,完成数据的准备工作。
  5. 通过水位检测与流量干预来保护系统,让业务系统不会被压崩溃。

作者介绍

金瑞敏,有赞核心交易、java 框架团队负责人。带领团队完成核心交易平台化体系建设,优化有赞服务化治理方案、环境隔离方案、全链路压测方案等等。长期从事分布式系统的建设与研究。

2017-11-10 22:008189

评论 1 条评论

发布
用户头像
真的是很好的一篇文章
2019-01-11 17:03
回复
没有更多了
发现更多内容

云服务器挂载硬盘命令

百度搜索:蓝易云

云计算 Linux 运维 云服务器 硬盘

Golang微服务框架kratos实现Socket.IO服务

喵个咪

golang socket websocket Kratos

Spring AOP 中,切点有多少种定义方式?

江南一点雨

Java spring

用故事给予企业全面预算管理一个灵魂

智达方通

全面预算管理 企业全面预算管理 预算场景

NineData已支持「最受欢迎数据库」PostgreSQL

NineData

postgresql 客户端 数据源 NineData 集成AI

Linux系统Nginx优化与防盗链详细教程

百度搜索:蓝易云

nginx 云计算 Linux 运维 云服务器

直播程序源码开发建设:洞察全局,数据统计与分析功能-山东布谷科技创作

山东布谷科技

软件开发 直播 源码搭建 程序源码 mac数据分析统计软件

Centos7安装Node.js详细教程。

百度搜索:蓝易云

node.js 云计算 Linux centos 运维

百度智能云连拿四年第一,为什么要深耕AI公有云市场

脑极体

AI 大模型

Kratos 大乱炖 —— 整合其他Web框架:Gin、FastHttp、Hertz

喵个咪

golang gin Kratos

Linux系统Apache优化与防盗链详细教程

百度搜索:蓝易云

Apache 云计算 Linux 运维 云服务器

分布式事务两阶段提交和三阶段提交有什么区别?

王磊

java面试

Golang微服框架Kratos与它的小伙伴系列 - ORM框架 - Ent

喵个咪

golang ORM Kratos

拥抱AIGC,他们有话说——百度李双龙:AIGC将赋能多个场域并惠及千行百业

百度Geek说

人工智能 百度 企业号 7 月 PK 榜 AICG

澜舟科技创始人兼CEO周明受邀出席“基础科学与人工智能论坛”

澜舟孟子开源社区

快速玩转 Llama2!阿里云机器学习 PAI 推出最佳实践(二)——全参数微调训练

阿里云大数据AI技术

人工智能

视觉套件专项活动!与飞桨技术专家一起提升技术实力,更多荣誉奖励等你领取

飞桨PaddlePaddle

人工智能 百度 paddle 飞桨 百度飞桨

oracle已有表的分表分区优化操作步骤(单表过大)

zhengzai7

oracle 表分区

Cassandra SSTable 合并策略(一):STCS

冰心的小屋

Cassandra STCS Compaction

Golang微服框架Kratos与它的小伙伴系列 - ORM框架 - GORM

喵个咪

golang ORM gorm Kratos

3D建模和3D渲染是吃CPU还是显卡?以及专业图形显卡和游戏显卡的区别

Finovy Cloud

3D

密集发布AI应用后,微软2023财报传递了什么信号|TE解读

TE智库

Dify.AI:简单易用的 LLMOps 平台,可视化创造和运营你的 AI 原生应用

Dify

AI LLMOps

Golang微服务框架kratos实现SSE服务

喵个咪

golang websocket Kratos openai

Golang微服务框架Kratos实现GraphQL服务

喵个咪

golang graphql Kratos

热烈祝贺埃文科技荣获CCF第38届中国计算机应用大会计算机应用科学技术二等奖

郑州埃文科技

Golang微服务框架kratos实现SignalR服务

喵个咪

golang SignalR Kratos

Golang微服务框架Kratos实现Thrift服务

喵个咪

fastposter v2.16.0 让海报开发更简单

物有本末

图片处理 海报生成器 海报生成

Java程序员常用的日志框架有哪些?

java易二三

Java 编程 程序员 计算机

Java基础 日期和时间

java易二三

程序员 计算机 java 编程

有赞11·11:全链路压测方案设计与实施详解_软件工程_金瑞敏_InfoQ精选文章