后端开发小白,学习中,记录一下自己遇到的(也许在别人看来很幼稚的)问题
在开发spring boot应用的时候,为了降低响应时延,我使用rabbitmq将数据异步写入数据库,线程无需等待mysql写入完成,只需要把数据发送到消息队列后就可以直接返回响应,缩短响应时间,听起来似乎美滋滋
为了充分展示这种方法的优势,我决定使用jmeter做压力测试,对比使用rabbitmq和直接写入mysql这两种方法,用数据来说话
由于我的vps们都只有一两g内存,实在是太寒碜了,于是我把应用部署在实验室的服务器上,实验室的服务器可是有好几十个cpu和好几百g内存,虽然跑大模型比较吃力,但是收拾个小应用还是绰绰有余
然而测试结果却让人有些意外,在只有几十到几百QPS的时候,使用rabbitmq优化的效果并不明显,和直接写入mysql的响应时间不相上下
一定是并发量还不够大,不能体现出消息队列的优势,给我加大药量,QPS调到2000试试看
奇怪,怎么使用mq的响应时间还更长了?反复检查配置文件和代码,我没把他俩搞混啊,不应该啊
询问万能的gpt,告诉我可能是rabbitmq开启了消息持久化和手动确认增加了时延,好,把这些可能影响性能的都关了
再次实验,使用mq的响应时间还是没有明显改善啊,奇怪
看一下rabbitmq的web控制页面,好像也没啥毛病,rabbitmq工作一切正常啊
是不是mysql连接数不够?消费消息太慢,show variables like "%conn%";
,看一下mysql的最大连接数
只有151?这怎么能扛得住我们成千上万QPS的呢?SET GLOBAL max_connections = 5000
,先临时改成5000试试看吧
emm,差别不大,只不过是实验的偶然误差罢了,多重复几次实验,会发现并没有什么作用
是不是设置没有立即生效,看一下mysql的最大历史连接数SHOW STATUS LIKE 'Max_used_connections'
奇怪,怎么只有11个连接啊,别说5000个连接数,连mysql默认的151个连接也没用满啊
询问gpt老师,gpt表示,spring boot 使用的是 HikariCP 连接池,默认的连接池大小(最大连接数)是10。所以只有11个连接,10个是HikariCP连接池的,还有一个是我们在mysql控制台的命令行连接
怎么不早说?这就是所谓的spring boot的“约定优于配置”吗
不过知道了就好,我现在就把spring.datasource.hikari.maximum-pool-size
改成1000试试看
再次测试,果然不出所料,Max_used_connections成为了1001
然而,jmeter的测试时延,看起来依然没有什么显著的改变
真是离谱,难道rabbitmq搞了半天,是个负优化?和我写论文提出的方法一样?一顿操作猛如虎,实验数据出来一看,毫无卵用甚至还有负作用
而且,max_connections 只是MySQL允许的最大并发连接数,它并不会直接优化SQL查询执行的速度。另外,即使增大mysql的连接数能缩短mysql消费mq的时延,那么对于直接写入db的方法,mysql响应时间也应该会相应缩短,依然无法解释直接写入db比通过mq异步写入更快的现象
检查一下代码逻辑:
if (conversationUseMqPersistence){
// 写入rabbitmq
rabbitTemplate.convertAndSend(...);
}else {
// 直接写入mysql
xxxMapper.insert(...);
}
return response
这样的实验结果只能说明,直接写入db的时间和把消息发送到mq的时间差不多,甚至还稍微快一点
于是乎,抱着这种想法,换一台机器,在我的老破笔记本上进行实验
实验结果大意外!使用rabbitmq,平均只需要39ms响应,不使用的话需要764ms,响应时间缩短95%。如果继续增大请求数,不使用rabbitmq的话jmeter进程直接卡死,使用mq还可以保持低延迟响应
看来是机器设备的问题,mysql在笔记本上的插入耗时很长,但在服务器上插入相当快
为了验证上面的想法,我在写入mq和写入db的语句前后分别获取时间戳计时
在服务器上,直接写入mysql和把数据发送到消息队列都非常快(0-1ms),在这种情况下,使用rabbitmq异步写入意义不大,还会因为加入了复杂性导致响应时延略有提高
而在个人pc上,把数据发送到消息队列依然只需要几毫秒到几十毫秒左右,但写入数据库的时间大大提高,需要几千毫秒,这种场景下,使用rabbitmq带来的提升无疑是巨大的
得到了两个经验:1. 是否使用rabbitmq应该根据不同的场景,机器配置,并发数来决定,如果直接操作的响应也非常迅速,使用mq并不一定能带来性能上的提升
2. 与其引入各种各样的中间件优化性能,不如直接氪金升级机器(划掉)