dbporxy-mysql 协议流转图

Posted taek

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了dbporxy-mysql 协议流转图相关的知识,希望对你有一定的参考价值。

 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 协议流转图的主要内容,如果未能解决你的问题,请参考以下文章

基于阿里云物联网平台设计的实时图传系统_采用MQTT协议传输图像

Java 线程状态流转图

Flink 多流转换算子

C/C++ 协议解析通用流转包方法不怕连包

EasyRTSPLive摄像机NVR录像机RTSP协议实时流转RTMP协议直播流推送之搭建EasyRTMPLive拉RTSP流转RTMP测试环境的方法解析

一图胜千言:大数据入门必备的15张数据流转图(建议收藏)