1. 程式人生 > >dbporxy-mysql 協議流轉圖

dbporxy-mysql 協議流轉圖

span length mysql 順序 network 狀態 驗證 hand 第一個

dbproxy 支持 in 查詢, 當in 中的字段 屬於不同的分表時, QPS約為 5000左右, 如果為 等值查詢, qps的30000左右

主要原因是 對於in操作,會產生多個不同分表的sql, 這些sql的發送完全是順序的, 發送第二個sql, 要完全等到 第一個SQL結果的返回,

src/network-mysqld.c

void network_mysqld_con_handle(int event_fd, short events, void *user_data) {
    switch (con->state) {
         case CON_STATE_INIT:
            
//執行NETWORK_MYSQLD_PLUGIN_PROTO(proxy_init) plugin_call(srv, con, con->state); break; case CON_STATE_CONNECT_SERVER: //執行NETWORK_MYSQLD_PLUGIN_PROTO(proxy_connect_server) //準備發給client的隨機挑戰數 plugin_call(srv, con, con->state);
break; case CON_STATE_SEND_HANDSHAKE: //向client發送挑戰隨機數 network_mysqld_write(srv, con->client); //此處沒有對應的函數指針, 只是設置下state 為 CON_STATE_READ_AUTH; plugin_call(srv, con, con->state); break; case CON_STATE_READ_AUTH:
//讀取client返回數據 network_mysqld_read(srv, recv_sock); //NETWORK_MYSQLD_PLUGIN_PROTO(proxy_read_auth) 設置狀態為CON_STATE_SEND_AUTH_RESULT plugin_call(srv, con, con->state); case CON_STATE_SEND_AUTH_RESULT: //向client寫驗證返回數據 network_mysqld_write(srv, con->client); //沒有對應的函數指針, 設置狀態為 CON_STATE_READ_QUERY, 在這裏開始 讀取client 發送來的sql plugin_call(srv, con, con->state); break; case CON_STATE_READ_QUERY: network_socket *recv_sock = con->client; network_mysqld_read(srv, recv_sock); //執行NETWORK_MYSQLD_PLUGIN_PROTO(proxy_read_query), 讀取用戶sql, 設置狀態為CON_STATE_SEND_QUERY plugin_call(srv, con, con->state); break; case CON_STATE_SEND_QUERY: //發送到server network_mysqld_write(srv, con->server); //設置狀態 CON_STATE_READ_QUERY_RESULT break; case CON_STATE_READ_QUERY_RESULT: //讀取server返回數據 network_mysqld_read(srv, recv_sock); //執行NETWORK_MYSQLD_PLUGIN_PROTO(proxy_read_query_result), 設置狀態為CON_STATE_SEND_QUERY_RESULT plugin_call(srv, con, con->state); break; case CON_STATE_SEND_QUERY_RESULT: //先發送給client network_mysqld_write(srv, con->client); //執行NETWORK_MYSQLD_PLUGIN_PROTO(proxy_send_query_result) ////如果st->injected.queries隊列中無數據, 設置狀態為CON_STATE_READ_QUERY, 讀取client 的新sql //否則, 繼續向server發送隊列中的sql plugin_call(srv, con, con->state) break; } }

plugins/proxy/proxy-plugin.c

//初始化
NETWORK_MYSQLD_PLUGIN_PROTO(proxy_init) {
    network_mysqld_con_lua_t *st = con->plugin_con_state;
    st = network_mysqld_con_lua_new();
    con->plugin_con_state = st;
    con->state = CON_STATE_CONNECT_SERVER;
    return NETWORK_SOCKET_SUCCESS;
}

//連接backend, 就是準備些隨機挑戰數,  用於連接real mysql 用
NETWORK_MYSQLD_PLUGIN_PROTO(proxy_connect_server) {
    con->state = CON_STATE_SEND_HANDSHAKE;
}

//讀取client發來的驗證信息
NETWORK_MYSQLD_PLUGIN_PROTO(proxy_read_auth) {
    con->state = CON_STATE_SEND_AUTH_RESULT;
}


NETWORK_MYSQLD_PLUGIN_PROTO(proxy_read_query) {
    network_injection_queue_reset(st->injected.queries);
    sqls = sql_parse(con, tokens);
    for (i = 0; i < sqls->len; ++i) {
        inj = injection_new(id, sqls->pdata[i]);
        inj->resultset_is_needed = TRUE;
        g_queue_push_tail(st->injected.queries, inj);
    }

    inj = g_queue_peek_head(st->injected.queries);
    network_mysqld_queue_reset(send_sock);
    network_mysqld_queue_append(send_sock, send_sock->send_queue, S(inj->query));

    con->state = CON_STATE_SEND_QUERY;
}


NETWORK_MYSQLD_PLUGIN_PROTO(proxy_read_query_result) {
    if (0 != st->injected.queries->length) {
        //在讀取server返回數據時, 彈出st->injected.queries的頭元素
        inj = g_queue_pop_head(st->injected.queries);

        con->state = CON_STATE_READ_QUERY;
    }
}


//如果st->injected.queries隊列中無數據, 設置狀態為CON_STATE_READ_QUERY, 讀取client 的新sql
//否則, 繼續向server發送隊列中的sql
NETWORK_MYSQLD_PLUGIN_PROTO(proxy_send_query_result) {
    if (st->injected.queries->length == 0) {
        con->state = CON_STATE_READ_QUERY;
        return NETWORK_SOCKET_SUCCESS;
    }
    //發送給client後, 將st->injected.queries的頭元素 放到send_queue中
    inj = g_queue_peek_head(st->injected.queries);
    network_mysqld_queue_reset(send_sock);
    network_mysqld_queue_append(send_sock, send_sock->send_queue, S(inj->query));
    con->state = CON_STATE_SEND_QUERY;
    return NETWORK_SOCKET_SUCCESS;
}

network_mysqld_con_lua_t *network_mysqld_con_lua_new() {
    network_mysqld_con_lua_t *st;
    st = g_new0(network_mysqld_con_lua_t, 1);
    st->injected.queries = network_injection_queue_new();
    return st;
}

dbporxy-mysql 協議流轉圖