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 14e4858 commit 44068d7
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 10 deletions.
29 changes: 29 additions & 0 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,11 @@ 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].current_sessions && dst->rmap[l].max_sessions && dst->rmap[l].cpu_idle ) {
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
}
} else {
av = dst->rmap[l].max_load - lb_dlg_binds.get_profile_size(res[k]->profile, &dst->profile_id);
}
Expand Down Expand Up @@ -758,6 +767,7 @@ int lb_route(struct sip_msg *req, int group, struct lb_res_str_list *rl,
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 +828,30 @@ 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->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
15 changes: 11 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,12 @@ struct lb_resource_map {
struct lb_resource *resource;
unsigned int max_load;

unsigned int max_sessions; /* Raw data from HEARTBEART */
unsigned int current_sessions; /* Raw data from HEARTBEART */
unsigned int cpu_idle; /* Raw data from HEARTBEART */

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

int fs_enabled;
};

Expand Down
36 changes: 30 additions & 6 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 @@ -798,12 +810,24 @@ 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;

/*
* 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
*/
if (psz < dst->fs_sock->stats.max_sess) {
if ( flags & LB_FLAGS_PERCENT_WITH_CPU ) {
/*
* In this 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 */
dst->rmap[ri].sessions_since_last_heartbeat = 0;
} else 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 44068d7

Please sign in to comment.