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

new operational mode - percent with CPU #3351

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 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
33 changes: 30 additions & 3 deletions modules/load_balancer/lb_data.c
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,10 @@ int add_lb_dsturi( struct lb_data *data, int id, int group, char *uri,
fs_url = r->fs_url;
dst->rmap[i].max_load = initial_fs_load;
dst->rmap[i].fs_enabled = 1;

dst->rmap[i].current_sessions = 0;
dst->rmap[i].max_sessions = 0;
dst->rmap[i].cpu_idle = 100;
} else {
dst->rmap[i].max_load = r->val;
}
Expand Down Expand Up @@ -424,6 +428,12 @@ static int get_dst_load(struct lb_resource **res, unsigned int res_no,
if( flags & LB_FLAGS_RELATIVE ) {
if( dst->rmap[l].max_load )
av = 100 - (100 * lb_dlg_binds.get_profile_size(res[k]->profile, &dst->profile_id) / dst->rmap[l].max_load);
} else if( flags & LB_FLAGS_PERCENT_WITH_CPU ) {
/* generate score based on the percentage of channels occupied, reduced by CPU idle factor */
if( dst->rmap[l].max_sessions ) {
av = ( 100 - ( 100 * ( dst->rmap[l].current_sessions + dst->rmap[l].sessions_since_last_heartbeat ) / dst->rmap[l].max_sessions ) ) * dst->rmap[l].cpu_idle;
LM_DBG("destination %d <%.*s> availability score %d (sessions=%d since_last_hb=%d max_sess=%d cpu_idle=%.2f)", dst->id, dst->uri.len, dst->uri.s, av, dst->rmap[l].current_sessions, dst->rmap[l].sessions_since_last_heartbeat, dst->rmap[l].max_sessions, dst->rmap[l].cpu_idle);
}
} else {
av = dst->rmap[l].max_load - lb_dlg_binds.get_profile_size(res[k]->profile, &dst->profile_id);
}
Expand Down Expand Up @@ -490,7 +500,7 @@ int lb_route(struct sip_msg *req, int group, struct lb_res_str_list *rl,
struct lb_resource *it_r;
int load, it_l;
int i, j, cond, cnt_aval_dst;

unsigned int k, l;

/* init control vars state */
res_cur = NULL;
Expand Down Expand Up @@ -756,8 +766,7 @@ int lb_route(struct sip_msg *req, int group, struct lb_res_str_list *rl,
cnt_aval_dst = 0;
for( it_d=data->dsts,i=0,j=0 ; it_d ; it_d=it_d->next ) {
if( it_d->group == group ) {
if( (dst_bitmap_cur[i] & (1 << j)) &&
((it_d->flags & LB_DST_STAT_DSBL_FLAG) == 0) ) {
if( (dst_bitmap_cur[i] & (1 << j)) && ((it_d->flags & LB_DST_STAT_DSBL_FLAG) == 0) ) {
/* valid destination (group & resources & status) */
cnt_aval_dst++;
if( get_dst_load(res_cur, res_cur_n, it_d, flags, &it_l) ) {
Expand Down Expand Up @@ -818,11 +827,29 @@ int lb_route(struct sip_msg *req, int group, struct lb_res_str_list *rl,


if( dst != NULL ) {

LM_DBG("%s call of LB - winning destination %d <%.*s> selected "
"for LB set with free=%d\n",
(reuse ? "sequential" : "initial"),
dst->id, dst->uri.len, dst->uri.s, load );

if ( flags & LB_FLAGS_PERCENT_WITH_CPU ) {

// find all resources used by this call, increment on each
for( k=0 ; k<res_cur_n ; k++ ) {
for (l=0 ; l<dst->rmap_no ; l++ ) {
if( res_cur[k] == dst->rmap[l].resource ) {
dst->rmap[l].sessions_since_last_heartbeat++;

LM_DBG("incrementing sess since last HB for winning destination %d <%.*s> (sessions_since_last_heartbeat=%d)\n",
dst->id, dst->uri.len, dst->uri.s, dst->rmap[l].sessions_since_last_heartbeat );

break; // exit the loop
}
}
}
}

/* add to the profiles */
for( i=0 ; i<res_cur_n ; i++ ) {
if( lb_dlg_binds.set_profile(dlg, &dst->profile_id,
Expand Down
17 changes: 13 additions & 4 deletions modules/load_balancer/lb_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@
#include "../freeswitch/fs_api.h"
#include "lb_parser.h"

#define LB_FLAGS_RELATIVE (1<<0) /* do relative versus absolute estimation. default is absolute */
#define LB_FLAGS_NEGATIVE (1<<1) /* do not skip negative loads. default to skip */
#define LB_FLAGS_RANDOM (1<<2) /* pick a random destination among all selected dsts with equal load */
#define LB_FLAGS_DEFAULT 0
#define LB_FLAGS_RELATIVE (1<<0) /* do relative versus absolute estimation. default is absolute */
#define LB_FLAGS_NEGATIVE (1<<1) /* do not skip negative loads. default to skip */
#define LB_FLAGS_RANDOM (1<<2) /* pick a random destination among all selected dsts with equal load */
#define LB_FLAGS_PERCENT_WITH_CPU (1<<3) /* score as percentage of max sessions used + CPU util factor */
#define LB_FLAGS_DEFAULT 0

#define LB_DST_PING_DSBL_FLAG (1<<0)
#define LB_DST_PING_PERM_FLAG (1<<1)
Expand All @@ -62,6 +63,14 @@ struct lb_resource_map {
struct lb_resource *resource;
unsigned int max_load;

/* data received in last heartbeat */
unsigned int max_sessions;
unsigned int current_sessions;
float cpu_idle;

/* count of sessions allocated since last FS heartbeat */
unsigned int sessions_since_last_heartbeat;

int fs_enabled;
};

Expand Down
34 changes: 31 additions & 3 deletions modules/load_balancer/load_balancer.c
Original file line number Diff line number Diff line change
Expand Up @@ -556,9 +556,21 @@ static int w_lb_start(struct sip_msg *req, int *grp_no,
for( f=flstr->s ; f<flstr->s+flstr->len ; f++ ) {
switch( *f ) {
case 'r':
if( flags & LB_FLAGS_PERCENT_WITH_CPU ) {
LM_ERR("flags c & r are mutually exclusive (r)\n");
return -5;
}
flags |= LB_FLAGS_RELATIVE;
LM_DBG("using relative versus absolute estimation\n");
break;
case 'c':
if( flags & LB_FLAGS_RELATIVE ) {
LM_ERR("flags c & r are mutually exclusive (c)\n");
return -5;
}
flags |= LB_FLAGS_PERCENT_WITH_CPU;
LM_DBG("using percentage of max sessions with CPU factor estimation \n");
break;
case 'n':
flags |= LB_FLAGS_NEGATIVE;
LM_DBG("do not skip negative loads\n");
Expand Down Expand Up @@ -795,12 +807,28 @@ static void lb_update_max_loads(unsigned int ticks, void *param)
dst->rmap[ri].resource->profile, &dst->profile_id);
old = dst->rmap[ri].max_load;

// if ( flags & LB_FLAGS_PERCENT_WITH_CPU ) { todo flags not avavilable here
/*
spacetourist marked this conversation as resolved.
Show resolved Hide resolved
* The normal case. OpenSIPS sees, at _most_, the same number
* of sessions as FreeSWITCH does. Any differences must be
* subtracted from the remote "max sessions" value
* In LB_FLAGS_PERCENT_WITH_CPU mode we capture the raw values and use these in each LB calculation. This
* means we do not use profile counting in the load calculation. This is suitable for
* architectures where many unreplicated OpenSIPs instances feed calls into the same pool
* of FreeSWITCH instances.
*/
dst->rmap[ri].max_sessions = dst->fs_sock->stats.max_sess;
dst->rmap[ri].current_sessions = dst->fs_sock->stats.sess;
dst->rmap[ri].cpu_idle = dst->fs_sock->stats.id_cpu / (float)100;
/*
* reset sessions since last heartbeat counter
* todo ideally this happens when the heartbeat arrives, this fires according to fetch_freeswitch_stats timer
*/
dst->rmap[ri].sessions_since_last_heartbeat = 0;

if (psz < dst->fs_sock->stats.max_sess) {
/*
* The normal case. OpenSIPS sees, at _most_, the same number
* of sessions as FreeSWITCH does. Any differences must be
* subtracted from the remote "max sessions" value
*/
dst->rmap[ri].max_load =
(dst->fs_sock->stats.id_cpu / (float)100) *
(dst->fs_sock->stats.max_sess -
Expand Down
Loading