Navigation


Changeset 1390:46656b52ae97 in freeDiameter for extensions


Ignore:
Timestamp:
Nov 15, 2019, 7:21:41 PM (4 years ago)
Author:
Thomas Klausner <tk@giga.or.at>
Branch:
default
Phase:
public
Message:

rt_load_balance: improve algorithm

The extension now looks at the candidates with the highest
score. Among those it increases the score for all of them with
the lowest load by +1. Then it randomly gives one of them another
+1 boost.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • extensions/rt_load_balance/rt_load_balance.c

    r1284 r1390  
    3131
    3232#include <freeDiameter/extension.h>
     33#include <limits.h>
     34#include <time.h>
     35
     36struct best_candidate_entry {
     37    long load;
     38    struct rtd_candidate *cand;
     39};
     40
     41static unsigned int seed;
     42
     43#define MODULE_NAME "rt_load_balance"
    3344
    3445/*
    35  * Load balancing extension. Send request to least-loaded node.
     46 * Load balancing extension. Send request to least-loaded node: Add a
     47 * score of 1 to the least loaded candidates among those with highest
     48 * score.
    3649 */
    3750
     
    4154        struct fd_list *lic;
    4255        struct msg * msg = *pmsg;
    43        
     56        int max_score = -1;
     57        int max_score_count = 0;
     58
    4459        TRACE_ENTRY("%p %p %p", cbdata, msg, candidates);
    45        
     60
    4661        CHECK_PARAMS(msg && candidates);
    47        
     62
     63
    4864        /* Check if it is worth processing the message */
    4965        if (FD_IS_LIST_EMPTY(candidates))
    5066                return 0;
    5167
    52         /* load balancing */
     68        /* find out maximal score and how many candidates have it */
    5369        for (lic = candidates->next; lic != candidates; lic = lic->next) {
    5470                struct rtd_candidate * cand = (struct rtd_candidate *) lic;
    55                 struct peer_hdr *peer;
    56                 long to_receive, to_send, load;
    57                 int score;
    58                 CHECK_FCT(fd_peer_getbyid(cand->diamid, cand->diamidlen, 0, &peer));
    59                 CHECK_FCT(fd_peer_get_load_pending(peer, &to_receive, &to_send));
    60                 load = to_receive + to_send;
    61                 /* other routing mechanisms need to add to the
    62                  * appropriate entries so their base value is high
    63                  * enough that they are considered */
     71                if (max_score < cand->score) {
     72                        max_score = cand->score;
     73                        max_score_count = 1;
     74                }
     75                else if (cand->score == max_score) {
     76                        max_score_count++;
     77                }
     78        }
    6479
    65                 /* logarithmic scaling */
    66                 int load_log = 0;
    67                 while (load > 0) {
    68                     load_log++;
    69                     load /= 2;
    70                 }
    71                 score = cand->score;
    72                 cand->score -= load_log;
    73                 TRACE_DEBUG(FULL, "evaluated peer `%.*s', score was %d, now %d", (int)cand->diamidlen, cand->diamid, score, cand->score);
     80        if (max_score_count > 0) {
     81                /* find out minimum load among those with maximal
     82                 * score, and how many candidates have it */
     83                struct best_candidate_entry best_candidates[max_score_count];
     84                long min_load = LONG_MAX;
     85                int min_load_count = 0;
     86                int j;
     87
     88                for (j = 0, lic = candidates->next; lic != candidates; lic = lic->next) {
     89                        struct rtd_candidate * cand = (struct rtd_candidate *) lic;
     90                        if (cand->score == max_score) {
     91                                long to_receive, to_send, load;
     92                                struct peer_hdr *peer;
     93                                CHECK_FCT(fd_peer_getbyid(cand->diamid, cand->diamidlen, 0, &peer));
     94                                CHECK_FCT(fd_peer_get_load_pending(peer, &to_receive, &to_send));
     95                                load = to_receive + to_send;
     96
     97                                best_candidates[j].cand = cand;
     98                                best_candidates[j].load = load;
     99                                j++;
     100
     101                                if (min_load > load) {
     102                                        min_load = load;
     103                                        min_load_count = 1;
     104                                } else if (min_load == load) {
     105                                        min_load_count++;
     106                                }
     107                        }
     108                }
     109
     110                /* increase score by 1 for all entries with minimum
     111                 * load, and further increase by 1 for one randomly
     112                 * chosen candidate */
     113                if (min_load_count > 0) {
     114                        int lucky_candidate = rand_r(&seed) % min_load_count;
     115                        int i;
     116                        for (j = 0, i = 0; j < max_score_count; j++) {
     117                                struct best_candidate_entry *entry = best_candidates+j;
     118                                if (entry->load == min_load) {
     119                                        struct rtd_candidate *cand = entry->cand;
     120                                        long old_score = cand->score;
     121                                        cand->score++;
     122                                        TRACE_DEBUG(FULL, "%s: boosting peer `%.*s', score was %d, now %d; load was %ld", MODULE_NAME, (int)cand->diamidlen, cand->diamid, old_score, cand->score, entry->load);
     123
     124                                        if (i == lucky_candidate) {
     125                                                cand->score++;
     126                                                TRACE_DEBUG(FULL, "%s: boosting lucky peer `%.*s', score was %d, now %d; load was %ld", MODULE_NAME, (int)cand->diamidlen, cand->diamid, old_score, cand->score, entry->load);
     127                                        }
     128                                        i++;
     129                                }
     130                        }
     131                }
    74132        }
    75133
     
    86144        CHECK_FCT(fd_rt_out_register(rt_load_balancing, NULL, 10, &rt_load_balancing_hdl));
    87145
     146        seed = (unsigned int)time(NULL);
     147
    88148        TRACE_DEBUG(INFO, "Extension 'Load Balancing' initialized");
    89149        return 0;
     
    98158}
    99159
    100 EXTENSION_ENTRY("rt_load_balance", rt_load_balance_entry);
     160EXTENSION_ENTRY(MODULE_NAME, rt_load_balance_entry);
Note: See TracChangeset for help on using the changeset viewer.