MySQL中間件之ProxySQL(5):線程、線程池、鏈接池

返回ProxySQL系列文章:http://www.cnblogs.com/f-ck-need-u/p/7586194.htmlhtml

 

1.ProxySQL的線程

ProxySQL由多個模塊組成,是一個多線程的daemon類程序。每一個模塊都有一個或多個線程去執行任務。mysql

例如,如下是剛啓動ProxySQL時的進程狀況,一個main進程,一個主線程,21個線程。sql

[root@s1 ~]# pstree | grep proxy    
        |-proxysql---proxysql---21*[{proxysql}]

下面是正常運行時使用的線程列表:數據庫

1.1 Main thread

這實際上是一個進程,該進程只負責引導、啓動核心模塊以及啓動其它核心線程。後端

1.2 Admin thread

該線程負責如下幾件事:緩存

  • 初始化並引導啓動Admin接口。
  • 從磁盤數據庫或配置文件中加載配置,爲ProxySQL的運行提供環境。
  • 啓動一個監聽者,讓其負責監聽並接受到Admin接口的新鏈接,併爲每一個這樣的鏈接建立一個新線程。

因此,每鏈接一次admin接口,就會新生成一個線程。每次退出admin接口時,減去一個線程。安全

1.3 MySQL workers

mysql-threads線程負責處理MySQL流量,包括全部來自客戶端的鏈接以及全部到後端服務器節點的鏈接。也就是:用少許線程處理任意多數量的鏈接。服務器

MySQL workers線程在相同的端口上進行監聽。當新客戶端發起鏈接請求,其中一個MySQL worker線程將成功接受該鏈接,並建立一個MySQL會話(session):客戶端和會話綁定在該worker線程上,直到鏈接斷開。換句話說,在斷開鏈接以前,某客戶端的全部鏈接老是被同一個worker線程處理。session

默認狀況下,MySQL worker的線程數量爲4。多線程

mysql> select @@mysql-threads;
+-----------------+
| @@mysql-threads |
+-----------------+
| 4               |
+-----------------+

mysql-threads變量修改後,必須重啓ProxySQL才能生效,這是少有的須要重啓的變量之一(另外一個是mysql-stacksize)。例如,修改成8個mysql worker線程。

set mysql-threads=8;
save mysql variables to disk;

select * from runtime_global_variables 
 where variable_name='mysql-threads';
+---------------+----------------+
| variable_name | variable_value |
+---------------+----------------+
| mysql-threads | 4              |
+---------------+----------------+

service proxysql stop
service proxysql start

select * from runtime_global_variables 
 where variable_name='mysql-threads';
+---------------+----------------+
| variable_name | variable_value |
+---------------+----------------+
| mysql-threads | 8              |
+---------------+----------------+

1.4 MySQL auxiliary threads

這些線程其實就是空閒線程(idle threads)

若是proxysql使用--idle-threads選項啓動,每一個worker線程都會伴隨啓動一個auxiliary線程。每一個worker線程以及它的auxiliary線程一塊兒工做:第一個線程處理活動的鏈接,並將全部的空閒鏈接派遣到第二個線程上,但第二個線程只要等待到了發生在空閒鏈接上的一個事件(或超時),就會將鏈接還給第一個線程。

當活動的客戶端鏈接數量遠少於空閒客戶端鏈接數量時,強烈建議使用"idle threads"。這使得ProxySQL能夠處理幾十萬個鏈接(測試時是100W個鏈接)。

1.5 Monitor模塊相關的線程

monitor模塊有本身的線程管理系統,還有本身的線程池。正常狀況下,monitor模塊有如下幾個線程:

  • 一個master線程,負責生成、協調其它monitor相關的線程。
  • 一個負責監控connect的線程。
  • 一個負責監控ping的線程。
  • 一個負責監控read_only的線程。
  • 一個負責監控replication lag的線程。
  • 一個線程池提供monitor worker線程,上面每一個監控線程都是任務的生產者,worker線程從任務隊列消費一個任務並執行該任務。該線程池初始時默認爲mysql thread的兩倍。

線程池負責執行全部的檢查任務,並經過以上各調度線程來監控調度狀況。線程池會基於監控隊列中待檢查的數量多少而自動增加、收縮。基於檢查的結果,會使用相同的線程對結果進行處理,例如避開一個節點、從新配置一個主機組。

1.6 Query Cache purge thread

該線程是須要時才生成的,它扮演的是垃圾收集器,回收查詢緩存。經過垃圾收集器,可保證在客戶端等待響應的過程當中毫不會回收緩存。

1.7 其它線程

在ProxySQL運行過程當中,偶爾會派生臨時線程,這些臨時線程是爲了向後端發送KILL語句,以便殺掉後端服務器上對查詢長時間無響應的查詢線程。

此外,ilbmariadbclient庫還會使用一些後臺線程,這些線程是爲了和後端MySQL server進行一些特定的異步交互任務。

還有一些模塊,例如內置的Http server,正處於實驗階段的cluster、ClickHouse Server、SQLite3 Server,若是啓用了這些功能,則會按需建立它們對應的線程。

2.ProxySQL的線程池

在ProxySQL中,有兩個地方使用了線程池:

  • 快速創建和後端MySQL的鏈接:ProxySQL爲了儘快和後端MySQL創建新的TCP鏈接,使用了一個線程池來等待accept()返回新鏈接。
  • Monitor模塊:爲了儘快執行各監控線程生產的監控任務,monitor模塊提供了一個monitor worker線程池,能夠快速從任務隊列中消費任務。

須要注意的是,正常狀況下,MySQL worker線程是最繁忙、最消耗CPU資源的部分,但在一個極其繁忙的環境下,monitor模塊須要監控的鏈接數過多,消耗的CPU也是不可忽視的。

3.ProxySQL的鏈接池

ProxySQL一樣有兩個鏈接池,和線程池部分是對應的。

3.1 快速鏈接到後端MySQL節點

線程池是爲了快速和後端創建新的TCP鏈接,而這裏的鏈接池是爲了快速和後端創建鏈接。

ProxySQL使用一個鏈接池來存放必定數量的"以前已經和某後端創建鏈接,但當前是空閒鏈接"的鏈接。當須要向這些鏈接對應的後端發送新的數據包時,能夠快速地取回鏈接,由於這些鏈接早已經被打開。

當應用程序發送了一個MySQL請求給ProxySQL時,ProxySQL首先解析要路由到哪一個後端,若是鏈接池中已經有和該後端的鏈接,將重用該鏈接,不然將建立一個新的和後端的鏈接。

當處理完客戶端的請求後,鏈接會還回主機組管理器(HostGroup Manager)。若是主機組管理器判斷了該鏈接是能夠被安全共享的,且鏈接池未滿,則該鏈接會放進鏈接池。

放進鏈接池的鏈接都是空閒鏈接,正在使用的鏈接是不可能進入鏈接池的。ProxySQL會按期發送ping消息來維持空閒鏈接。若是某鏈接從上一次ping以後,若是尚未被使用,則該鏈接被定義爲空閒鏈接。對於空閒鏈接ping的時間間隔由變量mysql-ping_interval_server_msec控制。

可是,不是全部的未使用的鏈接都會放進鏈接池。該變量用來控制某後端的空閒鏈接和最大總鏈接數的百分比。對於每一個hostgroup/backend,主機組管理器只會保持鏈接池中的最大鏈接數爲mysql-free_connections_pct * mysql_servers.max_connections / 100。池中的每一個空閒鏈接都經過間斷性的ping來維持它的打開狀態。

當一個鏈接放回鏈接池時,會計算這個鏈接以後還能處理多少個語句,當處理的語句數量達到該閾值後,將關閉該鏈接(v1.4.3以前)或者重置該鏈接(從v1.4.4開始)。

3.1.1 相關變量

mysql-ping_interval_server_msec
ProxySQL爲了維持和後端的空閒鏈接,每隔一段時間發送一次ping,該變量指定發起ping的時間間隔。默認值爲10000毫秒(即10秒)。

mysql-ping_timeout_server
ProxySQL爲了維持和後端的空閒鏈接,每隔一段時間發送一次ping。該變量指定ping獲得回覆的超時時間。默認值爲200毫秒。

mysql-connection_max_age_ms
當該變量設置的值大於0時(單位毫秒),若是某個空閒鏈接(當前沒有任何會話使用)的空閒時長超過了這裏設置的值,則這個鏈接會關閉。默認值爲0,表示不會由於存活時間而關閉空閒鏈接。

3.2 Monitor模塊的鏈接池

Monitor有它本身的鏈接池。當鏈接池中空閒鏈接的空閒時長達到了3 * mysql-monitor_ping_interval(毫秒)後,該空閒鏈接將自動被purge。

變量mysql-monitor_ping_interval的默認值爲1分鐘(60000毫秒),因此,monitor鏈接池中的空閒鏈接默認最長維持3分鐘。

相關文章
相關標籤/搜索