Load Balancing in OpenSips
Load Balancing in OpenSips
Dispatcher has no load information - it just blindly forwards calls to the destinations based on
a probabilistic dispersion logic. It gets no feedback about the load of the destination (like how
many calls that were sent actually were established or how many are still going).
Load-balancer is load driven - LB routing logic is based primary on the load information. The
LB module is using the DIALOG module in order to keep trace of the load (ongoing calls).
+----+----------+-------------------------
+---------------------------------+
| id | group_id | dst_uri | resources
|
+----+----------+-------------------------
+---------------------------------+
| 1 | 1 | sip:yate1.mycluster.net | transc=30; pstn=32
|
| 2 | 1 | sip:yate2.mycluster.net | vm=100; transc=10
|
| 3 | 1 | sip:yate3.mycluster.net | vm=50; conf=300
|
| 4 | 1 | sip:yate4.mycluster.net |
vm=10;conf=10;transc=10;pstn=32 |
+----+----------+-------------------------
+---------------------------------+
if (!load_balance("1","transc;pstn")) {
sl_send_reply("500","Service full");
exit;
}
The first parameter of the function identifies the LB set to be used (see the group_id column in the
above DB snapshot). Second parameter is list of the required resource for the call. A third optional
parameter my be passed to instruct the LB engine on how to estimate the load - in absolute value (how
many channels are used) or in relative value (how many percentages are used).
The load_balance() will automatically create the dialog state for the call (in order to monitor it) and
will also allocate the requested resources for it (from the selected box).
The function will set as destination URI ($du) the address of the selected destination/box.
The resources will be automatically released when the call terminates.
The LB module provides an MI function that allows the admin to inspect the current load over the
destinations.
Example:
1) only boxes (1) and (4) will be selected at as they offer both
transcoding and pstn
3) for each box, the minimum available load (through all resources)
(1) 14 (PSTN)
(2) 1 (transcoding)
4) final selected box in (1) as it has the the biggest (=14) available
load for the most loaded resource.
The selection algorithm tries to avoid the intensive usage of a resource per box.
To enable pinging, you need first to set probing_interval to a non zero value - how often the pinging
should be done. The pinging will be done by periodically sending a OPTIONS SIP request to the
destination - see probing_method option.
To control which and when a destination is pinged, there is the probe_mode column in
the load_balancer table - see table definition. Possible options are:
3.1 Configuration
Let's consider the following case: a cluster of media servers providing voicemail service and PSTN (in
and out) service. So the boxes will be able to receive calls for Voicemail or for PSTN termination, but
they will be able to send back calls only for PSTN inbound.
We also want the destinations to be disabled from script (when a failure is detected); The re-enabling
of the destinations will be done based on pinging - we do pinging only when the destination is in
"failed" status.
4 destinations/boxes in the LB set
1) offers 50 channels for voicemail and 32 for PSTN
2) offers 100 voicemail channels
3) offers 50 voicemail channels
4) offers 10 voicemail and 64 PSTN
+----+----------+-------------------------+-------------------
+-----------+
| id | group_id | dst_uri | resources |
prob_mode |
+----+----------+-------------------------+-------------------
+-----------+
| 1 | 1 | sip:yate1.mycluster.net | vm=50; pstn=32 |
1 |
| 2 | 1 | sip:yate2.mycluster.net | vm=100 |
1 |
| 3 | 1 | sip:yate3.mycluster.net | vm=50 |
1 |
| 4 | 1 | sip:yate4.mycluster.net | vm=10;pstn=64 |
1 |
+----+----------+-------------------------+-------------------
+-----------+
fork=yes
children=2
log_stderror=no
log_facility=LOG_LOCAL0
disable_tcp=yes
disable_dns_blacklist = yes
auto_aliases=no
check_via=no
dns=off
rev_dns=off
loadmodule "modules/maxfwd/maxfwd.so"
loadmodule "modules/sl/sl.so"
loadmodule "modules/db_mysql/db_mysql.so"
loadmodule "modules/tm/tm.so"
loadmodule "modules/uri/uri.so"
loadmodule "modules/rr/rr.so"
loadmodule "modules/dialog/dialog.so"
loadmodule "modules/mi_fifo/mi_fifo.so"
loadmodule "modules/mi_xmlrpc/mi_xmlrpc.so"
loadmodule "modules/signaling/signaling.so"
loadmodule "modules/textops/textops.so"
loadmodule "modules/sipmsgops/sipmsgops.so"
loadmodule "modules/load_balancer/load_balancer.so"
modparam("dialog", "db_mode", 1)
modparam("dialog", "db_url",
"mysql://opensips:opensipsrw@localhost/opensips")
modparam("rr","enable_double_rr",1)
modparam("rr","append_fromtag",1)
modparam("load_balancer",
"db_url","mysql://opensips:opensipsrw@localhost/opensips")
# ping every 30 secs the failed destinations
modparam("load_balancer", "probing_interval", 30)
modparam("load_balancer", "probing_from", "sip:pinger@LB_IP:LB_PORT")
# consider positive ping reply the 404
modparam("load_balancer", "probing_reply_codes", "404")
route{
if (!mf_process_maxfwd_header("3")) {
send_reply("483","looping");
exit;
}
if ( has_totag() ) {
# sequential request -> obey Route indication
loose_route();
t_relay();
exit;
}
# send it out
if (!t_relay()) {
sl_reply_error();
}
}
failure_route[LB_failed]
{
# skip if call was canceled
if (t_was_cancelled()) {
exit;
}