Su的技术博客

  • 首页
  • Java
  • MySQL
  • DDD
  • 事故复盘
  • 架构方案
  • AI
  • Other
  • 工具
  • 打赏
  • 关于
路很长,又很短
  1. 首页
  2. Java
  3. 正文
                           

【京东】京东购物车如何提升30%性能

2023-02-17 206点热度 0人点赞 0条评论

01
背景



购物车面临的挑战:

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

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

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

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

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



02
全异步化改造方案


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

1)不同RPC并行

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



2)批量接口多分页并行

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

3)底层采用JSF异步调用

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



03
问题及解决


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

1)异常重试需精细化

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

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

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

2)异步RPC监控更复杂

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

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

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

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

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



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

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

5)分页均衡

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



04
收益


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


本文仅供学习!所有权归属原作者。侵删!文章来源: 京东零售技术

更多文章:

  1. mysql-connect-java驱动从5.x升级到8.x的CST时区问题
  2. 接口优化的常见方案实战总结
  3. MySQL性能优化浅析及线上案例讲解
  4. 【视频】NettyInAction作者:统治一切的框架Netty- One Framework to rule them all
  5. 笔记 | 5种网络IO模型
  6. Redis为什么这么快?
  7. 可插拔组件设计机制—SPI
  8. tomcat应用服务启不来,没有报错日志?不可能!
标签: 京东 批量 RPC 并行 购物车 性能优化 异步
最后更新:2023-02-19

coder

分享干货文章,学习先进经验。

打赏 点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

最新 热点 推荐
最新 热点 推荐
图解Git ChatGLM:ChatGPT的替代方案 关于聚合根、领域事件的那点事——深入浅出理解DDD 系统设计 | UUID 和 自增 ID 怎么选? Vim 一下日志文件,Java 进程没了? DDD系列第五讲:聊聊如何避免写流水账代码 LLM下半场之Agent基础能力概述:Profile、Memory、Plan、Action、Eval学习笔记 浅析Redis大Key
OpenAI震撼技术圈!0代码构建Assistants API,技术原理探秘LLM下半场之Agent基础能力概述:Profile、Memory、Plan、Action、Eval学习笔记系统设计 | 导入和导出系统设计 | 如何管理应用系统中的配置?系统设计 | UUID 和 自增 ID 怎么选?Vim 一下日志文件,Java 进程没了?关于聚合根、领域事件的那点事——深入浅出理解DDD浅析Redis大Key
【视频】NettyInAction作者:统治一切的框架Netty- One Framework to rule them all 设计模式在外卖营销业务中的实践 JVM GC配置指南 解放双手!ChatGPT助力编写JAVA框架 ChatGPT编程实践应用案例 DevOps 流水线 CI 成倍提速方案 富途证券关于2021.10.9凌晨交易中断事故的道歉和回复 RocketMQ 很慢?引出了一个未解之谜

618 (1) Agent (2) AIGC (1) bigkey (2) chatglm (1) checkout (1) commit (2) Disruptor (1) Excel (1) FGC (3) G1 (1) G1GC (2) git (2) GLM (1) hotkey (1) LangChain (1) LLM (3) mvc (1) OpenAI (2) ParNew (3) pull (1) push (1) solid (1) UUID (1) Vim (1) vivo (2) ygc (1) 业务编号 (1) 事务隔离级别 (1) 低耦合 (1) 依赖注入原则 (1) 分布式ID (1) 分支 (1) 分页 (3) 单一职责原则 (1) 命名 (1) 垃圾回收器 (7) 大模型 (2) 大语言模型 (1) 开源 (1) 开闭原则 (1) 微博 (1) 微服务 (1) 性能调优 (10) 接口隔离原则 (1) 数据字典 (1) 数据导入 (1) 数据导出 (1) 方案设计 (7) 权限 (1) 架构师 (1) 架构模式 (1) 架构设计 (4) 架构风格 (1) 模块 (1) 死锁 (1) 测试策略 (1) 滴滴 (1) 版本控制 (2) 电商 (2) 系统架构 (4) 编程语言 (2) 订单号 (1) 认证 (1) 软件架构 (2) 配置 (1) 里氏替换原则 (1) 鉴权 (1) 降级 (1) 高内聚 (1)

COPYRIGHT © 2014-2023 verysu.com . ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

粤ICP备15033072号-2