伪代码
public RespData findOrderTest(@RequestParam String orderCode,@RequestParam String strategy) {
TbOrder tbOrder = orderDao.findByOrderCodeAndStrategy(orderCode, strategy);
//do something
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return RespData.success(tbOrder);
}
使用 jmeter 并发调用,查询条件不变,反复查询同一条数据,发现查询速率变慢
正常耗时日志
`---[5054.53776ms] cn.*.PatientAppController:findOrderTest()
+---[54.165884ms] cn.*.TbOrderDao:findByOrderCodeAndStrategy() #349
+---[0.079756ms] javax.persistence.EntityManager:clear() #350
`---[0.018264ms] cn.*.RespData:buildSuccess() #363
测试期间接口耗时逐渐增加,异常耗时日志
`---[29406.81247ms] cn.*.PatientAppController:findOrderTest()
+---[24406.507885ms] cn.*.TbOrderDao:findByOrderCodeAndStrategy() #349
+---[0.036484ms] javax.persistence.EntityManager:clear() #350
`---[0.020533ms] cn.*.RespData:buildSuccess() #363
已排除是数据库性能问题,怀疑是 jpa 内部的实现机制所致,多番测试还是没有找到问题,分享出来给大家看看,请大佬指教
1
zhady009 2022-02-25 18:22:47 +08:00
mark 下 mongodb 好像也有这种情况
控制台里查一样的语句很快就返回 trace 的时候发现也是慢在 repository 的方法里 用了 10 秒 而且就 4000 条数据 版本是 2.4 的 |
2
joooooker21 OP 查询后直接返回,速度是不会变慢的。怀疑是 jpa 内部有某种锁的机制
|
3
wolfie 2022-02-25 18:31:08 +08:00
看看有没有缓存开关
|
4
mango88 2022-02-25 19:04:51 +08:00
压测多久发生一次 ? 变慢时,jvm 是否在 GC ?
|
5
siweipancc 2022-02-25 19:48:07 +08:00 via iPhone
orz 你开个纯接口,里边也睡一会,并发下还是会重现的
|
6
TheCure 2022-02-25 19:58:10 +08:00
|
7
joooooker21 OP |
8
1194129822 2022-02-25 21:59:00 +08:00 1
这不是 JPA 的问题,你换成 Mybatis 之类也会出现同样的情况。很明显是连接池的问题,Connection 一般都是有限的,你并发高,把 Connection 占完了,而且迟迟不释放。后面线程阻塞在获取 Connection ,你可以看一下你用的是什么 DataSource ,Hikari 默认只有 10 个连接。你把连接数调到几百试一下,你这就相当于慢查询,造成的雪崩效应。但是真实环境下 Connection 也不能太多,不然雪崩的就是数据库了,JDBC 的阻塞性其实保护的是数据库。
|
9
joooooker21 OP @1194129822 多谢分享。我有个疑问,数据库的 Connection 难道不是在返回查询结果后就立即释放了?另外这段代码是也并没有开启事务
|
10
zhenjiachen 2022-02-26 08:46:13 +08:00 via iPhone
我觉得 8 楼说的对,你可以看一下你的连接池支不支持指标,看一下指标就可以看出是不是并发后把链接用完了导致其他请求等待获取连接。
|