京东购物车分页方案探索和落地
Tech
--导读--
本文主要结合京东购物车的特性,从技术和业务层面综合考量,探索商品附属信息分页加载方案,为逐步扩容的购物车诉求做好底层技术支撑。通过本文,读者可以充分了解到主数据分页加载和附属信息分页加载分别适用哪些业务场景。在实际开发过程中,结合应用特性选择合适的分页技术方案,保证应用低碳高效运行。
本文主要结合京东购物车的特性,从技术和业务层面综合考量,探索商品附属信息分页加载方案,为逐步扩容的购物车诉求做好底层技术支撑。通过本文,读者可以充分了解到主数据分页加载和附属信息分页加载分别适用哪些业务场景。在实际开发过程中,结合应用特性选择合适的分页技术方案,保证应用低碳高效运行。
01
背景
在今年的敏捷团队建设中,我通过Suite执行器实现了一键自动化单元测试。Juint除了Suite执行器还有哪些执行器呢?由此我的Runner探索之旅开始了!
随着京东购物车应用场景的丰富化和加车渠道的多元化,京东购物车的商品容量从2015年至今一直在逐步增加。2015年京东购物车由80件扩容到120件;2018年由120件扩容到150件;2020年由150件扩容到180件;2021年京东PLUS会员扩容到了220件。持续不断的扩容给我们的后端服务带来了巨大的负载压力,因为用户购物车中商品种类数量的增加对应到后端的计算资源也会线性增加,如何做到资源最大限度的节约又能保证业务和用户的体验不受影响,如何从技术和业务层面综合考量为逐步扩容的购物车诉求做好底层的支撑,一直以来都是摆在我们面前的一个痛点和挑战。
首先描述下京东购物车的特性:用户在购物车操作完商品后会记录下用户当前的操作状态,比如勾选,反勾选,切换促销后的商品促销信息等,当用户再次进入购物车后会全量获取购物车中的所有商品,根据商品的勾选态,促销等实时计算商品的价格,展示给用户。每次刷新或者修改购物车商品都是全量数据下发。持续扩容势必会持续加大后端服务的压力,同时购物车页面的布局计算、渲染等操作不仅使用户等待页面刷新的时间变长,而且还会占用大量的内存资源,导致手机卡顿。
京东购物车为了提升用户体验,保留了勾选商品总额、优惠促销、运费等一系列整车维度的计算逻辑,最终导致目前无法一步到位去实现购物车主商品的分页。期间也对行业内的主流电商类APP做了充分的调研,大部分APP都没有做购物车分页且购物车容量上限也大都控制在120以下,做了分页的APP也在勾选态保留和全局优惠计算等方面做了一些简化和降级,所以我们决定从另一个方向进行探索和突破,即商品附属信息分页,暂时避开会影响到全局优惠计算和影响业务玩法、流量转化的主数据分页。
什么是商品基础信息和附属信息?商品基础信息和商品附属信息的划分主要从上游接口层面进行区分,商品基础信息即从购物车中台直接获取的商品信息,比如商品图片、商品名称、商品价格、商品类型等;基于基础信息,通过异步并行框架分批获取的商品的附属信息,比如优惠券、预估到手价、商品库存、活动标签、服务、秒杀、闪购等。
图1 商品信息示例
02 目标
理解,首先 MCube 会依据模板缓存状态判断是否需要网络获取最新模板,当获取到模板后进行模板加载,加载阶段会将产物转换为视图树的结构,转换完成后将通过表达式引擎解析表达式并取得正确的值,通过事件解析引擎解析用户自定义事件并完成事件的绑定,完成解析赋值以及事件绑定后进行视图的渲染,最终将目标页面展示到屏幕
1. 提升用户体验,解决由于上游服务接口无法支撑购物车超多商品并发访问而导致的产品体验问题,在无损用户体验的情况下,保证用户在购物车滑动过程中无感知分页加载商品附属信息;
2. 缩减机器成本,减少不必要的上游接口请求,降低后端服务器负载;
03 技术方案
理解,首先 MCube 会依据模板缓存状态判断是否需要网络获取最新模板,当获取到模板后进行模板加载,加载阶段会将产物转换为视图树的结构,转换完成后将通过表达式引擎解析表达式并取得正确的值,通过事件解析引擎解析用户自定义事件并完成事件的绑定,完成解析赋值以及事件绑定后进行视图的渲染,最终将目标页面展示到屏幕。从设计稿出发,提升页面搭建效率,亟需解决的核心问题有:
1)商品附属信息分页加载价值分析
根据购物车线上不同维度埋点数据分析结果显示,京东购物车中商品数量在20-220区间的请求次数占总请求次数一半以上,平均一屏展示的商品数量不超过3个,购物车中商品浏览的平均曝光深度6~7个,由此分析大部分的上游接口调用都有很大节省空间。通过前端线上模拟分页埋点分析预估,商品附属信息分页调用的方式可以减少30+%的上游异步接口调用,做到在无损用户体验的情况下,削减接口调用峰值,降低接口的性能压力和机器资源消耗。
2)商品附属信息分页加载
商品附属信息分页前后接口交互的差异在下图进行了清晰的标识,主要体现在页面刷新和页面滑动两个方面。
图2 异步请求分页方案
商品附属信息不分页加载方案:客户端触发一次刷新操作需要从各个上游接口获取所有商品信息并组装整合后一次性下发给客户端进行展示,在页面滑动过程中不涉及接口请求。上游接口的调用方式主要分以下3种:
单次获取全量商品某附属信息:即客户端获取商品基础信息后仅调用一次上游接口,该上游接口一次性返回所有商品的某附属信息。这种方式接口调用频次较低且避免了部分商品附属信息缺失的体验问题,但是随着购物车中商品数量的增加,对于接口的响应时长等性能挑战也越大。
单次获取部分商品某附属信息:即客户端获取商品基础信息后仅调用一次该上游接口,但只会获取前几个商品的某附属信息,其他商品的该附属信息会缺失。这种方式减少了上游接口的调用频次,但是牺牲了部分用户体验(通常是由于上游接口不支持频繁调用,且单次计算逻辑复杂导致);
分批次获取全量商品某附属信息:即客户端获取商品基础信息后分批调用该上游接口,从而获取所有商品的某附属信息。这种方式避免了部分商品附属信息缺失的体验问题,但是上游接口的高频次调用给上游带来了较大的挑战,随着购物车中商品数量的增加,机器资源消耗也会随之增加。
优点:对于客户端而言交互简单,只需关心数据刷新/变更类操作(如下拉刷新购物车、勾选反选等),一次性获取购物车全部商品信息后整体刷新页面,无需分析用户滑动行为,不需要处理商品数据的组装整合,逻辑简单轻量。
缺点:客户端每次触发数据刷新/变更类操作,除了从后端获取购物车全部商品基本信息外还需要通过异步并发框架分批请求全部商品的附属信息,直接导致购物车整体流量翻倍,增加机器资源成本。
商品附属信息分页加载方案:客户端从后端获取商品基础信息后,对商品进行页码划分,然后同步并行请求第1页至屏幕浏览当前页的商品附属信息,组装整合后下发给客户端展示;其他页码的商品附属信息由客户端在列表滑动过程中逐页预加载,将返回的该页商品附属信息与商品基础信息组装整合后展示。下图对商品附属信息分页加载方案中购物车客户端以及各上游接口的整体交互流程进行了清晰的说明,整体详细的步骤为:
调用查询接口时将主商品所在页码的pageSize传递给服务器,服务器将pageSize所在页的主商品的附属信息下发,客户端渲染
将商品的所有附属信息封装为一个独立接口
在主商品上进行打戳,标志预加载的请求时机。此处的打戳标识是根据埋点数据和用户跟踪获取到的预加载标志,既能保证独立的附属信息接口不会有大量无效的加载,同时能够保证附属信息接口的数据及时更新到页面上,确保用户体验
优点:商品附属信息分页加载方案,将用户的刷新/变更操作和滑动操作进行行为差异细分。通过将各页商品的附属信息后置到滑动过程中获取,大幅缓解了单次刷新/变更操作中上游接口集中分批调用带来的流量性能压力,起到日常流量削峰的作用,同时节省了未浏览商品的附属信息异步接口调用(30+%),节约了对应流量的机器资源成本。
缺点:对于客户端而言交互复杂,不仅需要关注购物车商品的刷新/变更,同时需要在滑动过程中关注上一页/下一页/当前页商品附属信息是否完整,针对附属信息缺失的商品适时进行预加载,并对购物车主数据进行组装整合处理。
图3 商品附属信息分页加载方案
04 技术难点与解决方案
理解,首先 MCube 会依据模板缓存状态判断是否需要网络获取最新模板,当获取到模板后进行模板加载,加载阶段会将产物转换为视图树的结构,转换完成后将通过表达式引擎解析表达式并取得正确的值,通过事件解析引擎解析用户自定义事件并完成事件的绑定,完成解析赋值以及事件绑定后进行视图的渲染,最终将目标页面展示到屏幕。
05 收益
理解,首先 MCube 会依据模板缓存状态判断是否需要网络获取最新模板,当获取到模板后进行模板加载,加载阶段会将产物转换为视图树的结构,转换完成后将通过表达式引擎解析表达式并取得正确的值,通过事件解析引擎解析用户自定义事件并完成事件的绑定,完成解析赋值以及事件绑定后进行视图的渲染,最终将目标页面展示到屏幕。
求分享
求点赞
求在看