记录关于历史遗留系统优化历程,从代码到消息队列rabbitmq,配置中心apollo,缓存redis,数据库

历史遗留系统整体采用生产者–消息队列–消费者–代理者的架构,本质没有什么问题,但是生产者数量及生产消息数量骤增时,队列常常出现堆积现象,堆积数据最高可达500w。

通过生产数据及压测观察,生产者接受数据能力并不小,单台每秒可达1000上下。生产者对外的接口输入比较精简,许多配置化的东西都配置到了apollo配置中心(加载到本地内存),查询数据库的东西统一都缓存到了redis中,基本满足性能要求,3600*1000=360w。

消息队列堆积一般都是消费速率低于生产速率导致的,所以从消费者开始着手优化,发现以下几个问题:

1 所有配置化的东西都是查数据库,本身配置的东西数据量并不大,而且需要反复查询,完全可以缓存到redis或本地。将查库操作进行封装,先查redis缓存,再查数据库,缓存统一设置失效时间30天+随机数。

2 将1中变化比较频繁的配置全部由数据库转移到apollo配置中心。

在这里插入图片描述

3 消费者原来的逻辑是将生产者数据和数据库配置信息组合成一个新的对象,重新路由到消息队列,然后自己消费去调用代理者。数据冗余,直接将生产者数据和数据库表(所有字段)组合在一起,许多不必要的字段全部加载出来,并且都进入了消息队列。

优化后只保留关键属性,数据库表只查询需要的字段,精简对象,减少传输payload,减小消息队列内存占用。
在这里插入图片描述
4 数据库明细表主键生成查询数据库序列(一个),数据量大时频繁请求数据库,修改为先查询查询序列,步长为1000,本地序列采用自增生成,减少与数据库交互。

在这里插入图片描述
5 原队列数量多达150个,按照不同维度分的很细,有些维度搭配却永远不会用到,每个队列都设置相同数量的concurrency=20,prefetch=1。

动态生成队列部分重新整理,避免永远不会用到的无用组合,队列数量减少为25条队列,根据不同队列的生产速率设置不同的concurrency 10 15 20,prefetch设置为1太保守,调整为5 10 15。
在这里插入图片描述
6 原数据库保存,针对批量数据请求采用单条循环保存逻辑,调整为批量保存。

7 整理依赖jar包排除多余的依赖jar包,原项目输出达到35M,排除一些重复的,功能近似的jar包,如commons-lang和commons-lang3共存的情况,httpClient和okHttp,jodd-http共存的情况,jackson和fastjson,gson共存的情况,输出war包部署到tomcat还依赖tomcat-embed-core等等情况。

统一调整代码,使用统一的api,排除掉冗余的jar包依赖,瘦身输出war包到18M。

8 原数据表设计直接保存明细数据,针对批量请求,明细数据存在大量的重复信息。新建批次表,公共信息保存批次表,明细表只保存个性数据,通过批次id勾兑批次表。

9 消费者调用代理者dubbo接口改为异步消费,异步执行回调,同代理者发送回执给消费者,同样使用异步消费。

10 使用jstat观察gc情况,收集gc日志,根据压测数据重新调整新生代,老年代大小,避免因集中请求过大,导致本该回收的对象过早进入老年代,导致full gc,尽量gc控制在young gc。

写累了,去休息了,如有纰漏,欢迎批评指正。

公众号:码农小麦,欢迎关注:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43275277/article/details/108013273
今日推荐