MINOR: stream: Stickiness server lookup by name.

With this patch we modify the stickiness server targets lookup behavior.
First we look for this server targets by their names before looking for them by their
IDs if not found. We also insert a dictionary entry for the name of the server targets
and store the address of this entry in the underlying stick-table.
This commit is contained in:
Frdric Lcaille 2019-05-20 10:08:27 +02:00 committed by Willy Tarreau
parent 7da71293e4
commit 03cdf55e69
1 changed files with 56 additions and 21 deletions

View File

@ -39,6 +39,7 @@
#include <proto/checks.h>
#include <proto/cli.h>
#include <proto/connection.h>
#include <proto/dict.h>
#include <proto/dns.h>
#include <proto/stats.h>
#include <proto/fd.h>
@ -1483,6 +1484,49 @@ static int process_server_rules(struct stream *s, struct channel *req, int an_bi
return 1;
}
static inline void sticking_rule_find_target(struct stream *s,
struct stktable *t, struct stksess *ts)
{
struct proxy *px = s->be;
struct eb32_node *node;
struct dict_entry *de;
void *ptr;
struct server *srv;
/* Look for the server name previously stored in <t> stick-table */
HA_RWLOCK_RDLOCK(STK_SESS_LOCK, &ts->lock);
ptr = __stktable_data_ptr(t, ts, STKTABLE_DT_SERVER_NAME);
de = stktable_data_cast(ptr, server_name);
HA_RWLOCK_RDUNLOCK(STK_SESS_LOCK, &ts->lock);
if (de) {
struct ebpt_node *name;
name = ebis_lookup(&px->conf.used_server_name, de->value.key);
if (name) {
srv = container_of(name, struct server, conf.name);
goto found;
}
}
/* Look for the server ID */
HA_RWLOCK_RDLOCK(STK_SESS_LOCK, &ts->lock);
ptr = __stktable_data_ptr(t, ts, STKTABLE_DT_SERVER_ID);
node = eb32_lookup(&px->conf.used_server_id, stktable_data_cast(ptr, server_id));
HA_RWLOCK_RDUNLOCK(STK_SESS_LOCK, &ts->lock);
if (!node)
return;
srv = container_of(node, struct server, conf.id);
found:
if ((srv->cur_state != SRV_ST_STOPPED) ||
(px->options & PR_O_PERSIST) || (s->flags & SF_FORCE_PRST)) {
s->flags |= SF_DIRECT | SF_ASSIGNED;
s->target = &srv->obj_type;
}
}
/* This stream analyser works on a request. It applies all sticking rules on
* it then returns 1. The data must already be present in the buffer otherwise
* they won't match. It always returns 1.
@ -1539,27 +1583,8 @@ static int process_sticking_rules(struct stream *s, struct channel *req, int an_
struct stksess *ts;
if ((ts = stktable_lookup_key(rule->table.t, key)) != NULL) {
if (!(s->flags & SF_ASSIGNED)) {
struct eb32_node *node;
void *ptr;
/* srv found in table */
HA_RWLOCK_RDLOCK(STK_SESS_LOCK, &ts->lock);
ptr = __stktable_data_ptr(rule->table.t, ts, STKTABLE_DT_SERVER_ID);
node = eb32_lookup(&px->conf.used_server_id, stktable_data_cast(ptr, server_id));
HA_RWLOCK_RDUNLOCK(STK_SESS_LOCK, &ts->lock);
if (node) {
struct server *srv;
srv = container_of(node, struct server, conf.id);
if ((srv->cur_state != SRV_ST_STOPPED) ||
(px->options & PR_O_PERSIST) ||
(s->flags & SF_FORCE_PRST)) {
s->flags |= SF_DIRECT | SF_ASSIGNED;
s->target = &srv->obj_type;
}
}
}
if (!(s->flags & SF_ASSIGNED))
sticking_rule_find_target(s, rule->table.t, ts);
stktable_touch_local(rule->table.t, ts, 1);
}
}
@ -1657,6 +1682,7 @@ static int process_store_rules(struct stream *s, struct channel *rep, int an_bit
for (i = 0; i < s->store_count; i++) {
struct stksess *ts;
void *ptr;
struct dict_entry *de;
if (objt_server(s->target) && objt_server(s->target)->flags & SRV_F_NON_STICK) {
stksess_free(s->store[i].table, s->store[i].ts);
@ -1675,6 +1701,15 @@ static int process_store_rules(struct stream *s, struct channel *rep, int an_bit
ptr = __stktable_data_ptr(s->store[i].table, ts, STKTABLE_DT_SERVER_ID);
stktable_data_cast(ptr, server_id) = __objt_server(s->target)->puid;
HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock);
HA_RWLOCK_WRLOCK(STK_SESS_LOCK, &ts->lock);
de = dict_insert(&server_name_dict, __objt_server(s->target)->id);
if (de) {
ptr = __stktable_data_ptr(s->store[i].table, ts, STKTABLE_DT_SERVER_NAME);
stktable_data_cast(ptr, server_name) = de;
}
HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock);
stktable_touch_local(s->store[i].table, ts, 1);
}
s->store_count = 0; /* everything is stored */