SIP Load Balancing

Home » Asterisk Users » SIP Load Balancing
Asterisk Users 13 Comments

I have a very simple setup with two SIP routes to my carrier. I need to have
every other phone call placed to that carrier go to a different address.

This is what I need the call flow to look like. I have spent many hours
searching and have not found a working example.
Call1 exten => NXXNXXXXX,2,Dial(SIP/${DIALEDNUM}@2.4.6.8
)
Call2 exten => NXXNXXXXX,2,Dial(SIP/${DIALEDNUM}@1.2.3.4
)
Call3 exten => NXXNXXXXX,2,Dial(SIP/${DIALEDNUM}@2.4.6.8
)
Call4 exten => NXXNXXXXX,2,Dial(SIP/${DIALEDNUM}@1.2.3.4
)
Call5 exten => NXXNXXXXX,2,Dial(SIP/${DIALEDNUM}@2.4.6.8
)
Call6 exten => NXXNXXXXX,2,Dial(SIP/${DIALEDNUM}@1.2.3.4
)
Call7 exten => NXXNXXXXX,2,Dial(SIP/${DIALEDNUM}@2.4.6.8
)
Call8 exten => NXXNXXXXX,2,Dial(SIP/${DIALEDNUM}@1.2.3.4
)
……………………..

13 thoughts on - SIP Load Balancing

  • I think what you need to do here is check/set a variable in the astdb.

    (If the variable is 1, set it to 2 and route via A; otherwise, set it to
    1 and route via B.)

    Translation of this to dialplan logic is left as an exercise for the
    student.

    R

  • Sorry for the confusion, but the last sentence throws me off. “Translation
    of this to dialplan logic is left as an exercise for the
    student.” Is this example from some sort of book or is this a way of saying
    I am left to figure the rest out??

    I was hoping to find a simple example of how this works.

  • It’s a way of leafing you to figure the rest out.

    It’s a bastardised version of a quote from many textbooks – along the
    lines of “implementation is left as an excercise to the student” – ie.
    this is the method in general terms, you write nuts & bolts of the code.

    One reference to it might be:

    http://catb.org/jargon/html/E/exercise–left-as-an.html

    Roger has told you how to do it – use a variable kept in the astdb and
    alternate it

    In pseudo code:

    if (switch == 1)
    Dial (SIP/provider1/number)
    switch = 0
    else
    Dial (SIP/provider2/number
    switch = 1
    endif

    Now your task is write the actual dialplan. Or you can pay me or Roger to
    do it for you if you like, but really, it’s only a few lines of dialplan.

    Gordon

  • Actually it was not so difficult to understand what Roger said, but let me
    expand it further (the way I would do it):

    First of all setup a global variable TRUNK in extension.conf;
    [globals]
    TRUNK=0;

    Then use your dialplan like this:

    exten => NXXNXXXXX,1,GotoIf($[“${TRUNK}”=”0”]?trunk1:trunk2)

    exten => NXXNXXXXX,n(trunk1),SetGlobalVar(TRUNK=1])
    exten => NXXNXXXXX,n,Dial(SIP/${DIALEDNUM}@2.4.6.8 )

    exten => NXXNXXXXX,n(trunk2),SetGlobalVar(TRUNK=0)
    exten => NXXNXXXXX,n,Dial(SIP/${DIALEDNUM}@1.2.3.4 )

    I used global variable because otherwise your variable will always reset
    itself on a start of a call and will always stay 0.

    If you want to add more trunks in the future, you can expand this logic
    using:
    SetGlobalVar(TRUNK=$[${TRUNK}+1]

    and for every trunk number, go to a different line of the context. In the
    end, make sure to set the TRUNK variable back to 0.

    Using a macro for dialing would be even a better idea, but that would make
    it more complicated for you at this time. Keep it simple for only two
    trunks.

    Sincerely,

    Zeeshan A Zakaria

    http://www.ilovetovoip.com
    http://www.pbxforall.com (beta)

  • Thanks For The replies. I have tried piecing the samples together. Just for
    testing purposes i have created the following.

    [test]
    exten =>
    _X.,1,GotoIf(${SET(DB(avoics/route)=$[!0${DB(avoics/route)}])}?route1:route2)
    exten => _X.,n(route1),Set(DB(avoics/route)=1)
    exten => _X.,n,SayNumber(1)
    exten => _X.,n,Hangup()
    exten => _X.,n(route2),Set(DB(avoics/route)=0)
    exten => _X.,n,SayNumber(2)
    exten => _X.,n,Hangup()

    The idea is if I continue dialing any number into this context I should hear
    1 2 1 2 1 2

    Currently it is skipping to 2 as it should be since my database shows:
    /avoics/route : 1

    It appears there is something wrong with my set command?

  • If your goal is really load balancing, not just alternating between
    providers, you might look at the GROUP* functions. Otherwise, if you
    hit a stretch where you have, e.g., several even-numbered calls of long
    duration mixed with short odd-numbered calls, most of your traffic will
    wind up on the same route.

  • Its not so much me load balancing but the carrier requires that every other
    call I send goes to the other address..

  • You can drop your separate Set application. The SET() dialplan function
    does the alternation for you.

  • I updated it as follows and I am still only getting the SayNumber(2)

    [tim]
    exten =>
    _X.,1,GotoIf(${SET(DB(avoics/route)=$[!0${DB(avoics/route)}])}?route1:route2)
    exten => _X.,n(route1),SayNumber(1)
    exten => _X.,n,Hangup()
    exten => _X.,n(route2),SayNumber(2)
    exten => _X.,n,Hangup()

  • It seems that the
    GotoIf(${SET(DB(avoics/route)=$[!0${DB(avoics/route)}])}?route1:route2) is
    always returning false as if the SET command is not returning a value nor is
    it changing the value in the DB.
    Will this not work because I am running Asterisk 1.4.25.1??

  • You’ve identified a bug in the expression parser. I have just fixed it in
    Subversion. In the meantime, you can drop the ‘0’ in the expression, and
    it should work fine. It was only there to ensure that you did not get an
    error the first time through, when the db key might not exist.