京东购物车如何提升30%性能 | 京东云技术团队

news2025/1/12 13:42:16

1、背景

购物车面临的挑战:

1)新业务:随着业务形态的丰富,购物车在不断支持各种新业务,依赖的外部接口也随之增加;

2)下沉:一些前端调用的接口下沉到购物车中台;

3)前置:结算流程很多业务前置到购物车中,如优惠券、京豆;

4)扩容:为改善用户体验购物车可容纳的商品数量在不断增长;

这些导致购物车依赖的RPC接口数量及分页调用次数都在不断增加。购物车作为交易流程开端,本身流量较大,在业务复杂化的背景下,如何提高性能保证用户体验,成为购物车面临的较大挑战。

2、全异步化改造方案

通过增加服务器资源虽然能在一定程度上解决问题,但会带来较大的成本开销,也与工匠精神相悖。能否通过技术手段提升性能呢?通过分析,异步化改造成为解决这一问题的有效手段。

1)不同RPC并行

购物车依赖接口达几十个,各接口间存在复杂依赖关系。必须先梳理各接口间依赖,识别哪些可以并行。然后将原有代码拆分为两部分:RPC异步请求和结果处理,按照依赖关系,让RPC最大限度并行执行,减少在结果处理阶段异步响应等待时间,从而达到提升性能的目的。

2)批量接口多分页并行

购物车依赖接口多为批量接口,且单次调用有数据量限制,需将数据拆分为多个分页调用。那么多个分页间也可以并行,改造中封装了异步分页工具,使业务层对分页逻辑无感知,异步工具自动将超过接口上限的数据拆分为多个分页并行调用,提升单接口响应速度。

3)底层采用JSF异步调用

异步调用基于京东RPC框架JSF,推荐使用1.7.5以后版本,支持CompletableFuture。

3、问题及解决

异步化改造的总体方案并不复杂,但是在实际落地过程中,遇到了很多细节问题:

1)异常重试需精细化

同步调用时,如果超时会重新调用。改为异步后重试会失效,因为在调用时一般不会报错,需要在结果处理阶段获取异步响应超时后,再进行重试。

另外,多分页并行时,当某一页请求超时后,应该只重试出错的分页。底层对分页调用进行了封装,上层业务代码在获取数据时无法感知是哪一页超时,所以必须在异步调用时将现场信息保存在包装类中,一起返回给业务层,在Get数据超时后,单独重试出错的分页。

发生异常时,并不是所有情况都需要重试,当遇到限流等异常时,不能进行重试。底层工具需要自动过滤限流异常,当然也支持自定义规则。

2)异步RPC监控更复杂

底层RPC耗时监控需要拆分为两部分,在分页调用时记为开始时间,在异步结果到达后,记为结束时间。如果调用异常或Get超时,需要标记本次调用失败。对于重试同样需要记录调用耗时,且正常调用与重试调用需分开记录。

除了需要监控RPC耗时外,还需要监控结果处理阶段Get等待时长,这个时间才是真正对应用性能有影响的时间。由于底层是分页调用,所以业务调用次数和底层RPC调用次数并不相同。

3)分页异步结果不能合并,否则无法获取异常Provider信息

底层异步调用结果,必须通过包装类原样返回给上层,除了上边提到的需要单分页重试外,另一个原因是必须保留异步结果,在分页超时后才能输出超时的Provider信息。这是由于Provider信息依赖JSF框架的JSFCompletableFuture,如果在底层合并结果,会导致信息丢失。

4)每页超时时间需单独控制

分页调用过程如上图所示,在结果处理时,每页Get超时时间需要单独控制,因为获取结果是顺序进行,获取后边的分页时,前边分页等待的时间也应计算在内,以保证整个获取结果的时间不超过单个分页的最大超时时间。计算公式如下:

超时=RPC超时时间 > (当前时间-异步调用开始时间) ? RPC超时时间 – (当前时间-异步调用开始时间) : 0

5)分页均衡

为避免最后一页数据过少造成数据倾斜,需要将请求数据均分到每一页,以最大限度提高整个请求的性能。

4、收益

改造完成后购物车核心接口耗时减少30%,保证用户体验,节省大量服务器资源。后续增加新的RPC接口时,只要处在调用拓扑的非关键路径上,对购物车性能没有太大影响。另外,容量增加时除少数不能分页调用的接口外,对性能影响已经比较小。

作者:京东零售 王利辉 梁奉龙

内容来源:京东云开发者社区

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/558227.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux systemd

这里写目录标题 一:配置文件内容二:配置文件位置三:开机启动配置四:systemctl使用 一:配置文件内容 systemd服务配置文件存放在/usr/lib/systemd目录下,有系统system和用户user之分,需要开机不登录就能运行的程序,放在/usr/lib/systemd/syst…

项目跟踪的好处有哪些?项目经理必须了解

项目跟踪要跟踪什么呢?主要针对计划、任务和项目成员三个方面,是为了了解项目的实际进展情况而进行。 在跟踪过程中我们会发现项目计划的不当之处,促使我们去改进和完善计划;发现项目风险,及时解决问题;了…

软件设计之UML用例图大白话教程

1、为什么要使用UML用例图? 对一个复杂问题或者现象的分析,好的方式方法往往能带来事半功倍的效果。比如在软件开发领域,参与的人员角色各种各样,比如软件开发工程师、产品经理、客户、运营人员、老板、用户、B端客户等等&#x…

chatgpt赋能Python-python_kargs

Python中的*kargs:详解 在Python编程中,经常需要为函数传递参数。除了常规的参数传递,Python还支持通过关键字参数传递参数。这种方法比较灵活,可以快速地修改函数的输入参数。其中,kargs是Python中非常常见的一个参数…

管理git项目:003

首先我们得创建一个git管理仓库 进入桌面路径,待会创建的文件可以在桌面找到 cd ..【创建git管理仓库】:创建一个.git 管理仓库, 这个文件被创建后是一个隐藏文件。这个.git文件的作用是:指定当前文件夹作为git管理仓库 git init …

今天,我问了ChatGPT一个难以启齿的问题,内容实录

文 / 高扬(微信公众号:量子论) 七个月前,我是一个害怕失业的漂泊上海的小青年,每天在合租房里刷着LeetCode。 现在我已经在一家人工智能公司从事着自己喜欢的关于机器深度学习的研发工作。 你想知道我的生活发生了什么…

学习git

文章目录 02-为什么要学习Git软件?03 概念:版本控制04 概念:版本控制软件基础功能05 概念:集中式、分布式版本控制系统、多人协作开发5.1 文件冲突问题5.2集中式版本控制(CVS,SVN)5.3 分布式版本…

Word控件Aspose.Words教程:使用 Aspose.在 Java 中对条码使用 ECI 编码

Aspose.Words是一种高级Word文档处理API,用于执行各种文档管理和操作任务。API支持生成,修改,转换,呈现和打印文档,而无需在跨平台应用程序中直接使用Microsoft Word。 Aspose API支持流行文件格式处理,并…

LabVIEWCompactRIO 开发指南30 目标间通信

LabVIEWCompactRIO 开发指南30 目标间通信 可以从两种方法选择在FPGA VI和实时处理机上运行的VI之间传输数据的方法:前面板控制和指示器或DMAFIFO。可以使用前面板控件和指示器来传输最新值或标签以及DMA FIFO,以流式传输数据或发送消息和命令。这两种…

数据存储应用与原理剖析

存储引擎 存储引擎就是存放和读取用户数据的地方,对于持久化的存储引擎而言,数据的归宿是非易失性的存储介质(通俗意义上来说就是磁盘)所以该以什么形式组织和存储数据,这就是存储引擎设计的艺术所在这一块涉及到和操…

【历史上的今天】5 月 23 日:Java 正式发布;晶体管的共同发明者出生

整理 | 王启隆 透过「历史上的今天」,从过去看未来,从现在亦可以改变未来。 今天是 2023 年 5 月 23 日,在 2007 年的今天,盛大宣布出售所持有新浪公司股票,累计获利 7650 万美元。盛大曾于 2005 年 2 月通过公开市场…

Golang-循环变量作用域针对那些数据类型会出现问题

一、原因 在 Go 中,循环变量的作用域是整个 for 循环语句块。因此,循环变量在 for 循环语句块中的代码都是可见的。 但是,当循环变量的值被用于闭包, 协程或者使用指针类型的数据结构时,会出现一些问题。这是因为循环变量的值在…

每日一练 | 网络工程师软考真题 Day8

1、某客户端采用ping命令检测网络连接故障时,发现可以ping通127.0.0.1及本机的IP地址,但无法ping通同一网段内其他工作正常的计算机的IP地址。该客户端的故障可能是 。 A.TCP/IP协议不能正常工作 B.本机网卡不能正常工作 …

80%的人加班都是因为没搞清业务需求:小白如何做好需求调研?

做过项目的都知道,收集和明确需求并非易事,尤其是挖掘需求方详细、深层次的需求。 很多企业在做需求调研时,经常由于双方对问题描述和理解上的差异,使得需求在不断传递的过程中发生较大的偏差,结果导致最终开发出来的…

Head-Free Lightweight Semantic Segmentation with Linear Transformer 新颖的分割网络

现有的语义分割网络基本都是编码解码结构,新的语义分割网络主要都是在解码阶段添加新的不同模块,提高解码阶段特征处理能力,从而实现语义分割。而这篇文章主要是去除了解码阶段,把工作重心放在了编码阶段。它采用并行架构来利用原…

chatgpt赋能Python-python_isdigit_小数

Python isdigit 小数:如何检测字符串是否为数字? 在Python中,字符串是一种非常常见的数据类型。有时我们需要将字符串转换成数字类型,以便于进行各种计算,比如统计数据、计算平均数等等。在这种情况下,我们…

四、Spring从入门到改行

一、Spring概述 Spring是一个轻量级的控制反转(IOC)和面向切面(AOP)的容器&#xff08;框架&#xff09;。 二、Spring基础程序 1、pom.xml中导入依赖 <dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifact…

chatgpt赋能Python-python_ip地址处理

Python IP地址处理 在网络通信中&#xff0c;IP地址是非常重要的内容。Python作为一门强大的编程语言&#xff0c;自然也能处理IP地址。本文将介绍Python处理IP地址的方法&#xff0c;并提供一些实用的例子。 IP地址的表示方式 IP地址是一个32位的二进制数&#xff0c;通常表…

chatgpt赋能Python-python_if_跳过

Python中if语句的跳过和应用 Python的if语句是编程中常用的一条条件语句&#xff0c;它允许开发者根据不同的情况&#xff0c;对代码进行不同的处理。if语句也带来了一些跳过语句&#xff0c;可以有效地帮助开发者避免不必要的操作&#xff0c;提高程序运行效率。本文将介绍Py…

toString 自定义逻辑 过滤 limit ignore 字段 ReflectionToStringBuilder ToStringBuilder

ToStringBuilder 有自己的属性,style, 也有工具方法,直接代理了ReflectionToStringBuilder // ReflectionToStringBuilder 非并发安全,需每次都new ReflectionToStringBuilder reflectionToStringBuilder new ReflectionToStringBuilder(this, org.apache.commons.lang3.build…