#
# client-balance - the home server is chosen by hashing the
# source IP address of the packet. If that home server
- # is down, the next one in the list is used, just as
- # with "fail-over".
+ # is down, then "load-balance" method is used.
#
# There is no way of predicting which source IP will map
# to which home server.
#
# client-port-balance - the home server is chosen by hashing
# the source IP address and source port of the packet.
- # If that home server is down, the next one in the list
- # is used, just as with "fail-over".
+ # If that home server is down, then "load-balance"
+ # method is used.
#
# This method provides slightly better load balancing
# for EAP sessions than "client-balance". However, it
# server = (hash % num_servers_in_pool).
#
# If there is no Load-Balance-Key in the control items,
- # the load balancing method is identical to "load-balance".
+ # or if the chosen server is down, then the
+ # "load-balance" method is used.
#
# For most non-EAP authentication methods, The User-Name
# attribute provides a good key. An "unlang" policy can
# be used to copy the User-Name to the Load-Balance-Key
# attribute. This method may not work for EAP sessions,
# as the User-Name outside of the TLS tunnel is often
- # static, e.g. "anonymous@realm".
- #
+ # static, e.g. "anonymous@realm". In that case, the key
+ # should include both the User-Name, and the
+ # Calling-Station-Id, which helps to make the hash more
+ # evenly distributed.
+ #
+ # consistent-keyed-balance - the server uses consistent
+ # hashing to pick a home server. If all home servers
+ # are up, then this method is equivalent to
+ # keyed-balance.
+ #
+ # If the first chosen home server is down, then a new
+ # home server is chosen using consistent hashing. The
+ # "consistent" portion means that the same key will map
+ # to the same "second chosen" home server. If that
+ # server is down the same key will map to the same
+ # "third chosen" home server, etc.
+
+ # This method is most useful for EAP, where all packets
+ # for the same authentication session should take the
+ # same route through a proxy fabric. In the event of a
+ # failure of one home server, all packets for one EAP
+ # session will still be routed through the same home
+ # server.
#
# The default type is fail-over.
type = fail-over
* situation.
*
* @todo - if there's only one server alive, just pick that?
+ *
+ * @todo - move to a home_server_id_t structure, which contains a
+ * home_server_t* and a uin32_t id. We can then allocate 8-16
+ * IDs per home server, which will help with load balancing. If
+ * each home server has only one ID, there is a chance that two
+ * will be randomly assigned right next to each other. That
+ * results in bad load balancing.
*/
static home_server_t *home_server_by_consistent_key(REQUEST *request, home_pool_t *pool, uint32_t hash)
{
* Determine how to pick choose the home server.
*/
switch (pool->type) {
-
-
/*
* For load-balancing by client IP address, we
* pick a home server by hashing the client IP.
hash = 0;
break;
}
+
+ pick_matching_server:
+ /*
+ * Try the matching server first. If it's alive, we return it.
+ *
+ * Otherwise we fall back to just picking a random one.
+ */
start = hash % pool->num_home_servers;
+ found = pool->servers[start];
+ if (home_server_active(request, found)) return found;
+
+ /*
+ * The matching one is dead. We then use the
+ * "load-balance" algorithm to pick the server.
+ */
+ found = NULL;
+ start = 0;
break;
case HOME_POOL_CLIENT_PORT_BALANCE:
}
hash = fr_hash_update(&request->packet->src_port,
sizeof(request->packet->src_port), hash);
- start = hash % pool->num_home_servers;
- break;
+ goto pick_matching_server;
case HOME_POOL_KEYED_BALANCE:
if ((vp = fr_pair_find_by_num(request->config, PW_LOAD_BALANCE_KEY, 0, TAG_ANY)) != NULL) {
hash = fr_hash(vp->vp_strvalue, vp->vp_length);
start = hash % pool->num_home_servers;
- break;
+ goto pick_matching_server;
}
/* FALL-THROUGH */
- case HOME_POOL_LOAD_BALANCE:
case HOME_POOL_FAIL_OVER:
+ case HOME_POOL_LOAD_BALANCE:
start = 0;
break;
default: /* this shouldn't happen... */
start = 0;
break;
-
}
/*
* it. If it is too busy, skip it.
*
* Otherwise, use it.
+ *
+ * The difference between fail-over (i.e redundant) and
+ * load balance is that redundant always starts at the
+ * first one, and load balance starts at a random one.
*/
for (count = 0; count < pool->num_home_servers; count++) {
home_server_t *home = pool->servers[(start + count) % pool->num_home_servers];
}
/*
- * We've found the first "live" one. Use that.
+ * For fail-over, we just pick the first one
+ * which is alive.
+ *
+ * For all other methods, we load balance among
+ * all servers, picking the least busy home
+ * server.
*/
- if (pool->type != HOME_POOL_LOAD_BALANCE) {
+ if (pool->type == HOME_POOL_FAIL_OVER) {
found = home;
break;
}