进程启动后,线程数迅速上升至最小线程数后,缓慢上升(线程池限制)到数千,而后因为线程过多,CPU飙升到90%。sql
对外表现为Api无响应或链接超时。数据库
有些数据存在于另外一个机房,经过内网专线链接。一个服务程序有4个数据库,其中3个在本地机房,1个在外地。 api
各类排查,没有解决。缓存
函数中,第一句的GetKey函数以下,其中有一个lock。其中代码仅仅是赋值,或是在集成认证的状况下才执行。因此卡住的可能性不大。服务器
第二句是个赋值,且MysqlPoolManager.pools是个字段(field),理论上不会卡住。网络
第二个lock中,若是指定key对应的缓存已存在,则lock会很快返回。若是不存在,则执行new MysqlPool(setttings);函数代码以下:
异步
其主要功能有socket
这5个步骤中,最可能耗时较久的是步骤d。其余步骤理论上不会有问题。函数
步骤d中的代码,虽然就一个函数,可是代码不少。spa
通过不停的查看代码,发现其主要功能是根据链接字符串中的设置,建立一个指定类型的链接。其底层建立代码以下:
能够看到,任何建立Stream失败的状况都会抛出异常,最终致使链接池建立失败。
其中第一句,GetStream的底层代码以下:
开始链接(BeginConnect)后,即开始了等待。等待的超时默认值以下:
2147483s,即596h。若是有链接到数据库服务器的网络有问题或其余缘由致使链接不成功,而也未触发其余致使失败的状况,则会一直等下去。若是推断正确,那么全部线程中,必定有线程的调用堆栈在以下位置:
对Dump文件中的全部线程堆栈排序,有且仅有一个线程处于该调用堆栈处。高亮行正是上述堆栈的函数名CreateSocketStream。上面一行就是WaiteOne。以后进入本机代码。
那么根本缘由也就清楚了:一个链接的建立卡住了数据库链接建立,间接卡住了链接池的锁,又间接卡住了其余链接池的使用和建立。致使全部数据库链接不可用。因此,全部进入的请求通过运行,所有堆在GetPool这里。
以上全部信息基于.Net版本Mysql.Data 6.9.9版本反编译分析。