從昨天開(kāi)始,我們突然遇到了一個(gè)問(wèn)題,就是連接到數(shù)據(jù)庫(kù)時(shí),提示Too many connections.即使知道這個(gè)錯(cuò)誤是由于同時(shí)打開(kāi)的連接數(shù)太多導(dǎo)致的,然而還是有點(diǎn)懵.因?yàn)榧词刮彝V沽宋⒎?wù),在通過(guò)show status查看MySQL的當(dāng)前連接數(shù),還是沒(méi)有變化.
一天中出現(xiàn)了兩次這樣的錯(cuò)誤,由于沒(méi)有時(shí)間來(lái)解決,所以我只能暫時(shí)通過(guò)重啟MySQL的做法,來(lái)暫時(shí)處理一下.但是這樣終究不是長(zhǎng)遠(yuǎn)之計(jì).
我們通過(guò)show processlist命令,發(fā)現(xiàn)大多數(shù)連接都處于sleep狀態(tài),也就是說(shuō),并沒(méi)有被使用,也沒(méi)有被釋放.而HikariCP確實(shí)在微服務(wù)被停止時(shí),被關(guān)閉了.于是猜測(cè)是微服務(wù)被關(guān)閉時(shí),出了些問(wèn)題,比如突然斷網(wǎng)了,導(dǎo)致MySQL只好等待一定的超時(shí)時(shí)間,等到請(qǐng)求超時(shí)之后,才關(guān)閉連接.
而這個(gè)超時(shí)時(shí)間一般不應(yīng)該是很短嗎?為什么連接在微服務(wù)停止后的半個(gè)小時(shí)之后都沒(méi)有被釋放?
實(shí)際上,這個(gè)超時(shí)時(shí)間,默認(rèn)是八個(gè)小時(shí)!!!
在MySQL的配置文件中,使用wait_timeout這一項(xiàng)來(lái)表示.
這么長(zhǎng)的超時(shí)時(shí)間,對(duì)于使用連接池的有狀態(tài)的Java應(yīng)用來(lái)說(shuō),可能正好合適.但是對(duì)于一些不使用連接池的應(yīng)用來(lái)說(shuō),如果連接沒(méi)有被正確關(guān)閉,就要等待8小時(shí)超時(shí)之后才能關(guān)閉,未免有點(diǎn)浪費(fèi)資源.這樣很快就到達(dá)了MySQL的max_connections限制,導(dǎo)致出現(xiàn)Too many connections這個(gè)錯(cuò)誤.
實(shí)際上,在我們開(kāi)發(fā)階段,因?yàn)槭褂昧诉B接池,反而更加助紂為虐,因?yàn)槲覀冃枰l繁的關(guān)閉并重新打包微服務(wù),然后重新運(yùn)行,每次運(yùn)行,都需要新建一個(gè)有200個(gè)連接的連接池,而我們的MySQL的**max_connections **總共才300.這樣在第二次運(yùn)行時(shí),就會(huì)出現(xiàn)錯(cuò)誤.
所以,我們先調(diào)整一下MySQL的wait_timeout,將其調(diào)整成10分鐘,同時(shí),減少Hikari連接池的建立的連接數(shù),將其調(diào)整成10.
而且,我注意到,只有當(dāng)我的HikariCP連接池設(shè)置的很大時(shí),出現(xiàn)了Too many connections錯(cuò)誤時(shí),此時(shí)停止微服務(wù),才會(huì)導(dǎo)致連接并沒(méi)有被完全釋放.不知道是否是HikariCP連接池的bug.有時(shí)間閱讀一下源碼,看一下.