Skip to content

Commit

Permalink
new operational mode - percent with CPU
Browse files Browse the repository at this point in the history
  • Loading branch information
spacetourist committed Mar 28, 2024
1 parent 4b23a80 commit 4575762
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 10 deletions.
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, 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
/*
* 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

0 comments on commit 4575762

Please sign in to comment.