本文已参加「新人创造礼」活动, 一起敞开创造之路。
那是一个休闲的周六上午,我吃着面,突然看到作业群信息两条告警信息:1.出产数据库反常。2.下单事务衔接数据库失利……不是吧阿sir,这种事都能让我碰到,手中的面突然不香了。接着领导信息接踵而来,我说赶忙先让运维重启数据库服务器吧,我也没权限操作数据库服务器呀。说完大量吸入手中的拌面,赶忙回家看看问题。
事务背景
数据库主从相似keepalived的机制,主从都安装keepalived,keepalived会定时检测心跳,主机器挂了会进行vip飘移。简单来说便是拜访43VIP,便是拜访41,检测到41挂了,就会进行VIP漂移和数据库主从切换。一开始是说vip没飘过去,我就说赶忙重启41。。不然无法玩,后面说现已飘过去了,43是能拜访的,可是程序仍是有问题。我还以为是43拜访不了,那就和程序没有关系,本来仍是有关系的….。然后运维重启了在线体系,问题解决。
问题定位
由于运维重启前没有打印线程快照,所以只能通过事务日志的时刻去定位问题…..
首先记录几个时刻:
毛病发生时刻 11:36:28 – 11:54:30
最终一次HTTP恳求回来:11:37:13
途径:tomcat的logs目录下localhost_access_log.2023-03-11.txt
第一次体系报错时刻:11:37:21
途径:catalina.out
确定在36分半的时分,数据库现已挂了,在线体系的恳求全卡在恳求数据库那里,然后坚持了差不多一分钟就无法处理恳求了。体系卡了20分钟,重启后恢复。
毛病分析
为什么获取数据库衔接失利没有抛反常呢?
由于c3p0衔接池的5秒超时被注释掉了。。为什么注释掉了呢,这要追溯到上一次的出产事端了…大概便是某一天的并发很高,然后体系网络又有点卡顿,导致数据库衔接数满了,有一些衔接恳求数据库5秒后就抛反常了,最关键的是..体系try catch把反常吞了,导致没有触发重试机制。然后领导就觉得让他渐渐消费也能够,就注释掉了。这其实算是一个策略,数据库衔接池满了究竟怎么处理,假如是短时刻内的阻塞,能够让他渐渐消费,假如是长时刻的阻塞,就只能抛反常了。就要从成果来说仍是要设置超时时刻比较好,就不会导致恳求阻塞。。
为什么会报C3P0的死锁?
网上搜c3p0 APPARENT DEADLOCK发现一大堆事例。我以为是由于这个死锁导致的体系溃散,成果在本地环境能复现这个问题。我是本地搭了一个数据库,然后没有发动服务,衔接池连不上就会报这个过错。
接着我测验拜访下单接口,看看多久回来
2分钟。。直接卡死
假如设置了超时时刻
接着我再把本地数据库翻开,体系正常拜访,所以问题是和c3p0死锁没有关系,便是恳求全阻塞了。
优化方案
- 设置超时时刻5秒,尽管可能会扔掉一部分恳求,可是不至于阻塞整个体系
- 事务拆分,把关键事务和非关键事务分开布置,现在是由于一个上报接口并发太高导致tomcat衔接数和数据库衔接数都用完了,后期还能根据事务拆分数据库。
- 加大tomcat衔接和c3p0数据库衔接数,现在tomcat默许200的衔接数,c3p0最大设置200,要把这两个参数翻倍,让体系再坚硬一瞬间。
- 数据库主从切换时刻要更迅速一点,一分多钟才切换成功有点久了
- 告警出现值班运维要立刻查看体系cpu和内存使用情况,假如出现反常需求记录下来,并打印线程快照,最终重启服务。
总结
由于主库挂了导致4台集群无法作业,便是由于一个超时时刻的问题,也确实不应该。只能用要多想想一些特别的情况,比方数据库挂了怎么办,线程池满了怎么办,http恳求超时怎么办。一个大事端的发生都是多个小问题引起的。别的微服务思想也是重要的,不能由于某个小事务并发高导致体系阻塞。