[asterisk-dev] AstriDevCon Follow Up - Asterisk and Kamailio - smoother integration

Matthew Jordan mjordan at digium.com
Mon Feb 23 09:19:57 CST 2015

On Wed, Feb 11, 2015 at 11:12 AM, Olle E. Johansson <oej at edvina.net> wrote:

> On 11 Feb 2015, at 17:50, Matthew Jordan <mjordan at digium.com> wrote:
> On Tue, Feb 3, 2015 at 6:11 AM, Daniel-Constantin Mierla <
> miconda at gmail.com> wrote:
> I was thinking some more about this, and I realized that I'm not really
> sure how I would pick a specific Asterisk server in a pool of servers.
> This is probably going to demonstrate some of my ignorance when it comes
> to Kamailio, but I'm going to go ahead anyway :-)
> Say, for example, we have n Asterisk servers, all of which can serve any
> need that an inbound SIP request requires. They are generic media
> application servers, and Kamailio just needs to pick one and send the
> request to it, most likely indicating the purpose in a SIP header. Then, we
> may receive a request from Alice to go into a conference room:
> INVITE sip:conference at my-service-provider.com SIP/2.0
> From: Alice <alice at super-awesome-company.com>
> ...
> And we want to proxy that request to one of our media application servers,
> turning it into something like this:
> INVITE sip:conference at asterisk-node-five.mydomain.com SIP/2.0
> From: Alice <alice at super-awesome-company.com>
> To: ...
> X-Exec-App: Conference
> X-Exec-App-Data: 1000
> No need to retarget unless your asterisk is really requiring that domain.

True. The same questions exist even if we are sending the INVITE request to
sip:conference at asterisk-node-five.myservice-provider.com however.

> Any Asterisk server can then receive the request, extract the application
> to execute, and start the correct application, letting an ARI application
> do the heavy lifting of actually implementing the requested application.
> exten => s,1,NoOp()
>  same => n,Set(app=${PJSIP_HEADER(read,X-Exec-App)})
>  same => n,Set(args=${PJSIP_HEADER(read,X-Exec-App-Data)})
>  same => n,Stasis(${app}, ${args})
>  same => n,Hangup()
> All of that is fine and good - but how did Kamailio choose
> "asterisk-node-five" as the Asterisk server to send the request to?
> There are many ways, our dispatcher module has as many ways to dispatch
> traffic as Asterisk has
> queue algorithms.
I think that's a very apt comparison :-)

The Queue application's ring strategies can be problematic. In relatively
simple scenarios they apply fairly well; with sufficient complexity, you
either have to use other mechanics to achieve the functionality you want
(say, for example, Local channel members) or you find that your ring
strategy simply isn't achievable. Sometimes, Asterisk _can_ provide you the
levers to toggle the behaviour you want; however, in many complex
scenarios, it can't give you all the functionality you desire. Ideally, you
want the developer building a system on top of Asterisk to control the
business application logic - hence, the advent of ARI. In fact, the Queue
application's ring strategy limitations were a major contributing factor in
the development of ARI.

The same could be said here. Sure, I can use one of the many levers that
exist in the dispatcher module, and there's a reasonable chance that it
will accommodate the complexity of a particular scenario. Playing around
with it over the past few days, ds_select_dst is clearly very powerful. On
the other hand, I'm still limited to the algorithms implemented in
Kamailio. While I could write my own algorithm in C and contribute it
upstream, not everyone is a C programmer!

It may be given the tight timing constraints that Kamailio exists under
(which is somewhat tighter than Asterisk determining who to ring in a Call
Queue) that hardcoding the algorithms in Kamailio is the best way to do it
- but I'm curious if there are ways outside of that.

> What's more, if those servers are truly dynamic, where we are using
> something like OpenStack to spin up and spin down Asterisk servers on an
> as-needed basis, than the mere act of knowing the pool of available
> Asterisk server is going to be tricky. Granted, the Asterisk servers could
> register themselves to Kamailio, so it will know at any one time who all is
> available for a resource, but it feels like the Kamailio routing could get
> tricky, with a lot of business logic sprinkled into it.
> We could add the new DMQ message buss to Asterisk which would make
> Kamailio aware of it.
> There are many ways. Kamailio monitors the cluster with OPTIONs so if you
> spin up one that was
> down, it won't take long before we send traffic.
Or we could have Kamailio integrate with Asterisk using Corosync :-)

The DMQ message bus module looks to be rather generic. Is there any
documentation on the actual messages published over the message bus?

> Expanding on the snippet above, if I send another request from Bob <
> bob at super-awesome-company.com>, and Bob is attempting to get into the
> same conference room by sending a request to
> conference at my-service-provider.com, I need to have the logic someplace
> that we would preferably send Bob to the same Asterisk server. Granted, two
> Asterisk servers can form a single conference room by connecting themselves
> together, but that's less efficient than having both SIP requests land on
> the same Asterisk server.
> That is one area that needs some logic. I have used a realtime database
> for this with kamailio asking
> for routing. Or in another setup I just fork to all asterisk servers and
> the one that has the conference
> answers. If no one answer, I retarget the request to another uri which
> means "OPEN the damn conference"
> and target that to one specific server.
Ouch on the forking. That's a bit of extra traffic on the Asterisk servers!

I think this goes back to my previous point of having "business logic" be
accessible from the routing logic in Kamailio, where that business logic is
hopefully not hardcoded in a non-scalable way.

> There may be elegant ways to handle this in Kamailio already; I'm just not
> sure what they would be in this scenario.
> One way of handling this using Asterisk would be to have another Asterisk
> instance (or predictable set of Asterisk instances) act as a Redirect
> server. All requests that require a media application server get sent to
> those limited number of Asterisk servers, and they use an ARI application
> to perform the business logic lookups of who to forward the request onto.
> That Asterisk server would always return a 302 Redirect. Whether or not
> that removes Kamailio from the entire path or not is probably up to
> Kamailio to decide. But that ends up adding more communication to the path,
> and I'm not sure that's the right way to handle this.
> Too complex.
> At some point in time, there's going to be (a) logic that requires dynamic
> lookups to determine where to send a request, and (b) business logic that
> has to live somewhere to govern those routing rules. I do know that having
> all of that live or be replicated across Asterisk servers is not fantastic;
> my inclination right now is to pull that out of the Asterisk instances and
> have those kinds of lookups live outside of the communications engines. I'd
> be curious what other options are available in a larger system architecture.
> Sorry, but you are discussing non-issues. At least for me.
> An issue in my mind would be to feed the load of one asterisk into
> kamailio to help with load-balancing algorithms. We have the data in
> Asterisk, but it's
> not in Kamailio. DMQ could be one option here, or an AMI module for
> Kamailio.
I'm not sure it's completely a non-issue. The scenario where individual
requests are logically grouped at a higher level than what a pure
load-balancing algorithm can ascertain is certainly "an issue," even if you
solved it in a particular manner. Going to a database to determine whether
or not a request should go to a particular server is certainly one way of
solving it. However, you may either have to hit that database for every
request, or you have to know in your routing that some destinations will
require that lookup - which again requires adding business related logic to
the Kamailio routing. Maybe that result is a foregone conclusion, but I'm
curious if there are other ways around it.

The internet is certainly not overflowing with information on this topic,
at the very least :-)

I agree that having the load of Asterisk feed out would be interesting. We
had some discussion about this at AstriDevCon; particularly, what data
items would be needed. There was some contention around exactly what should
be available from Asterisk. Things that were listed were:

   - CPU usage
   - Channel count
   - Memory usage
   - Call quality statistics (as a secondary indicator)
   - Distribution of response times on requests/responses

I believe Torey mentioned that they send an INVITE request every so often
and just see what happens - which is probably similar to the OPTIONS
request pinging, although you'll get a bit more useful data out of the
INVITE request.

Can you think of anything else?

Are there other ways of distributing this information other than AMI/DMQ?
Asterisk also supports other mechanisms, including more standardized ones
such as Corosync, statsd, etc. Given how easy it is to build an interface
on top of the internal message bus in Asterisk, we're pretty flexible
there. If we did push more information about load out of Asterisk, it'd be
nice if it was in a standard way of consuming, such that it benefited users
outside of Kamailio as well.


Matthew Jordan
Digium, Inc. | Engineering Manager
445 Jan Davis Drive NW - Huntsville, AL 35806 - USA
Check us out at: http://digium.com & http://asterisk.org
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-dev/attachments/20150223/496e0594/attachment-0001.html>

More information about the asterisk-dev mailing list