赞
踩
一、问题描述
正在给毕业设计(采用的微服务架构)的统一网关进行完善时,刚开始,正常运行,突然改完逻辑bug之后启动,报错
Too many connections
二、排查问题
报错信息
根据报错信息,很快可以进行问题定位
,本身程序没有问题,是数据库那边的服务应用报错 Too Many Connections ,很显然肯定是MYSQL的连接数过大。
MYSQL分析
(1)登录Mysql,发现 采用 mysql -u root -p
进行连接也会报错 Too Many Connections,于是 既然连接数过多,那我把现有的连接都关了,即可连接去设置 最大连接数
(2)关闭、释放现有连接,可依旧报错–【??内心疑问,,大概率是连接虽然关闭了,可MYSQL自身的运行、睡眠线程未释放】
(3)直接重启MYSQL service mysqld restart 或 service mysql restart
,果然重启是解决问题的最好办法–,然后再根据需要设置最大线程数set global max_connections = 10000
(1)show status like 'Thread%'
查看线程数分配情况和 show variables like '%max_connections
查看最大线程;
(2)设置一个可控的最大线程数,并递增连接MYSQL;发现一个现象
当最大线程数设置较大时,每添加一个数据源连接多固定的10个线程,用IDEA工具连接,只需要一个线程;
当最大程序树较小时,每添加一个数据源连接时,多2个不等的线程消耗。
说明:当线程够用时,就尽情的挥霍,不够用则省着用,符合情理
(3)分析MYSQL的线程池和线程原理(请参考)
线程池
线程池由许多线程组构成,每个组管理一系列客户端连接。一旦连接被建立,线程池会以轮询调度(round-robin)的方式把其分配给线程组。
每个线程组可拥有的最大线程数量为4096(或4095,在一些操作系统上,其中一个线程供内部使用)
线程池隔离了连接和线程,所以线程和连接之间没有固定的关系,这和缺省的线程处理模式不一样。缺省的线程处理模式会把线程同连接关联,这样以便线程执行来自连接的所有语句。
任何时刻,线程组尽量确保每个线程组中至多只有一个执行线程,但有时候,为了最佳性能,允许多余一个临时的执行线程。算法如下:
l 每个线程组有一个监听线程,监听来自分配给线程组的连接的语句。当语句到达时,线程组或者立刻开始执行,或放入队列等待稍后执行。
n 如果仅收到语句,且当前队列中没有排队等待执行的语句,或者无正在执行的语句,则立即执行
n 如果语句不能立即被执行则放入队列。
l 如果立即执行语句,那么由监听线程来执行(这意味着线程组中暂时没有线程在监听)。如果语句快速执行完,执行线程返回继续监听语句。否则,线程池会认为该语句执行滞后,并开启另一个线程作为监听线程(如果有必要的话)。为了保证没有线程组被执行滞后的语句阻塞,线程池有个后台线程定期监控线程组状态。
通过使用监听线程来执行可立执行的语句,如果语句可以快速执行完的话,不必创建一个额外线程。这样确保了在线程数很少的情况下,最大的执行效率。
当开启线程组插件时,它会为每个线程组创建一个线程(监听线程),外加一个后台线程。有必要的话创建额外的线程来执行语句。
l 线程池关注于限制当前短时间运行的语句数量。执行语句到达停滞时间(stall time)之前,它会阻止其它语句开始执行。如果语句超过停滞时间,则允许其继续执行,但是不再阻止其它语句的运行。通过这种方式,线程池尽力确保每个线程组中,不多于一个短时间运行的执行语句。
l 如果语句遇到磁盘I/O操作或用户级锁(行锁或表锁),语句将被阻塞。这种阻塞会导致线程组变得不可用,所以会有针对线程组的回调来确保线程池可以在改组中立即开启一个新的线程来执行其它的语句。当返回一个阻塞线程时,线程池允许立即重启它。
l 有两个队列,一个高优先级(high-priority)队列和一个低优先(low-priority)级队列。事务中的第一条语句分配到低优先级队列。如果事务正在进行(刚开始执行事务中的语句),接下来的其它任意语句分配到高优先级队列,否则进入低优先级队列。队列分配可通过thread_pool_high_priority_connection系统变量来控制,开启该系统变量会导致会话中所有排队中的语句分配到高优先级队列
针对非事务性存储引擎或开启autocommit下的事务性存储引擎的语句,被视为低优先级语句,因为这种情况下,每条语句都是一个事务。如果给定的语句既有针对InonoDB表,也有MyISAM表的,那么线程池会为针对InnoDB表的语句安排更高的优先级,除非开启了autocommit。如果开启了autocommit,所有语句都是低优先级。
l 当线程组从队列中选取语句进行执行时,它先在高优先级队列中查找,然后低优先级队列。如果找到语句则将其从队列中移除并开始执行它。
l 如果语句在低优先级停留太久,线程池会把它移到高优先级队列。thread_pool_prio_kickup_timer系统变量控制了这个“停留时间”。对每个线程组来说,语句停留的最大时间为10ms。
l 线程池重用最活跃的线程来获取对CPU缓存更好的利用。这个小的调整对性能有重大的影响。
三、思考
对于MYSQL的连接线程、实则为线程池的一个管理连接问题,可以理解为资源统一管理者,分发资源需要根据自身的情况去量体裁衣,而不同的线程需要各司其职,当资源有限时只需开启核心线程去解决问题,但当资源够用则全部开启去满足。–可对标 理解docker和虚拟机,docker是一个轻量级的只使用内核OS,小巧轻便,而虚拟机则笨重,硬件层面虚拟化。对于线程池合理管理线程的这样弹性可伸缩性,应该是一种设计所推崇的。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。