mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-10 09:07:02 +02:00
MEDIUM: checks: Implement redis check using tcp-check rules
A share tcp-check ruleset is now created to support redis checks. This way no extra memory is used if several backends use a redis check. The following sequence is used : tcp-check send "*1\r\n$4\r\nPING\r\n" tcp-check expect string "+PONG\r\n" error-status "L7STS" \ on-error "%[check.payload(),cut_crlf]" on-success "Redis server is ok"
This commit is contained in:
parent
9e6ed1598e
commit
33f05df650
@ -179,7 +179,7 @@
|
||||
#define DEF_CHECK_PATH ""
|
||||
#define DEF_SMTP_CHECK_REQ "HELO localhost\r\n"
|
||||
#define DEF_LDAP_CHECK_REQ "\x30\x0c\x02\x01\x01\x60\x07\x02\x01\x03\x04\x00\x80\x00"
|
||||
#define DEF_REDIS_CHECK_REQ "*1\r\n$4\r\nPING\r\n"
|
||||
|
||||
|
||||
#define DEF_HANA_ONERR HANA_ONERR_FAILCHK
|
||||
#define DEF_HANA_ERRLIMIT 10
|
||||
|
@ -69,6 +69,8 @@ int dup_tcpcheck_vars(struct list *dst, struct list *src);
|
||||
int spoe_prepare_healthcheck_request(char **req, int *len);
|
||||
int spoe_handle_healthcheck_response(char *frame, size_t size, char *err, int errlen);
|
||||
|
||||
int proxy_parse_redis_check_opt(char **args, int cur_arg, struct proxy *curpx, struct proxy *defpx,
|
||||
const char *file, int line);
|
||||
#endif /* _PROTO_CHECKS_H */
|
||||
|
||||
/*
|
||||
|
@ -308,9 +308,11 @@ struct tcpcheck_rule {
|
||||
};
|
||||
};
|
||||
|
||||
#define TCPCHK_RULES_NONE 0x00000000
|
||||
#define TCPCHK_RULES_SHARED 0x00000001 /* Set for shared list of tcp-check rules */
|
||||
#define TCPCHK_RULES_DEF 0x00000002 /* Ruleset inherited from the default section */
|
||||
#define TCPCHK_RULES_NONE 0x00000000
|
||||
#define TCPCHK_RULES_SHARED 0x00000001 /* Set for shared list of tcp-check rules */
|
||||
#define TCPCHK_RULES_DEF 0x00000002 /* Ruleset inherited from the default section */
|
||||
|
||||
#define TCPCHK_RULES_REDIS_CHK 0x00000020
|
||||
|
||||
/* A list of tcp-check vars, to be registered before executing a ruleset */
|
||||
struct tcpcheck_var {
|
||||
|
@ -170,7 +170,7 @@ enum PR_SRV_STATE_FILE {
|
||||
/* server health checks */
|
||||
#define PR_O2_CHK_NONE 0x00000000 /* no L7 health checks configured (TCP by default) */
|
||||
#define PR_O2_PGSQL_CHK 0x10000000 /* use PGSQL check for server health */
|
||||
#define PR_O2_REDIS_CHK 0x20000000 /* use LDAP check for server health */
|
||||
/* unused: 0x20000000 */
|
||||
#define PR_O2_SMTP_CHK 0x30000000 /* use SMTP EHLO check for server health - pvandijk@vision6.com.au */
|
||||
#define PR_O2_HTTP_CHK 0x40000000 /* use HTTP 'OPTIONS' method to check server health */
|
||||
#define PR_O2_MYSQL_CHK 0x50000000 /* use MYSQL check for server health */
|
||||
|
@ -2495,22 +2495,9 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
|
||||
if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
|
||||
goto out;
|
||||
}
|
||||
|
||||
else if (!strcmp(args[1], "redis-check")) {
|
||||
/* use REDIS PING request to check servers' health */
|
||||
if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
|
||||
err_code |= ERR_WARN;
|
||||
|
||||
free(curproxy->check_req);
|
||||
curproxy->check_req = NULL;
|
||||
curproxy->options2 &= ~PR_O2_CHK_ANY;
|
||||
curproxy->options2 |= PR_O2_REDIS_CHK;
|
||||
|
||||
curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
|
||||
memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
|
||||
curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
|
||||
|
||||
if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
|
||||
err_code |= proxy_parse_redis_check_opt(args, 0, curproxy, &defproxy, file, linenum);
|
||||
if (err_code & ERR_FATAL)
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
141
src/checks.c
141
src/checks.c
@ -1222,18 +1222,6 @@ static void __event_srv_chk_r(struct conn_stream *cs)
|
||||
}
|
||||
break;
|
||||
|
||||
case PR_O2_REDIS_CHK:
|
||||
if (!done && b_data(&check->bi) < 7)
|
||||
goto wait_more_data;
|
||||
|
||||
if (strcmp(b_head(&check->bi), "+PONG\r\n") == 0) {
|
||||
set_server_check_status(check, HCHK_STATUS_L7OKD, "Redis server is ok");
|
||||
}
|
||||
else {
|
||||
set_server_check_status(check, HCHK_STATUS_L7STS, b_head(&check->bi));
|
||||
}
|
||||
break;
|
||||
|
||||
case PR_O2_MYSQL_CHK:
|
||||
if (!done && b_data(&check->bi) < 5)
|
||||
goto wait_more_data;
|
||||
@ -5077,6 +5065,135 @@ static int proxy_parse_tcpcheck(char **args, int section, struct proxy *curpx,
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static struct tcpcheck_ruleset *tcpcheck_ruleset_lookup(const char *name)
|
||||
{
|
||||
struct tcpcheck_ruleset *rs;
|
||||
|
||||
list_for_each_entry(rs, &tcpchecks_list, list) {
|
||||
if (strcmp(rs->name, name) == 0)
|
||||
return rs;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct tcpcheck_ruleset *tcpcheck_ruleset_create(const char *name)
|
||||
{
|
||||
struct tcpcheck_ruleset *rs;
|
||||
|
||||
rs = calloc(1, sizeof(*rs));
|
||||
if (rs == NULL)
|
||||
return NULL;
|
||||
|
||||
rs->name = strdup(name);
|
||||
if (rs->name == NULL) {
|
||||
free(rs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LIST_INIT(&rs->list);
|
||||
LIST_INIT(&rs->rules);
|
||||
LIST_ADDQ(&tcpchecks_list, &rs->list);
|
||||
return rs;
|
||||
}
|
||||
|
||||
static void tcpcheck_ruleset_release(struct tcpcheck_ruleset *rs)
|
||||
{
|
||||
struct tcpcheck_rule *r, *rb;
|
||||
if (!rs)
|
||||
return;
|
||||
|
||||
LIST_DEL(&rs->list);
|
||||
list_for_each_entry_safe(r, rb, &rs->rules, list) {
|
||||
LIST_DEL(&r->list);
|
||||
free_tcpcheck(r, 0);
|
||||
}
|
||||
free(rs->name);
|
||||
free(rs);
|
||||
}
|
||||
|
||||
|
||||
/* Parses the "option redis-check" proxy keyword */
|
||||
int proxy_parse_redis_check_opt(char **args, int cur_arg, struct proxy *curpx, struct proxy *defpx,
|
||||
const char *file, int line)
|
||||
{
|
||||
static char *redis_req = "*1\r\n$4\r\nPING\r\n";
|
||||
static char *redis_res = "+PONG\r\n";
|
||||
|
||||
struct tcpcheck_ruleset *rs = NULL;
|
||||
struct tcpcheck_rules *rules = &curpx->tcpcheck_rules;
|
||||
struct tcpcheck_rule *chk;
|
||||
char *errmsg = NULL;
|
||||
int err_code = 0;
|
||||
|
||||
if (warnifnotcap(curpx, PR_CAP_BE, file, line, args[cur_arg+1], NULL))
|
||||
err_code |= ERR_WARN;
|
||||
|
||||
if (alertif_too_many_args_idx(0, 1, file, line, args, &err_code))
|
||||
goto out;
|
||||
|
||||
if (rules->list && !(rules->flags & TCPCHK_RULES_SHARED)) {
|
||||
ha_alert("parsing [%s:%d] : A custom tcp-check ruleset is already configured.\n",
|
||||
file, line);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
curpx->options2 &= ~PR_O2_CHK_ANY;
|
||||
curpx->options2 |= PR_O2_TCPCHK_CHK;
|
||||
|
||||
free_tcpcheck_vars(&rules->preset_vars);
|
||||
rules->list = NULL;
|
||||
rules->flags = 0;
|
||||
|
||||
rs = tcpcheck_ruleset_lookup("*redis-check");
|
||||
if (rs)
|
||||
goto ruleset_found;
|
||||
|
||||
rs = tcpcheck_ruleset_create("*redis-check");
|
||||
if (rs == NULL) {
|
||||
ha_alert("parsing [%s:%d] : out of memory.\n", file, line);
|
||||
goto error;
|
||||
}
|
||||
|
||||
chk = parse_tcpcheck_send((char *[]){"tcp-check", "send", redis_req, ""},
|
||||
1, curpx, &rs->rules, file, line, &errmsg);
|
||||
if (!chk) {
|
||||
ha_alert("parsing [%s:%d] : %s\n", file, line, errmsg);
|
||||
goto error;
|
||||
}
|
||||
chk->index = 0;
|
||||
LIST_ADDQ(&rs->rules, &chk->list);
|
||||
|
||||
chk = parse_tcpcheck_expect((char *[]){"tcp-check", "expect", "string", redis_res,
|
||||
"error-status", "L7STS",
|
||||
"on-error", "%[check.payload(),cut_crlf]",
|
||||
"on-success", "Redis server is ok",
|
||||
""},
|
||||
1, curpx, &rs->rules, file, line, &errmsg);
|
||||
if (!chk) {
|
||||
ha_alert("parsing [%s:%d] : %s\n", file, line, errmsg);
|
||||
goto error;
|
||||
}
|
||||
chk->index = 1;
|
||||
LIST_ADDQ(&rs->rules, &chk->list);
|
||||
|
||||
LIST_ADDQ(&tcpchecks_list, &rs->list);
|
||||
|
||||
ruleset_found:
|
||||
rules->list = &rs->rules;
|
||||
rules->flags |= (TCPCHK_RULES_SHARED|TCPCHK_RULES_REDIS_CHK);
|
||||
|
||||
out:
|
||||
free(errmsg);
|
||||
return err_code;
|
||||
|
||||
error:
|
||||
tcpcheck_ruleset_release(rs);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
static struct cfg_kw_list cfg_kws = {ILH, {
|
||||
{ CFG_LISTEN, "tcp-check", proxy_parse_tcpcheck },
|
||||
{ 0, NULL, NULL },
|
||||
|
Loading…
Reference in New Issue
Block a user