德鲁伊参数踩坑之路

上文说到 Druid德鲁伊参数调优实战,也正因此次优化,为后续问题埋下了伏笔

背景

2024/04/16日,业务反馈某个定时统计的数据未出来,大清早排查定位是其统计任务跑批失败,下面给一段伪代码

// 无事务执行
public void executor() {
    List<String> allShop = new ArrayList<>();
    List<Object> result = allShop.stream().map(shop -> {
        // 订单数量统计
        // 订单支付金额
        // 订单退款
        // 冲账支付
        // 冲账退款
        // todo 以上五个查询都是未指定事务的查询(默认连接为autocommit)
        return new Object();
    }).collect(Collectors.toList());
    // 批量插入
    mysql.batchInsert(result);
}
注:allShop大约几万个,这段代码表明了每次获取连接执行完SQL后都是将连接归还,然后下次再获取一个新的连接来执行

第一次失败异常

Cause: java.sql.SQLException: No operations allowed after statement closed. ; 
No operations allowed after statement closed.; nested exception is java.sql.SQLException: No operations allowed after statement closed. at

看到这很清晰了,连接关闭后不允许再执行操作,突然回想前不久将德鲁伊中testOnBorrow 修改为false


到这真相大白,赶紧将testOnBorrow改回true,先将问题解决

打补丁发版再次重跑

修改后打补丁继续执行,又又又失败了…

失败异常
Cause: com.mysql.cj.jdbc.exceptions.MySQLTimeoutException: 
Statement cancelled due to timeout or client request ; 
Statement cancelled due to timeout or client request; 
nested exception is com.mysql.cj.jdbc.exceptions.MySQLTimeoutException: 
Statement cancelled due to timeout or client 

心好累,心好累,执行超时,立马查看mysql连接 以及 德鲁伊连接池 的超时参数,果然…


因此业务是历史遗留的,本着解决问题的思路先将此参数修改大一下,赶紧搞定就下班回家洗洗睡了

最后贴一版最后德鲁伊连接池参数

# 初始连接数
initialSize: 5
# 最大连接池数量
maxActive: 20
# 最小连接池数量
minIdle: 10
# 配置获取连接等待超时的时间
maxWait: 60000
# 配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。
use-unfair-lock: true
# 配置连接超时时间
connectTimeout: 30000
# 配置网络超时时间
socketTimeout: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis: 300000
# 配置一个连接在池中最大生存的时间,单位是毫秒
maxEvictableIdleTimeMillis: 900000
# 配置检测连接是否有效
validationQuery: SELECT 1 FROM DUAL
# 指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除.
testWhileIdle: true
# 指明是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个
testOnBorrow: true
# 指明是否在归还到池中前进行检验
testOnReturn: false
# 开启池的prepared statement 池功能
pool-prepared-statements: true
max-open-prepared-statements: 100
use-global-data-source-stat: true
# 对于长时间不使用的连接强制关闭
remove-abandoned: true
# 超过120分钟开始关闭空闲连接
remove-abandoned-timeout: 7200
# 将当前关闭动作记录到日志
log-abandoned: true
# 修改过后的查询超时时间120秒
query-timeout: 120
kill-when-socket-read-timeout: true

感想

其实在这段排查过程中,踩了好几个坑,也被好几个坑给阻碍排查的进度,下面列举下

1、一个跑批的定时任务居然没有重试机制,更何况没考虑任何事物问题(那部分事物提交后,后续没处理的数据如何继续处理?)
2、此任务作为一个统计任务一条日志都不留(所有日志都找不到此堆栈,后面走邮件清理掉跑成功的部分数据,然后重新单独跑此子任务才看清楚上面两个异常)
3、此任务是xxl-job一个子任务,当主任务成功时,子任务失败,在xxl-job看板上实际上是子任务异常信息展示
4、本项目数据库作为主从架构,跑批的查询选择走主库,这是一个统计上一日收益数据的任务完全没有必要查询主库(同样的SQL主从查询性能差距近40%-现场实测)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值