IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> 性能分析:动态代理失败导致缓存策略失效 -> 正文阅读

[开发测试]性能分析:动态代理失败导致缓存策略失效

压测原因

首页改版,所以要对首页进行压测,首页展示过程中涉及多个接口,需要进行压测。

压测分析

第一次排查

简单查看压测请求情况,初步观察日志可以额看到十个中有一到两个请求出现几百甚至上千毫秒的接口相应,排查TraceID之后发现为:接口调用到普通的测试环境和性能环境,导致部分请求走到测试环境,普通的测试环境只有1C2G,而生产环境的配置为40核64G/92G,所以相应结果较长也在意料之中。

同时排查过程中还发现部分接口调用链极短,这与线上的请求调用是不相符的,排查发现是请求头Header未设置数据导致很多请求被过滤到,所以在请求头上加入对应参数再次压测。

第二次排查

第二次压测过程,惨不忍睹,整体请求成功率只有76%左右,查询部分接口的响应时间很长,甚至直接溢出500,可以看到product服务的(ProductLimitFacade.queryProductLimitByXXX)由于接口请求时间过长,导致sofa线程池被打满,从而出现性能测试曲线出现急剧下降以及请求报错。

  • TPS断崖下跌
  • 请求时长由毫秒级\十几毫秒增长到上千毫秒,打满清空多次成正弦曲线状态

原本计划采用缓存来提升整体的查询性能,但是发现代码中已经使用了XXCache本地缓存,但是在看日志过程中还是发现存在大量的查询SQL(产品限额信息需要根据产品列表循环查询)。

排查SQL日志过程中,也可以看出有大量的SQL查询日志,导致接口相应太慢,大量线程阻塞在查询限额的方法出,所以目标锁定–代码的XXCache缓存使用不当,导致缓存策略未生效。
(XXCache:内部封装的一种缓存策略,根据参数值可以设置缓存在Redis或者缓存在本地中,可以参考GuavaCache的实现方式)[参考:GuavaCache的认识]

@XXCache(value = "productLimit", key = "productYieldDXXX_#{}_#{}_#{}")

第三次排查

现在已知是缓存策略失效的问题,第一反应为注解使用不当,导致缓存穿透。因为同时查询产品限额信息,以为是未配置allowNullValue的问题导致的,但是XXCache会默认会开启空缓存数据,所以也不是缓存穿透导致的。[参考:缓存穿透、缓存击穿、缓存雪崩区别和解决方案]

  • 缓存的正常流程为:先查询缓存然后查询数据库。查询缓存,若存在数据,则返回;如果缓存没有则查询数据库;如果数据库也没有返回空。
  • 缓存穿透:缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。
  • 缓存雪崩:缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。

第四次排查

采用Debug调试过程中,查看发现在XXCache打断点也无法阻断this.queryProductLimitByXXX()方法执行的调试线程。但是在另一处查询产品信息时却可以进入XXCache中阻断调试线程,清晰明了,就是该方法的XXCache并未拦截,导致本地缓存没有生效。

回归代码本源,接口调用的是列表查询接口,但是真正的本地缓存的是单个产品限额查询的接口,出发点很好,毕竟产品编号列表的排列组合太多,会不必要的浪费服务器宝贵的内存资源,问题就出在for循环的this调用,我们知道Spring的AOP核心思想是基于动态代理来实现的,如:

  • 基于接口的JDK的InvocationHandler动态代理
  • 基于子类继承的CGLib的MethodInterceptor动态代理。[Spring AOP 动态代理]

调用的列表查询接口会被代理对象增强,但是this调用不是代理对象执行的方法,而是原对象的原生方法,自然没法拦截增强,于是XXCache本地缓存就没有生效。至此, 问题排查完成。

问题解决

解决办法也很简单:一种是移除this调用改为获取代理对象(实现并注入ApplicationContextAware;然后使用该上下文来获取this服务的代理对象)来执行即可拦截增强,另一种将XXCache注解下移,将注解加到Manager上即可完成。


参考:

  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章      下一篇文章      查看所有文章
加:2022-03-17 22:30:22  更:2022-03-17 22:30:49 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/18 0:17:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码