快捷搜索:  汽车  科技

mysql 网络异常(为什么网络波动恢复后)

mysql 网络异常(为什么网络波动恢复后)线程池配置代码如下: /** * 核心线程数,默认为1 */ private static final int corePoolSize = 20; /** * 最大线程数,默认为Integer.MAX_VALUE */ private static final int maximumPoolSize = 100; /** * 线程池维护线程所允许的空闲时间,默认为60s */ private static final long keepAliveTime = 30L; /** * 线程池维护线程所允许的空闲时间的单位 */ public static final TimeUnit unit = TimeUnit.SECONDS; /**

22年7月的某一天下午公司网络故障,导致很多应用出现了异常。随着网络的恢复,应用也在恢复,唯独公司的统一登录平台没有恢复,DBA同学监控从监控平台看了一下,发现4台mysql连接池被打满。然后紧急进行应用扩容,结果也没有马上恢复。

mysql 网络异常(为什么网络波动恢复后)(1)

网络恢复后mysql连接监控

错误信息:

2022-07-26 15:15:28 [WARN ] [o.h.e.j.s.SqlExceptionHelper][129] -SQL Error: 0 SQLState: null 2022-07-26 15:15:28 [ERROR] [o.h.e.j.s.SqlexceptionHelper][131] -slave1 - Connection is not available request timed out after 30001ms. 2022-07-26 15:15:28 [WARN ] [c.i.b.w.c.BFFMobileController][230] -[96097BC7-CD7C-4A04-B722-CC3BD8207764]- 516029010|login exception javax.persistence.PersistenceException: org.hibernate.exception.JDBCConnectionException: could not prepare statement at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:149) at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:157) at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1423) at com.idsmanager.micro.commons.repository.AbstractRepositoryHibernate.find(AbstractRepositoryHibernate.java:49) at com.idsmanager.micro.commons.repository.AbstractRepositoryHibernate.findByUuid(AbstractRepositoryHibernate.java:65) at com.idsmanager.oauth.infrastructure.hibernate.UserRepositoryHibernate.findByUuid(UserRepositoryHibernate.java:113) at com.idsmanager.oauth.service.impl.UserServiceImpl.findByUuid(UserServiceImpl.java:91) at sun.reflect.GeneratedMethodAccessor593.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497)

这个问题一直没有找到根本原因,上周领导让我们团队进行协助分析。从统一登录团队代码分析发现了造成这个现象的原因,是登录的时候使用了多线程进行用户信息的获取。

线程池配置代码如下:

/** * 核心线程数,默认为1 */ private static final int corePoolSize = 20; /** * 最大线程数,默认为Integer.MAX_VALUE */ private static final int maximumPoolSize = 100; /** * 线程池维护线程所允许的空闲时间,默认为60s */ private static final long keepAliveTime = 30L; /** * 线程池维护线程所允许的空闲时间的单位 */ public static final TimeUnit unit = TimeUnit.SECONDS; /** * 线程池所使用的缓冲队列 */ private static BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(1000); /** * 线程池对拒绝任务(无线程可用)的处理策略,目前只支持AbortPolicy、CallerRunsPolicy;默认为后者 * a.AbortPolicy:直接抛出java.util.concurrent.RejectedExecutionException异常 * b.CallerRunsPolicy:主线程直接执行该任务,执行完之后尝试添加下一个任务到线程池中,可以有效降低向线程池内添加任务的速度 * c.DiscardOldestPolicy:抛弃旧的任务、暂不支持;会导致被丢弃的任务无法再次被执行 * d.DiscardPolicy:抛弃当前任务、暂不支持;会导致被丢弃的任务无法再次被执行 */ private static RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();

Mysql 连接池配置如下:

#连接超时时间30秒 spring.datasource.hikari.connection-timeout=30000 #最小连接数 spring.datasource.hikari.minimum-idle=20 #最大连接数 spring.datasource.hikari.maximum-pool-size=200 spring.datasource.hikari.leak-detection-threshold=5000 spring.datasource.hikari.validation-timeout=3000

从如上代码分析,根本原因是:在网络波动的时候,应用无法连接到数据库,这时候线程池等待的任务有1000个,活着的线程有100个,六个实例有6600个查询任务。等网络恢复后,一瞬间进行数据库的连接与查询,并且还有很多用户进行登录操作,每个mysql连接池的数据量为200,6个实例的连接数是1.2k,这就是第一个连接高平台,后续进行了扩容操作,扩容到8个节点,连接数变成了1.6k,这就是第二个连接高平台。

猜您喜欢: