MySQL中介軟體之ProxySQL(5):執行緒、執行緒池、連線池

駿馬金龍發表於2018-07-09

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

 

1.ProxySQL的執行緒

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

例如,以下是剛啟動ProxySQL時的程式情況,一個main程式,一個主執行緒,21個執行緒。

[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執行緒處理。

預設情況下,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分鐘。

相關文章