返回ProxySQL系列文章:http://www.cnblogs.com/f-ck-need-u/p/7586194.htmlhtml
ProxySQL由多個模塊組成,是一個多線程的daemon類程序。每一個模塊都有一個或多個線程去執行任務。mysql
例如,如下是剛啓動ProxySQL時的進程狀況,一個main進程,一個主線程,21個線程。sql
[root@s1 ~]# pstree | grep proxy |-proxysql---proxysql---21*[{proxysql}]
下面是正常運行時使用的線程列表:數據庫
這實際上是一個進程,該進程只負責引導、啓動核心模塊以及啓動其它核心線程。後端
該線程負責如下幾件事:緩存
因此,每鏈接一次admin接口,就會新生成一個線程。每次退出admin接口時,減去一個線程。安全
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 | +---------------+----------------+
這些線程其實就是空閒線程(idle threads)。
若是proxysql使用--idle-threads
選項啓動,每一個worker線程都會伴隨啓動一個auxiliary線程。每一個worker線程以及它的auxiliary線程一塊兒工做:第一個線程處理活動的鏈接,並將全部的空閒鏈接派遣到第二個線程上,但第二個線程只要等待到了發生在空閒鏈接上的一個事件(或超時),就會將鏈接還給第一個線程。
當活動的客戶端鏈接數量遠少於空閒客戶端鏈接數量時,強烈建議使用"idle threads"。這使得ProxySQL能夠處理幾十萬個鏈接(測試時是100W個鏈接)。
monitor模塊有本身的線程管理系統,還有本身的線程池。正常狀況下,monitor模塊有如下幾個線程:
connect
的線程。ping
的線程。read_only
的線程。replication lag
的線程。線程池負責執行全部的檢查任務,並經過以上各調度線程來監控調度狀況。線程池會基於監控隊列中待檢查的數量多少而自動增加、收縮。基於檢查的結果,會使用相同的線程對結果進行處理,例如避開一個節點、從新配置一個主機組。
該線程是須要時才生成的,它扮演的是垃圾收集器,回收查詢緩存。經過垃圾收集器,可保證在客戶端等待響應的過程當中毫不會回收緩存。
在ProxySQL運行過程當中,偶爾會派生臨時線程,這些臨時線程是爲了向後端發送KILL語句,以便殺掉後端服務器上對查詢長時間無響應的查詢線程。
此外,ilbmariadbclient庫還會使用一些後臺線程,這些線程是爲了和後端MySQL server進行一些特定的異步交互任務。
還有一些模塊,例如內置的Http server,正處於實驗階段的cluster、ClickHouse Server、SQLite3 Server,若是啓用了這些功能,則會按需建立它們對應的線程。
在ProxySQL中,有兩個地方使用了線程池:
須要注意的是,正常狀況下,MySQL worker線程是最繁忙、最消耗CPU資源的部分,但在一個極其繁忙的環境下,monitor模塊須要監控的鏈接數過多,消耗的CPU也是不可忽視的。
ProxySQL一樣有兩個鏈接池,和線程池部分是對應的。
線程池是爲了快速和後端創建新的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開始)。
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,表示不會由於存活時間而關閉空閒鏈接。
Monitor有它本身的鏈接池。當鏈接池中空閒鏈接的空閒時長達到了3 * mysql-monitor_ping_interval
(毫秒)後,該空閒鏈接將自動被purge。
變量mysql-monitor_ping_interval
的默認值爲1分鐘(60000毫秒),因此,monitor鏈接池中的空閒鏈接默認最長維持3分鐘。