天天看點

ProxySQL源碼分析4-線程分析

ProxySQL源碼分析4-線程分析
  1. Main thread

    初始化核心子產品和線程。Main線程最後一部分用watchdog做mysql work線程和idle線程的heartbeat檢查,如果超過20次則重新開機proxy,如果設定restart,則無限重新開機。

  2. Admin thread

    核心循環:admin_main_loop,是Admin子產品最重要的循環

    建立并監聽Admin端口(預設的6032),為每個admin連接配接建立一個新的線程。

    加載各種配置資訊,以及管理配置變更(動态加載、持久化到sqlite)等。

    如果配置HTTP Server,AdminRestApiServer,還會負責啟動這些Server并處理web請求。

這裡有一個比較trick的事情,admin這個管理賬号隻能local連接配接,其他賬号可以遠端連接配接,其他這些賬号都是一樣的管理者權限。如果硬要解釋,那就是coder的情懷了~
  1. MySQL workers threads & MySQL idle threads

    worker thread負責處理活躍的用戶端mysql請求,是主要的工作線程。

    idle thread主要就是監聽非活躍的Session是否有新的請求,然後移交給worker線程處理。

    當活躍連接配接遠小于非活躍連接配接的時候,idle和worker搭配可以很好地提高性能。官網資料可處理連接配接能到1百萬。

    idle thread和work thread是1:1建立的。其互動流程入下圖所示。

    ProxySQL源碼分析4-線程分析
  2. Monitor threads

    産生5類生産者線程:connection checks、ping checks、read-only checks、replication lag checks、group replication monitoring

    排程消費線程池:一方面負責check任務; 另一方面就是處理上面的check結果,比如ping失敗之類的。處理主要是通過更新 MyHGM->p_update_mysql_error_counter狀态來實作,如下代碼。

void *monitor_ping_thread(void *arg) {
    MySQL_Monitor_State_Data *mmsd = (MySQL_Monitor_State_Data *) arg;
 
    if (mmsd->interr) { // ping failed
        MyHGM->p_update_mysql_error_counter(p_mysql_error_type::proxysql, mmsd->hostgroup_id, mmsd->hostname,
                                            mmsd->port, mysql_errno(mmsd->mysql));
    } else {
        if (crc == false) {
            GloMyMon->My_Conn_Pool->put_connection(mmsd->hostname, mmsd->port, mmsd->mysql);
            mmsd->mysql = NULL;
        }
    }
    ...
    if (ping_success) {
        __sync_fetch_and_add(&GloMyMon->ping_check_OK, 1);
    } else {
        __sync_fetch_and_add(&GloMyMon->ping_check_ERR, 1);
    }
}
           
  1. Query Cache purge thread

    對query cache執行一個垃圾回收的功能

// ProxySQL_Admin::load_proxysql_servers_to_runtime(bool _lock)
// char *query=(char *)"SELECT hostname, port, weight, comment FROM proxysql_servers ORDER BY hostname, port";
void ProxySQL_Cluster_Nodes::load_servers_list(SQLite3_result *resultset, bool _lock) {
    for (std::vector<SQLite3_row *>::iterator it = resultset->rows.begin(); it != resultset->rows.end(); ++it) {
        ...
        if (ite == umap_proxy_nodes.end()) {
            ...
            // 每個Server都建立所有連接配接
            if (pthread_create(&a->thrid, &attr, ProxySQL_Cluster_Monitor_thread, (void *) a) != 0) {
                ...
            }
        } else {
            ...
        }
    }
}