Skip to end of metadata
Go to start of metadata

This article describes OpenSIPS based SIP Load Balancer. For building a SIP Proxy on AWS, please click Here.

Description

OpenSIPS Load Balancer module setting up traffic routing based on load. It can select the least loaded destination from the list of multiple targets, keep track of available ports and health of the destination targets. OpenSIPS can read routes from its routing database. In this example we will use MySQL as its routing database.

Setting up MySQL database

Start by installing MySQL database. It can be located locally or on the remote host. We need to create at least a minum set of tables for OpenSIPS:

  • Standard tables
  • Load balancer tables
  • Dialog module tables (Dialog module is required for Load Balancer)

MySQL initialization scripts are located in `scripts/mysql/` directory. They can be imported with these commands:

mysql -p opensips < scripts/mysql/standard-create.sql
mysql -p opensips < scripts/mysql/dialog-create.sql
mysql -p opensips < scripts/mysql/load_balancer-create.sql

Create a MySQL user and grant privileges to it. You will need SELECT privileges for all tables and ALL PRIVILEGES for a dialog table.

Fill at least one route into load_balancer table:

mysql> INSERT INTO load_balancer (group_id, dst_uri, resources, probe_mode) VALUES (1, 'sip:192.168.1.10', 'trunk=30', 1);
mysql> select * from load_balancer;
+----+----------+-------------------+-----------+------------+-------------+
| id | group_id | dst_uri           | resources | probe_mode | description |
+----+----------+-------------------+-----------+------------+-------------+
|  1 |        1 | sip:192.168.1.10  | trunk=30  |          1 |             |
+----+----------+-------------------+-----------+------------+-------------+

Data in database should look like above. Some notes on the column meanings:

  • group_id - Resources can be grouped into groups, this is used in more complex scenarios. User any numeric value here.
  • dst_uri - destination URI.
  • resources - we specifiy number of channels here for each destination, but also a resource type. This allows to tell OpenSIPS that for this or another resource we want to specify different number of available ports. In example above we just chose keyword "trunk" and set 30 ports to it.
  • probe_mode - OpenSIPS is able to send SIP probes to the destination to determine their health. Use 0 for no probes, 1 - to probe only when destination is disabled, 2 - to probe always

Configuration file

Start by loading Dialog and Load Balancer modules:

#### DIALOG module
loadmodule "dialog.so"
modparam("dialog", "dlg_match_mode", 1)
modparam("dialog", "default_timeout", 21600)
modparam("dialog", "db_mode", 2)
modparam("dialog", "db_url", "mysql://username:password@localhost/opensips")

#### LOAD BALANCER module
loadmodule "load_balancer.so"
modparam("load_balancer", "db_url", "mysql://username:password@localhost/opensips")
modparam("load_balancer", "probing_method", "OPTIONS")
modparam("load_balancer", "probing_interval", 30)


Then, in the routing script find the place where the destination in selected (usually around route(relay) statement) and add this block:

        xlog("searching for route");
        if ( !lb_start("1","trunk","s")) {
                send_reply("500","No Destination available");
                exit;
        }
        t_on_failure("GW_FAILOVER");
        route(relay);

The code above searches for a route with the help of lb_start() function. We have supplied 3 arguments to it:

  • The first argument is group_id, it has to match with the Group ID in the database
  • The second argument is resource type. Remember it was set to "trunk" in database. It should match as well.
  • The third argument is optional flag. In the example above flag "s" means to randomly try all available routes instead of filling up first, second etc.

The t_on_failure() statement is invoked when Load Balancer has determined that the first route is not available. Add following code block to handle it:

failure_route[GW_FAILOVER] {
        if (t_was_cancelled()) {
                exit;
        }
        # failure detection with redirect to next available trunk
        if (t_check_status("(408)|([56][0-9][0-9])")) {
                xlog("Failed trunk $rd/$du detected \n");
                if ( lb_next() ) {
                        t_on_failure("GW_FAILOVER");
                        t_relay();
                        exit;
                }
                send_reply("500","All GW are down");
        }
}

This block recursively does status check and recursively calls itself until either a valid route is found or all gateways are down and error 500 is returned.




  • No labels