MXS-827: Add connection keepalive

The readwritesplit now sends COM_PING queries to backend servers that have
been idle for too long. The option is configured with the
`connection_keepalive` parameter.
This commit is contained in:
Markus Mäkelä
2017-03-24 05:22:25 +02:00
parent e3bae59e1a
commit 710012ac5d
10 changed files with 125 additions and 14 deletions

View File

@ -196,6 +196,7 @@ MXS_MODULE *MXS_CREATE_MODULE()
{"max_sescmd_history", MXS_MODULE_PARAM_COUNT, "0"},
{"strict_multi_stmt", MXS_MODULE_PARAM_BOOL, "true"},
{"master_accept_reads", MXS_MODULE_PARAM_BOOL, "false"},
{"connection_keepalive", MXS_MODULE_PARAM_COUNT, "0"},
{MXS_END_MODULE_PARAMS}
}
};
@ -278,6 +279,7 @@ static MXS_ROUTER *createInstance(SERVICE *service, char **options)
router->rwsplit_config.disable_sescmd_history = config_get_bool(params, "disable_sescmd_history");
router->rwsplit_config.max_sescmd_history = config_get_integer(params, "max_sescmd_history");
router->rwsplit_config.master_accept_reads = config_get_bool(params, "master_accept_reads");
router->rwsplit_config.connection_keepalive = config_get_integer(params, "connection_keepalive");
if (!handle_max_slaves(router, config_get_string(params, "max_slave_connections")) ||
(options && !rwsplit_process_router_options(router, options)))

View File

@ -275,6 +275,8 @@ typedef struct rwsplit_config_st
enum failure_mode master_failure_mode; /**< Master server failure handling mode.
* @see enum failure_mode */
bool retry_failed_reads; /**< Retry failed reads on other servers */
int connection_keepalive; /**< Send pings to servers that have
* been idle for too long */
} rwsplit_config_t;
#if defined(PREP_STMT_CACHING)

View File

@ -19,9 +19,11 @@
#include <stdlib.h>
#include <stdint.h>
#include <maxscale/alloc.h>
#include <maxscale/router.h>
#include <maxscale/modutil.h>
#include "rwsplit_internal.h"
/**
* @file rwsplit_route_stmt.c The functions that support the routing of
* queries to back end servers. All the functions in this module are internal
@ -44,6 +46,35 @@ static backend_ref_t *check_candidate_bref(backend_ref_t *cand,
select_criteria_t sc);
static backend_ref_t *get_root_master_bref(ROUTER_CLIENT_SES *rses);
void handle_connection_keepalive(ROUTER_INSTANCE *inst, ROUTER_CLIENT_SES *rses,
DCB *target_dcb)
{
ss_dassert(target_dcb);
ss_debug(int nserv = 0);
for (int i = 0; i < rses->rses_nbackends; i++)
{
/** Each heartbeat is 1/10th of a second */
int keepalive = inst->rwsplit_config.connection_keepalive * 10;
backend_ref_t *bref = &rses->rses_backend_ref[i];
if (bref->bref_dcb != target_dcb && BREF_IS_IN_USE(bref) &&
!BREF_IS_WAITING_RESULT(bref))
{
ss_debug(nserv++);
int diff = hkheartbeat - bref->bref_dcb->last_read;
if (diff > keepalive)
{
MXS_INFO("Pinging %s, idle for %d seconds",
bref->bref_dcb->server->unique_name, diff / 10);
modutil_ignorable_ping(bref->bref_dcb);
}
}
}
ss_dassert(nserv < rses->rses_nbackends);
}
/**
* Routing function. Find out query type, backend type, and target DCB(s).
* Then route query to found target(s).
@ -148,6 +179,12 @@ bool route_single_stmt(ROUTER_INSTANCE *inst, ROUTER_CLIENT_SES *rses,
}
}
if (succp && inst->rwsplit_config.connection_keepalive &&
(TARGET_IS_SLAVE(route_target) || TARGET_IS_MASTER(route_target)))
{
handle_connection_keepalive(inst, rses, target_dcb);
}
return succp;
} /* route_single_stmt */