/** * swap the server connection with a connection from * the connection pool * * we can only switch backends if we have a authed connection in the pool. * * @return NULL if swapping failed * the new backend on success */ network_socket *network_connection_pool_lua_swap(network_mysqld_con *con, int backend_ndx, GHashTable *pwd_table) { network_backend_t *backend = NULL; network_socket *send_sock; network_mysqld_con_lua_t *st = con->plugin_con_state; // GString empty_username = { "", 0, 0 }; /* * we can only change to another backend if the backend is already * in the connection pool and connected */ backend = network_backends_get(con->srv->backends, backend_ndx); if (!backend) return NULL; /** * get a connection from the pool which matches our basic requirements * - username has to match * - default_db should match */ #ifdef DEBUG_CONN_POOL g_debug("%s: (swap) check if we have a connection for this user in the pool '%s'", G_STRLOC, con->client->response ? con->client->response->username->str: "empty_user"); #endif int flag = 0; network_connection_pool* pool = chassis_event_thread_pool(backend); if (NULL == (send_sock = network_connection_pool_get(pool))) { /** * no connections in the pool */ flag = 1; if (NULL == (send_sock = self_connect(con, backend, pwd_table))) { st->backend_ndx = -1; return NULL; } } /* the backend is up and cool, take and move the current backend into the pool */ #ifdef DEBUG_CONN_POOL g_debug("%s: (swap) added the previous connection to the pool", G_STRLOC); #endif // network_connection_pool_lua_add_connection(con); /* connect to the new backend */ st->backend = backend; // st->backend->connected_clients++; st->backend_ndx = backend_ndx; if (flag == 0 && !g_atomic_int_compare_and_exchange(&st->backend->connected_clients, 0, 0)) { g_atomic_int_dec_and_test(&st->backend->connected_clients); //g_critical("pool_lua_swap:%08x's connected_clients is %d\n", backend, backend->connected_clients); } return send_sock; }
int backend_load_balance_get(network_mysqld_con* con) { int ret = -1; gint i, load_value, count, flag = 0; double cv, connect_value; network_backend_t* backend; network_connection_pool* pool; if(con->config->max_connections == 0) return ret; network_backends_t* backends = con->srv->priv->backends; count = network_backends_count(backends); load_value = con->config->max_connections; for(i = 0; i < count; i++) { backend = network_backends_get(backends, i); if (backend == NULL) continue; pool = chassis_event_thread_pool(backend); if (pool == NULL) continue; if (backend->type == BACKEND_TYPE_RO && backend->state == BACKEND_STATE_UP && backend->connected_clients >= load_value) { flag = 1; connect_value = backend->connected_clients / (double)backend->weight; break; } } if(flag == 0) return ret; for(i = 0; i < count; i++) { backend = network_backends_get(backends, i); if (backend == NULL) continue; pool = chassis_event_thread_pool(backend); if (pool == NULL) continue; if (backend->type == BACKEND_TYPE_RO && backend->state == BACKEND_STATE_UP) { cv = backend->connected_clients / (double)backend->weight; if(cv <= connect_value) { ret = i; connect_value = cv; } } } return ret; }
/** * swap the server connection with a connection from * the connection pool * * we can only switch backends if we have a authed connection in the pool. * * @return NULL if swapping failed * the new backend on success */ network_socket *network_connection_pool_lua_swap(network_mysqld_con *con, int backend_ndx) { network_backend_t *backend = NULL; network_socket *send_sock; network_mysqld_con_lua_t *st = con->plugin_con_state; chassis_private *g = con->srv->priv; // GString empty_username = { "", 0, 0 }; /* * we can only change to another backend if the backend is already * in the connection pool and connected */ backend = network_backends_get(g->backends, backend_ndx); if (!backend) return NULL; /** * get a connection from the pool which matches our basic requirements * - username has to match * - default_db should match */ #ifdef DEBUG_CONN_POOL g_debug("%s: (swap) check if we have a connection for this user in the pool '%s'", G_STRLOC, con->client->response ? con->client->response->username->str: "empty_user"); #endif network_connection_pool* pool = chassis_event_thread_pool(backend); if (NULL == (send_sock = network_connection_pool_get(pool))) { /** * no connections in the pool */ if (NULL == (send_sock = self_connect(con, backend))) { st->backend_ndx = -1; return NULL; } } /* the backend is up and cool, take and move the current backend into the pool */ #ifdef DEBUG_CONN_POOL g_debug("%s: (swap) added the previous connection to the pool", G_STRLOC); #endif // network_connection_pool_lua_add_connection(con); /* connect to the new backend */ st->backend = backend; // st->backend->connected_clients++; st->backend_ndx = backend_ndx; return send_sock; }
/** * get proxy.global.backends[ndx] * * get the backend from the array of mysql backends. * * @return nil or the backend * @see proxy_backend_get */ static int proxy_backends_get(lua_State *L) { network_backend_t *backend; network_backend_t **backend_p; network_backends_t *bs = *(network_backends_t **)luaL_checkself(L); int backend_ndx = luaL_checkinteger(L, 2) - 1; /** lua is indexes from 1, C from 0 */ /* check that we are in range for a _int_ */ if (NULL == (backend = network_backends_get(bs, backend_ndx))) { lua_pushnil(L); return 1; } backend_p = lua_newuserdata(L, sizeof(backend)); /* the table underneath proxy.global.backends[ndx] */ *backend_p = backend; network_backend_lua_getmetatable(L); lua_setmetatable(L, -2); return 1; }
int idle_rw(network_mysqld_con* con) { int ret = -1; guint i; network_backends_t* backends = con->srv->priv->backends; guint count = network_backends_count(backends); for (i = 0; i < count; ++i) { network_backend_t* backend = network_backends_get(backends, i); if (backend == NULL) continue; network_connection_pool* pool = chassis_event_thread_pool(backend); if (pool == NULL) continue; if (backend->type == BACKEND_TYPE_RW && backend->state == BACKEND_STATE_UP) { ret = i; break; } } return ret; }
int idle_ro(network_mysqld_con* con) { int max_conns = -1; guint i; network_backends_t* backends = con->srv->priv->backends; guint count = network_backends_count(backends); for(i = 0; i < count; ++i) { network_backend_t* backend = network_backends_get(backends, i); if (backend == NULL) continue; network_connection_pool* pool = chassis_event_thread_pool(backend); if (pool == NULL) continue; if (backend->type == BACKEND_TYPE_RO && backend->state == BACKEND_STATE_UP) { if (max_conns == -1 || backend->connected_clients < max_conns) { max_conns = backend->connected_clients; } } } return max_conns; }
int wrr_ro(network_mysqld_con *con) { guint i, j; network_backends_t* backends = con->srv->priv->backends; g_wrr_poll* rwsplit = backends->global_wrr; guint ndx_num = network_backends_count(backends); if (rwsplit->next_ndx >= ndx_num) rwsplit->next_ndx = 0; gint backend_ndx = backend_load_balance_get(con); if(0 < backend_ndx) return backend_ndx; // set max weight if no init if (rwsplit->max_weight == 0) { for(i = 0; i < ndx_num; ++i) { network_backend_t* backend = network_backends_get(backends, i); if (backend == NULL || backend->state != BACKEND_STATE_UP) continue; if (rwsplit->max_weight < backend->weight) { rwsplit->max_weight = backend->weight; rwsplit->cur_weight = backend->weight; } } } guint max_weight = rwsplit->max_weight; gint cur_weight = rwsplit->cur_weight; guint next_ndx = rwsplit->next_ndx; // get backend index by slave wrr gint ndx = -1; for(i = 0; i < ndx_num; ++i) { network_backend_t* backend = network_backends_get(backends, next_ndx); if (backend == NULL) goto next; network_connection_pool* pool = chassis_event_thread_pool(backend); if (pool == NULL) goto next; if (backend->type == BACKEND_TYPE_RO && backend->weight >= cur_weight) { if(backend->state == BACKEND_STATE_UP) { ndx = next_ndx; }else { for(j = 0; j < ndx_num; ++j) { network_backend_t* b = network_backends_get(backends, j); if(b == NULL) continue; network_connection_pool* p = chassis_event_thread_pool(b); if(p == NULL) continue; if(b->type == BACKEND_TYPE_RO && b->state == BACKEND_STATE_UP) ndx = j; } } } next: if (next_ndx >= ndx_num - 1) { --cur_weight; next_ndx = 0; if (cur_weight <= 0) cur_weight = max_weight; } else { ++next_ndx; } if (ndx != -1) break; } rwsplit->cur_weight = cur_weight; rwsplit->next_ndx = next_ndx; return ndx; }
/** * swap the server connection with a connection from * the connection pool * * we can only switch backends if we have a authed connection in the pool. * * @return NULL if swapping failed * the new backend on success */ network_socket* network_connection_pool_lua_swap(network_mysqld_con *con, int backend_ndx, int need_keep_conn, int *err) { network_backend_t *backend = NULL; network_socket *send_sock; network_connection_pool *pool, *second_pool; network_mysqld_con_lua_t *st = con->plugin_con_state; chassis_private *g = con->srv->priv; /* * we can only change to another backend if the backend is already * in the connection pool and connected */ backend = network_backends_get(g->backends, backend_ndx); if (!backend) return NULL; /** * get a connection from the pool which matches our basic requirements * - username has to match * - default_db should match */ #ifdef DEBUG_CONN_POOL g_debug("%s: (swap) check if we have a connection for this user in the pool '%s'", G_STRLOC, con->client->response ? con->client->response->username->str: "empty_user"); #endif if(need_keep_conn == 0) { pool = chassis_event_thread_pool(backend); send_sock = network_connection_pool_get(pool); if(send_sock == NULL) { second_pool = chassis_event_thread_secondpool(backend); send_sock = network_expiretime_connection_pool_get(second_pool, con); } }else { second_pool = chassis_event_thread_secondpool(backend); send_sock = network_connection_secondpool_get(second_pool, con); if(send_sock == NULL) g_message("%s:the connection need keep, but it's not in the pool now.", G_STRLOC); } if (NULL == send_sock ) { /** * no connections in the pool */ if ((con->config->max_connections <= 0) || (backend->connected_clients < con->config->max_connections)) { if (NULL == (send_sock = self_connect(con, backend))) { st->backend_ndx = -1; return NULL; } } else { st->backend_ndx = -1; *err = -1; return NULL; } } /* the backend is up and cool, take and move the current backend into the pool */ #ifdef DEBUG_CONN_POOL g_debug("%s: (swap) added the previous connection to the pool", G_STRLOC); #endif /* connect to the new backend */ st->backend = backend; g_atomic_int_inc(&(st->backend->connected_clients)); st->backend_ndx = backend_ndx; return send_sock; }
/** * 测试zabbix没有启动的情况 * @return */ void test_admin_backend_mange_Add(void) { /** 初始化内存变量*/ network_backend_t *b = NULL; chassis *srv1 = g_new0(chassis, 1); srv1->priv = g_new0(chassis_private, 1); srv1->priv->backends = network_backends_new(); srv1->xml_filename = "test_config.xml"; network_backends_add(srv1->priv->backends, "X.X.X.X:3306#2#UP", BACKEND_TYPE_RW); b = network_backends_get(srv1->priv->backends, 0); g_mutex_init(&(b->mutex[0])); g_mutex_init(&(b->mutex[1])); network_backends_add(srv1->priv->backends, "X.X.X.X:3306#3#UP", BACKEND_TYPE_RO); b = network_backends_get(srv1->priv->backends, 1); g_mutex_init(&(b->mutex[0])); g_mutex_init(&(b->mutex[1])); network_mysqld_con *con = network_mysqld_con_new(); con->client = network_socket_new(); con->srv = srv1; con->srv->detect_threads = g_ptr_array_new(); //network_mysqld_add_connection(srv1, con); gchar *cmd = g_strdup("addBackend --backend=X.X.X.X:3306"); g_assert_cmpint(COMMAND_PROCESS_ERROR, ==, admin_command_process(con, cmd)); g_free(cmd); cmd = NULL; cmd = g_strdup("addBackend"); g_assert_cmpint(COMMAND_PROCESS_ERROR, ==, admin_command_process(con, cmd)); g_free(cmd); cmd = NULL; g_assert(COMMAND_NO_QUERY_SPECIFIED == admin_command_process(con, NULL)); cmd = g_strdup("addBackend --backend=X.X.X.X:3307"); g_assert(COMMAND_PROCESS_ERROR == admin_command_process(con, cmd)); g_free(cmd); cmd = NULL; cmd = g_strdup("addBackend --backend=X.X.X.X:3307#1#up --bktype=rw"); g_assert(COMMAND_PROCESS_ERROR == admin_command_process(con, cmd)); g_free(cmd); cmd = NULL; cmd = g_strdup("addBackend --backend=X.X.X.X:3307 --bktype=ro"); g_assert(COMMAND_PROCESS_SUCCESS == admin_command_process(con, cmd)); network_backend_t *backend = network_backends_get_by_name(srv1->priv->backends, "X.X.X.X:3307"); g_assert(backend); g_free(cmd); cmd = NULL; cmd = g_strdup("addBackend --backend=192.1968.x.xx:3308"); g_assert(COMMAND_PROCESS_ERROR == admin_command_process(con, cmd)); g_free(cmd); cmd = NULL; cmd = g_strdup("addBackend --backends=X.X.X.X:3308"); g_assert(COMMAND_PROCESS_ERROR == admin_command_process(con, cmd)); g_free(cmd); cmd = NULL; cmd = g_strdup("addBackend --backend=X.X.X.X:103307"); g_assert(COMMAND_PROCESS_ERROR == admin_command_process(con, cmd)); g_free(cmd); cmd = NULL; cmd = g_strdup("addBackends --backend=X.X.X.X:3308"); g_assert(COMMAND_NOT_SUPPORT == admin_command_process(con, cmd)); g_free(cmd); cmd = NULL; // g_ptr_array_free(con->srv->detect_threads, TRUE); // con->srv->detect_threads = NULL; //network_mysqld_con_free(con); //con = NULL; //network_backends_free(srv1->priv->backends); //srv1->priv->backends = NULL; //g_free(srv1->priv); //srv1->priv = NULL; //g_free(srv1); //srv1 = NULL; }
void test_adjust_backend(void) { network_backend_t *b = NULL; guint health = 0; network_backends_add(srv1->priv->backends, "192.168.x.x:3306#2#UN", BACKEND_TYPE_RO); network_backends_add(srv1->priv->backends, "192.168.x.x:3306#4#UN", BACKEND_TYPE_RO); network_backends_add(srv1->priv->backends, "192.168.x.x:3306#1#UN", BACKEND_TYPE_RO); b = network_backends_get(srv1->priv->backends, 0); adjust_backend(BACKEND_STATE_UP, srv1, b); g_assert_cmpint(b->state, ==, BACKEND_STATE_UP); health = b->health_check.rise + b->health_check.fall - 1; g_assert_cmpint(b->health_check.health, == , health); g_assert_cmpint(b->type, ==, BACKEND_TYPE_RW); adjust_backend(BACKEND_STATE_DOWN, srv1, b); g_assert_cmpint(b->state, ==, BACKEND_STATE_UP); health--; g_assert_cmpint(b->health_check.health, == , health); g_assert_cmpint(b->type, ==, BACKEND_TYPE_RW); adjust_backend(BACKEND_STATE_UP, srv1, b); g_assert_cmpint(b->state, ==, BACKEND_STATE_UP); health = b->health_check.rise + b->health_check.fall - 1; g_assert_cmpint(b->health_check.health, == , health); g_assert_cmpint(b->type, ==, BACKEND_TYPE_RW); adjust_backend(BACKEND_STATE_DOWN, srv1, b); g_assert_cmpint(b->state, ==, BACKEND_STATE_UP); health--; g_assert_cmpint(b->health_check.health, == , health); g_assert_cmpint(b->type, ==, BACKEND_TYPE_RW); adjust_backend(BACKEND_STATE_DOWN, srv1, b); g_assert_cmpint(b->state, ==, BACKEND_STATE_UP); health--; g_assert_cmpint(b->health_check.health, == , health); g_assert_cmpint(b->type, ==, BACKEND_TYPE_RW); adjust_backend(BACKEND_STATE_DOWN, srv1, b); g_assert_cmpint(b->state, ==, BACKEND_STATE_DOWN); health = 0; g_assert_cmpint(b->health_check.health, == , health); g_assert_cmpint(b->type, ==, BACKEND_TYPE_RO); adjust_backend(BACKEND_STATE_UP, srv1, b); g_assert_cmpint(b->state, ==, BACKEND_STATE_DOWN); health++; g_assert_cmpint(b->health_check.health, == , health); g_assert_cmpint(b->type, ==, BACKEND_TYPE_RO); adjust_backend(BACKEND_STATE_DOWN, srv1, b); g_assert_cmpint(b->state, ==, BACKEND_STATE_DOWN); health = 0; g_assert_cmpint(b->health_check.health, == , health); g_assert_cmpint(b->type, ==, BACKEND_TYPE_RO); adjust_backend(BACKEND_STATE_UP, srv1, b); g_assert_cmpint(b->state, ==, BACKEND_STATE_DOWN); health++; g_assert_cmpint(b->health_check.health, == , health); g_assert_cmpint(b->type, ==, BACKEND_TYPE_RO); adjust_backend(BACKEND_STATE_UP, srv1, b); g_assert_cmpint(b->state, ==, BACKEND_STATE_UP); health = b->health_check.rise + b->health_check.fall - 1; g_assert_cmpint(b->health_check.health, == , health); g_assert_cmpint(b->type, ==, BACKEND_TYPE_RW); network_backends_free(srv1->priv->backends); srv1->priv->backends = NULL; }