使用Druid报错abandon connection, open stackTrace
问题原由
最近使用 quartz
写了一个定时任务,这个定时任务主要是给会员增加类似积分的东西,并且要保存积分增加记录,每天凌晨4点钟执行,但是会有些时候会出现很多会员的积分并没有增加,查了一下日志,发现 Druid
抛出了 abandon connection, open stackTrace
,查看了一下报错的代码行,是在保存积分增加记录的时候抛出的异常,而且是等了30分钟才抛出的,也就是说,4点开始执行,然后4点半就抛异常了,导致用户的积分没有增加。
表结构
-- 用户会员信息表
create table client_vip_user_info
(
id varchar(36) not null comment '主键'primary key,
user_id varchar(36) null comment '用户编号',
had_stays int default 0 not null comment '积分',
create_time datetime null comment '创建时间(成为会员的时间)',
update_time datetime null comment '更新时间',
deadline datetime null comment '本期截止时间',
min_vip_level varchar(36) null comment '会员最低等级',
source varchar(20) null comment '注册途径'
)comment '用户会员信息表';
-- 会员积分记录表
create table client_vip_stays_log
(
id varchar(36) not null comment '主键' primary key,
userid varchar(36) null comment '用户编号',
type varchar(36) null comment '类型',
oldvalue int null comment '老数据',
incomevalue int null comment '新添加的数据',
value int null comment '当前数据',
createtime timestamp null comment '创建时间'
)comment '会员积分操作日志';
相关代码
//定时器
public void execute(JobExecutionContext context) throws JobExecutionException {
//加载bean
LiveUserService liveUserService = (LiveUserService) AppContext.getSpringBean("liveUserService");
UserService clientUserService = (UserService) AppContext.getSpringBean("clientUserService");
VIPLevelService vipLevelService = (VIPLevelService) AppContext.getSpringBean("vipLevelService");
VipUserInfoService vipUserInfoService = (VipUserInfoService) AppContext.getSpringBean("vipUserInfoService");
VIPStaysLogService vipStaysLogService = (VIPStaysLogService) AppContext.getSpringBean("vipStaysLogService");
OrderService orderService = (OrderService) AppContext.getSpringBean("orderService");
try {
//获取前一天的日期
String yesterday = DateUtil.getYesterdayDate();
//获取当前日期前一天的入住人
List<Map<String, Object>> list = liveUserService.getLiveUsers(yesterday);
User user = null;
Order order = null;
for (Map<String, Object> map : list) {
user = clientUserService.findByPhone(map.get("PHONE").toString(), map.get("phoneareacode").toString());
if (null != user) {
VIPLevel vipLevel = vipLevelService.getByUserId(user.getUserID());
//是会员才会进行操作
if (null != vipLevel) {
//用户会员信息
VipUserInfo vipUserInfo = vipUserInfoService.getByUserId(user.getUserID());
int oldStays = vipUserInfo.getHadStays();
int newStays = oldStays + 1;
//间夜数变更日志
VipStaysLog vipStaysLog = new VipStaysLog();
vipStaysLog.setCreateTime(new Date());
vipStaysLog.setId(UuidUtil.get32UUID());
vipStaysLog.setOldValue(oldStays);
vipStaysLog.setIncomeValue(1);
vipStaysLog.setValue(newStays);
vipStaysLog.setUserId(user.getUserID());
vipStaysLog.setType("入住新增");
vipStaysLogService.save(vipStaysLog); //就是这一行抛出的异常
//省略代码
vipUserInfoService.update(vipUserInfo);
}
}
}
} catch (Exception e) {
LOGGER.error("-------------------error");
e.printStackTrace();
}
}
//mybatis
<!--表名 -->
<sql id="tableName">
`client_vip_stays_log`
</sql>
<!-- 字段 -->
<sql id="Field">
`id` ,
`userid` ,
`type` ,
`oldvalue` ,
`incomevalue` ,
`value` ,
`createtime`
</sql>
<!-- 字段值 -->
<sql id="FieldValue">
#{id} ,
#{userId} ,
#{type} ,
#{oldValue} ,
#{incomeValue} ,
#{value} ,
#{createTime}
</sql>
<insert id="save" parameterType="VipStaysLog">
INSERT INTO
<include refid="tableName"></include>
(
<include refid="Field"></include>
) VALUES (
<include refid="FieldValue"></include>
)
</insert>
相关配置
// 数据源配置
url:jdbc:mysql://localhost:3306/leyizhu?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
driverClassName:com.mysql.jdbc.Driver
username:root
password:123456
filters:stat
maxActive:20
initialSize:1
maxWait:60000
minIdle:10
maxIdle:15
timeBetweenEvictionRunsMillis:60000
minEvictableIdleTimeMillis:300000
validationQuery:SELECT 'x'
testWhileIdle:true
testOnBorrow:false
testOnReturn:false
maxOpenPreparedStatements:20
removeAbandoned:true
removeAbandonedTimeout:1800
logAbandoned:true
环境配置
应用服务器
CPU: 2核
内存: 16 GB
实例类型: I/O优化
操作系统: Aliyun Linux 17.1 64位
独立数据库服务器
规格族:通用型 数据库类型:MySQL 5.6 CPU:4 核
数据库内存:8192MB 最大IOPS:5000 最大连接数:2000
可维护时间段:02:00-06:00 实例规格:rds.mysql.s3.large
错误日志
目前我检查了代码很多遍,都没有发现代码哪里有问题,同事也没有看出来,目前已知的是为什么30分钟后才抛异常,是因为 removeAbandonedTimeout
设置的就是30分钟。如果主动获取连接,30分钟没有主动释放掉,druid就会自动释放掉,也就是说,代码停止了30分钟。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
查看一下数据库连接数相关 还有检查一下是否存在其他调用没有进行连接释放
定时任务的处理逻辑时间会很久吗?
如果超过了
removeAbandonedTimeout
设定的时间 Druid会将这个连接回收remove