系统使用Druid数据库连接池,数据库使用mysql。由于是多业务在一个系统里里,每个业务连接一个数据库连接。所以,系统启动后,就会创建好几个Druid连接池去连接几个业务数据库。
目前遇到问题如下:
之前上的客户一直没遇到问题,最近上了一个新客户,多个业务系统里有一个报销系统,新客户涉及到用户很多,大约4千到5千人。新客户系统上线后,每天不定时会遇到后台服务卡死的问题。之前私下和杜总请教过,在杜总的指导下,逐步发现了问题所在。在系统卡死的时候,只要涉及到数据库访问的请求,全部不响应,不涉及到数据库连接的接口不受影响。其他用户量小的业务系统完全不受影响。因此就用arthas在线查看task线程的状态,发现众多waitting状态的task线程。打印线程的状态,可以看到都是在拿数据库连接的时候,线程卡死了。也就是卡死的task线程全部卡在拿数据库连接上。从下图可以看到明显是卡在拿数据库连接上了:
上网搜了一下druid的相关信息。说是拿数据库连接的时候,如果拿不到,就会一直卡在那里等。那我就把这个等待时间设置为100毫秒。这次不会卡死,但系统过一会儿就抛异常,说拿不到有效的数据库连接。我看了DruidPlugin的代码,它默认最大连接池连接数是32,这个是不是太小了?我尝试改到100,这次撑的时间久一些,能撑大半天或则一天,但还是会报无法拿到数据库连接的异常。业务系统里就两个使用方式,一种是隐式事务,就是直接查或则更新,autocommit=true的那种。一种就是声明IAtom接口实现,通过return false和return true控制事务的提交和回滚。
我的想问的问题是:我提升了maxActive到100,还是会遇到后面的请求拿不到数据库连接的异常问题,是因为并发量确实大,100个还是不够,还是因为前面的业务并没有把数据库连接归还到连接池呢?如果是确实并发量大,100个不够用,那我加大到500,甚至1000都可以。但如果是业务没有归还数据库连接到连接池,那我就是加到1万也没用,早晚还是会消耗完。
因为是多业务系统,所以业务代码都会使用Db.use("配置名称").find这样的方式访问数据库,要么就是使用实体里类直接操作数据库。jfinal不应该是在用完数据库连接后,自动把数据库连接放回到连接池吗?还是需要注意些什么?
麻烦指导一下!谢谢!
SHOW VARIABLES LIKE 'max_connections';
最大允许连接数
SHOW STATUS LIKE 'Max_used_connections';
历史最大并发连接数