Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ProxyHCTemplate support to mod_lbmethod_cluster #304

Merged
merged 6 commits into from
Dec 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 45 additions & 10 deletions native/balancers/mod_lbmethod_cluster.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
#include "mod_watchdog.h"
#include "common.h"


#define LB_CLUSTER_WATHCHDOG_NAME ("_lb_cluster_")
static ap_watchdog_t *watchdog;

Expand All @@ -16,6 +15,9 @@ static struct context_storage_method *context_storage = NULL;
static struct balancer_storage_method *balancer_storage = NULL;
static struct domain_storage_method *domain_storage = NULL;

static apr_table_t *proxyhctemplate;
static void (*set_proxyhctemplate_f)(apr_pool_t *, apr_table_t *) = NULL;

static int use_alias = 0; /* 1 : Compare Alias with server_name */
static int use_nocanon = 0;
static apr_time_t lbstatus_recalc_time =
Expand Down Expand Up @@ -91,7 +93,9 @@ static proxy_worker *find_best(proxy_balancer *balancer, request_rec *r)
node_table = read_node_table(r->pool, node_storage, 0);
}

node_storage->lock_nodes();
mycandidate = internal_find_best_byrequests(r, balancer, vhost_table, context_table, node_table);
node_storage->unlock_nodes();

return mycandidate;
}
Expand Down Expand Up @@ -319,7 +323,9 @@ static apr_status_t mc_watchdog_callback(int state, void *data, apr_pool_t *pool
}

/* cleanup removed node in shared memory */
node_storage->lock_nodes();
remove_removed_node(s, pool, now, node_table);
node_storage->unlock_nodes();
}
break;

Expand All @@ -339,29 +345,38 @@ static int lbmethod_cluster_post_config(apr_pool_t *p, apr_pool_t *plog, apr_poo

node_storage = ap_lookup_provider("manager", "shared", "0");
if (node_storage == NULL) {
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, "proxy_cluster_post_config: Can't find mod_manager for nodes");
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, "lbmethod_cluster_post_config: Can't find mod_manager for nodes");
return !OK;
}
host_storage = ap_lookup_provider("manager", "shared", "1");
if (host_storage == NULL) {
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, "proxy_cluster_post_config: Can't find mod_manager for hosts");
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, "lbmethod_cluster_post_config: Can't find mod_manager for hosts");
return !OK;
}
context_storage = ap_lookup_provider("manager", "shared", "2");
if (context_storage == NULL) {
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, "proxy_cluster_post_config: Can't find mod_manager for contexts");
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
"lbmethod_cluster_post_config: Can't find mod_manager for contexts");
return !OK;
}
balancer_storage = ap_lookup_provider("manager", "shared", "3");
if (balancer_storage == NULL) {
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, "proxy_cluster_post_config: Can't find mod_manager for balancers");
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
"lbmethod_cluster_post_config: Can't find mod_manager for balancers");
return !OK;
}
domain_storage = ap_lookup_provider("manager", "shared", "5");
if (domain_storage == NULL) {
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, "proxy_cluster_post_config: Can't find mod_manager for domains");
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, "lbmethod_cluster_post_config: Can't find mod_manager for domains");
return !OK;
}
set_proxyhctemplate_f = ap_lookup_provider("manager", "shared", "6");
if (set_proxyhctemplate_f == NULL) {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
"lbmethod_cluster_post_config: Can't find mod_manager for set_proxyhctemplate function");
} else if (!apr_is_empty_table(proxyhctemplate)) {
set_proxyhctemplate_f(p, proxyhctemplate);
}

/* Add version information */
ap_add_version_component(p, MOD_CLUSTER_EXPOSED_VERSION);
Expand All @@ -375,19 +390,19 @@ static int lbmethod_cluster_post_config(apr_pool_t *p, apr_pool_t *plog, apr_poo
mc_watchdog_register_callback = APR_RETRIEVE_OPTIONAL_FN(ap_watchdog_register_callback);
if (!mc_watchdog_get_instance || !mc_watchdog_register_callback) {
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
APLOGNO(03262) "proxy_cluster_post_config: mod_watchdog is required");
APLOGNO(03262) "lbmethod_cluster_post_config: mod_watchdog is required");
return !OK;
}
if (mc_watchdog_get_instance(&watchdog, LB_CLUSTER_WATHCHDOG_NAME, 0, 1, p)) {
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
APLOGNO(03263) "proxy_cluster_post_config: Failed to create watchdog instance (%s)",
APLOGNO(03263) "lbmethod_cluster_post_config: Failed to create watchdog instance (%s)",
LB_CLUSTER_WATHCHDOG_NAME);
return !OK;
}
while (s) {
if (mc_watchdog_register_callback(watchdog, AP_WD_TM_SLICE, s, mc_watchdog_callback)) {
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
APLOGNO(03264) "proxy_cluster_post_config: Failed to register watchdog callback (%s)",
APLOGNO(03264) "lbmethod_cluster_post_config: Failed to register watchdog callback (%s)",
LB_CLUSTER_WATHCHDOG_NAME);
return !OK;
}
Expand All @@ -405,10 +420,30 @@ static const char *cmd_nocanon(cmd_parms *parms, void *mconfig, int on)
return NULL;
}

static const char *cmd_proxyhctemplate(cmd_parms *cmd, void *dummy, const char *arg)
{
const char *err = NULL;
(void)dummy;

if (!proxyhctemplate) {
proxyhctemplate = apr_table_make(cmd->pool, 8);
}

err = parse_proxyhctemplate_params(cmd->pool, arg, proxyhctemplate);
if (err != NULL) {
return err;
}
return NULL;
}

static const command_rec lbmethod_cmds[] = {
AP_INIT_FLAG("UseNocanon", cmd_nocanon, NULL, OR_ALL,
"UseNocanon - When no ProxyPass or ProxyMatch for the URL, passes the URL path \"raw\" to the backend "
"(Default: Off)")};
"(Default: Off)"),
AP_INIT_RAW_ARGS(
"ModProxyClusterHCTemplate", cmd_proxyhctemplate, NULL, OR_ALL,
"ModProxyClusterHCTemplate - Set of health check parameters to use with mod_lbmethod_cluster workers."),
{NULL}};

static void register_hooks(apr_pool_t *p)
{
Expand Down
16 changes: 16 additions & 0 deletions native/common/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -670,3 +670,19 @@ const node_context *context_host_ok(request_rec *r, const proxy_balancer *balanc

return best->node != -1 ? best : NULL;
}

const char *parse_proxyhctemplate_params(apr_pool_t *pool, const char *arg, apr_table_t *params)
{
while (*arg) {
char *key, *val;
key = ap_getword_conf(pool, &arg);
val = strchr(key, '=');
if (!val) {
return "Invalid ProxyHCTemplate parameter. Parameter must be in the form 'key=value'";
}
*val++ = '\0';

apr_table_add(params, key, val);
}
return NULL;
}
6 changes: 6 additions & 0 deletions native/include/balancer.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,4 +143,10 @@ struct balancer_storage_method
*/
int (*get_max_size_balancer)(void);
};

/**
* Helper function for translating hcheck template parameters to corresponding balancer parameters
*/
const char *translate_balancer_params(const char *param);

#endif /*BALANCER_H*/
8 changes: 6 additions & 2 deletions native/include/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
* Common routines
*/


#include "mod_proxy_cluster.h"


Expand All @@ -17,7 +16,6 @@ struct counter
int *values;
};


/**
* Read the virtual host table from shared memory
* @param pool pool to use for memory allocation
Expand Down Expand Up @@ -222,3 +220,9 @@ apr_status_t loc_get_id(void *mem, void *data, apr_pool_t *pool);
const node_context *context_host_ok(request_rec *r, const proxy_balancer *balancer, int node, int use_alias,
const proxy_vhost_table *vhost_table, const proxy_context_table *context_table,
const proxy_node_table *node_table);

/**
* Parse ProxyHCTemplate parameters from @param arg into @param params using @param pool for allocations
* @return error message or NULL if everything went well
*/
const char *parse_proxyhctemplate_params(apr_pool_t *pool, const char *arg, apr_table_t *params);
24 changes: 24 additions & 0 deletions native/mod_manager/balancer.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,3 +174,27 @@ mem_t *create_mem_balancer(char *string, unsigned *num, int persist, apr_pool_t
{
return create_attach_mem_balancer(string, num, persist, 1, p, storage);
}

const char *translate_balancer_params(const char *param)
{
if (strcasecmp(param, "hcinterval") == 0) {
return "w_hi";
}
if (strcasecmp(param, "hcpasses") == 0) {
return "w_hp";
}
if (strcasecmp(param, "hcfails") == 0) {
return "w_hf";
}
if (strcasecmp(param, "hcmethod") == 0) {
return "w_hm";
}
if (strcasecmp(param, "hcuri") == 0) {
return "w_hu";
}
if (strcasecmp(param, "hcexpr") == 0) {
return "w_he";
}

return NULL;
}
36 changes: 32 additions & 4 deletions native/mod_manager/mod_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,13 @@ static mem_t *hoststatsmem = NULL;
static mem_t *balancerstatsmem = NULL;
static mem_t *sessionidstatsmem = NULL;
static mem_t *domainstatsmem = NULL;
/* Used for HCExpr templates with lbmethod_cluster */
static apr_table_t *proxyhctemplate = NULL;

static void set_proxyhctemplate(apr_pool_t *p, apr_table_t *t)
{
proxyhctemplate = apr_table_overlay(p, t, proxyhctemplate);
}

static slotmem_storage_method *storage = NULL;
static balancer_method *balancerhandler = NULL;
Expand Down Expand Up @@ -540,6 +547,7 @@ static int manager_pre_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *p
(void)ptemp;
ap_mutex_register(pconf, node_mutex_type, NULL, APR_LOCK_DEFAULT, 0);
ap_mutex_register(pconf, context_mutex_type, NULL, APR_LOCK_DEFAULT, 0);
proxyhctemplate = apr_table_make(plog, 1);
return OK;
}

Expand Down Expand Up @@ -910,6 +918,11 @@ static int is_same_worker_existing(const request_rec *r, const nodeinfo_t *node)
static apr_status_t mod_manager_manage_worker(request_rec *r, const nodeinfo_t *node, const balancerinfo_t *bal)
{
apr_table_t *params;
apr_status_t rv;
int i;
const apr_array_header_t *h;
const apr_table_entry_t *entries;

params = apr_table_make(r->pool, 10);
/* balancer */
apr_table_set(params, "b", node->mess.balancer);
Expand All @@ -922,7 +935,10 @@ static apr_status_t mod_manager_manage_worker(request_rec *r, const nodeinfo_t *
apr_table_set(params, "b_wyes", "1");
apr_table_set(params, "b_nwrkr",
apr_pstrcat(r->pool, node->mess.Type, "://", node->mess.Host, ":", node->mess.Port, NULL));
balancer_manage(r, params);
rv = balancer_manage(r, params);
if (rv != APR_SUCCESS) {
return rv;
}
apr_table_clear(params);

/* now process the worker */
Expand All @@ -938,6 +954,17 @@ static apr_status_t mod_manager_manage_worker(request_rec *r, const nodeinfo_t *

/* Use 10 sec for the moment, the idea is to adjust it with the STATUS frequency */
apr_table_set(params, "w_hi", "10000");

h = apr_table_elts(proxyhctemplate);
entries = (const apr_table_entry_t *)h->elts;

for (i = 0; i < h->nelts; i++) {
const char *key = translate_balancer_params(entries[i].key);
if (key != NULL) {
apr_table_set(params, key, entries[i].val);
}
}

return balancer_manage(r, params);
}

Expand Down Expand Up @@ -1548,14 +1575,14 @@ static char *process_config(request_rec *r, char **ptr, int *errtype)
/* Insert the Alias and corresponding Context */
phost = vhost;
if (phost->host == NULL && phost->context == NULL) {
loc_unlock_nodes();
/* if using mod_balancer create or update the worker */
if (balancer_manage) {
apr_status_t rv = mod_manager_manage_worker(r, &nodeinfo, &balancerinfo);
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "process_config: balancer-manager returned %d", rv);
} else {
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "process_config: NO balancer-manager");
}
loc_unlock_nodes();
return NULL; /* Alias and Context missing */
}
while (phost) {
Expand All @@ -1570,7 +1597,6 @@ static char *process_config(request_rec *r, char **ptr, int *errtype)
phost = phost->next;
vid++;
}
loc_unlock_nodes();

/* if using mod_balancer create or update the worker */
if (balancer_manage) {
Expand All @@ -1579,6 +1605,7 @@ static char *process_config(request_rec *r, char **ptr, int *errtype)
} else {
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "process_config: NO balancer-manager");
}
loc_unlock_nodes();

ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "process_config: Done");

Expand Down Expand Up @@ -2157,7 +2184,7 @@ static char *process_appl_cmd(request_rec *r, char **ptr, int status, int *errty
if (vhost->host != NULL) {
int start = 0;
i = 0;
while (host == NULL && i + start < strlen(vhost->host)) {
while (host == NULL && (unsigned)(i + start) < strlen(vhost->host)) {
while (vhost->host[start + i] != ',' && vhost->host[start + i] != '\0') {
i++;
}
Expand Down Expand Up @@ -3935,6 +3962,7 @@ static void manager_hooks(apr_pool_t *p)
ap_register_provider(p, "manager", "shared", "3", &balancer_storage);
ap_register_provider(p, "manager", "shared", "4", &sessionid_storage);
ap_register_provider(p, "manager", "shared", "5", &domain_storage);
ap_register_provider(p, "manager", "shared", "6", &set_proxyhctemplate);
}

/*
Expand Down
Loading
Loading