背景介绍
大促活动的三个关键词:瞬时流量、热点团单和核心路径。
瞬时流量:大促活动的一般形态是在活动日的某个时间节点(比如上午10点),开放一批0元抢购团单;这时大量用户会从H5活动页点击“免费吃”按钮(静态页面,用户会提前打开),跳转到Native团购详情页,给团购系统带来一个瞬间流量高峰。某次活动统计数据显示,瞬时高峰流量达到了平时流量的33倍。
热点团单:活动日上午10点开放的这批0元抢购团单,可以称之为是热点团单。
核心路径:活动高峰期大部分用户行为会集中在这些热点团单的购买流程上,而不是去搜索一个团单或者给团单写评价;这个热点团单的抢购流程就是大促活动的核心路径。
面对这个瞬时流量高峰,首先要回答的问题是系统能不能扛住;如果抗不住的话,最有效提升系统容量的方式是进行扩容。假设在系统没有瓶颈、可水平扩展的前提下,单个应用的扩容可以使用以下公式:
为了制定扩容计划,我们需要知道分子“活动峰值流量”和分母“单机容量”。大促活动准备期间,运营会根据活动预算、Push发送量和Push转化率等数据,推算出活动页的PV和UV;根据往期活动的经验数据,推算出抢购或秒杀活动的用户点击量,以此数据作为系统的入口峰值访问量。
有了入口峰值访问量,结合系统的流量模型,就可以推算出每个应用节点的活动峰值流量。通过对系统的压力测试,可以得出每个应用节点的单机容量极限值。
在开始正式讲流量预算和容量评估之前,先介绍下团购系统架构的演进。
早期的团购系统如下图所示,Web层和Service层都是单应用架构。Web层的团购MAPI应用,提供了包括团购首页、团购列表、购买流程、团购订单/券、退款流程等200多个接口(包括读接口和写接口),所有业务耦合在一起。Service层的团单服务也是类似的。
针对这样的系统架构做流量预算很简单,可以直接用运营同学给的入口峰值访问量做分子(活动峰值流量)即可。
但是要获取分母(单机容量)是比较困难的事情。针对这样的架构,在线上或者线下做一次有效的压力测试成本比较高——如果通过线上引流的方式做压力测试,读流量和写流量必须区分开;如果在线下模拟搭建一套压力测试环境,依赖的服务较多,搭建环境成本高;另外业务耦合在一起,线下也比较难模拟线上的接口分布等情况。
根据木桶短板理论,不需要压力测试也可以知道当时的团单系统性能不会很好。这样系统架构下,评估系统的容量的办法基本上只有拍脑袋。
现在的团单系统架构有了比较大的改进。如下图所示,团单服务做了“拆弹项目”,复杂的团单服务按照业务领域拆分成了基础服务、价格服务、库存服务、属性导航服务等。从服务名称可以看出来,一个应用拆分成了多个应用,每个应用单独负责某个领域;缓存集群和团购数据库也按照业务领域做了拆分。随后,大而全的Web层MAPI应用也按照业务领域拆分成了团购详情应用、团购交易应用和个人中心应用。
总结下的话,就是整体上逻辑耦合在一起的业务按微服务化拆分出来,每个服务独立专注的做一件事情。
下面两张图可以比喻团购系统架构的演进。左图是早期的团购系统,业务混杂在一起,难以量化;右图是拆分之后的团购系统,分层架构清晰合理,这个时候对系统建立模型、量化分析变成了一件可行的事。
活动流量预算
流量模型分析是流量预算的关键,只有清楚了系统的流量模型,才可能对系统每个节点的峰值流量做准确的评估。
团购系统在不同的场景有不同的流量模型。如下图所示,左图是系统平时的流量模型,右图是大促时的流量模型,其中中间人最多的路径是大促活动核心路径的流量模型。下面会介绍如何针对这条核心路径建立流量模型。
大促活动时的业务核心路径是:用户首先访问H5活动页,点击“免费抢”按钮到达热点团购详情页,然后通过点击团购详情页的“立即抢购”按钮进入提交订单页,并最终完成支付流程。
这个是大促活动的业务核心路径对应的系统架构图,用户跳转到团购详情页时,客户端会向Web层的团购详情API应用请求数据,团购详情API应用再向聚合服务层发起请求,聚合服务层分别异步调用团单价格服务、团单库存服务、团单属性服务等基础服务,并将这些基础数据组装好返回给上层应用,最终返回数据到客户端,展示在用户的移动设备上。
根据系统架构图,可以从上至下梳理调用关系链,建立核心路径的流量模型。
第一步:梳理活动页跳转到App Native页面的接口调用链。用户从活动页点击“免费吃”按钮进入团购详情页,会发起6个API接口请求。其中3个接口——团购基本信息接口,团购购买须知接口和团购适用商户接口——会对用户的购买决策起决定性作用,是团购详情页的核心路径。
团购详情页下方还有三个非核心模块会发起3个接口请求,分别为本店其他团购接口、网友评价接口和团购推荐的接口,这几个模块可以给用户购买决策提供参考,但是不是必须的,在大促活动场景下是非核心路径。这些接口可以通过开关关闭(关闭非核心场景是一种有效的降级方案),下面的分析假设非核心路径接口开关关闭。
第二步:梳理Web层接口之间的调用次数和调用顺序。用户打开团购详情页时,客户端会先发起团购基础信息接口,再获取团购基本信息(如:标题、价格、销量等)之后,会异步发出其他5个模块的接口请求。
第三步:通过代码分析和CAT调用堆栈分析,梳理Web层接口对下游服务的调用顺序和调用次数,汇总成对服务层各应用的调用倍数。(注:CAT是美团点评技术团队开源的实时监控平台,已在许多业界公司生产环境得到应用,详情参见:https://github.com/dianping/cat)
假设团购详情页的PV是1,会发出3个API请求;除了团购商户API之外,团购基础信息API和团购详情API会分别调用团购基础服务1次,另外在大促的场景下会在创建订单和支付等场景对团购基础服务有5次调用,即总共会有7次的团购基础服务的调用。
通过分析代码和调用堆栈,可以得知团购详情页的PV对团单价格服务和团单库存服务的调用次数也是1:7的关系。
这样我们可以得到大促活动核心路径的流量模型:假设详情页的流量单位为1,团购系统各个应用节点的流量构成如下表所示。
同理,大促活动核心路径对缓存和DB的最大访问次数也可以分析出来。
这时可以根据运营给到的入口峰值流量数据,推算出大促活动时团购系统从上到下(Web层、服务层、缓存和数据持久层)每一个应用节点可能会达到的最高流量。
最终给到运维的会是这样一份扩容计划表。综上所述根据流量模型可以推算出系统每个应用节点的活动峰值流量以及需要提供的集群容量(活动峰值流量*余量系数)。另外系统当前机器数是已知的,那么要完成扩容计划表,下一步要做的事情是进行容量评估,即通过压力测试,评估系统每个应用节点的单机容量。
系统容量主要通过线上环境或者线下环境的压力测试来评估。首先会介绍压力测试策略的制定,大促活动期间压力测试的目的,以及压力测试环境的选择(重点介绍性能测试环境PTP)。然后通过实例介绍压力测试执行中的压测工具的选择、压测场景的设计和压测数据的准备。