RabbitMQ evolution with OpenSIPS 2.3

rabbitmqlogoRabbitMQ is a powerful and widely used tool for message queuing integrations. And the usage of such a tool requires a more flexible support from OpenSIPS. Let’s see what 2.3 has to offer when comes to RabbitMQ based integration.

RabbitMQ is an open source message queuing/broker server, used by applications to publish messages on one side and consume them on the other side by a different application. The RabbitMQ server can be used to store, queue and route messages to multiple applications. It uses a subscribe-publish model to deliver messages to anyone interested in them. It implements the Advanced Message Queuing Protocol (AMQP), which is a very flexible and programmable protocol used to route and exchange messages.

OpenSIPS can be easily integrated with RabbitMQ to publish messages to the message broker. These messages can be read on the other side by different consumer applications. Integration with RabbitMQ comes in two flavors:

  1. Starting with version 1.7 OpenSIPS can automatically trigger events using RabbitMQ
  2. Starting with OpenSIPS 2.3, RabbitMQ messages can be published directly from OpenSIPS script in a more flexible and complex way

RabbitMQ Events

OpenSIPS Event Interface is a mechanism used to trigger internal events to external applications. These events can be related to OpenSIPS‘ internal state, such as running out of memory, or losing database connection, as well as triggered by SIP signalling, such as when a new customer is registered, a dialog starts, or a CDR is generated. These events can be sent to external applications over various channels such as xmlrpc commands, datagram packets, running OpenSIPS routes as well as sending RabbitMQ messages.

In order to receive events over RabbitMQ, one needs to load the event_rabbitmq module and subscribe for events to be sent to a specific AMQP URI. This can be done by either issuing an MI command:

opensipsctl fifo event_subscribe E_PIKE_BLOCKED rabbitmq:guest@127.0.0.1/queue 0

or by subscribing directly in the OpenSIPS script:

startup_route {
    subscribe_event("E_PIKE_BLOCKED", "rabbitmq:guest@127.0.0.1/queue");
}

Any further events triggered by OpenSIPS will be sent to the RabbitMQ server specified in the URI. Publishing RabbitMQ messages over the OpenSIPS Event Interface works very well, but this approach has a few limitations:

  1. messages are sent only when an event is triggered. Although it is possible to manually trigger a custom event, scripting this becomes a bit more complicated.
  2. events raised through RabbitMQ have a specific format and carry certain information. One cannot simply add an opaque body to the message.
  3. because the RabbitMQ URI has a strict format, it is hard to tune RabbitMQ parameters such as exchange, headers, etc.
  4. OpenSIPS events are a generic concept. Therefore all the data attached to an event needs to be stored in a generic manner, because it is sent to consumer applications over different transports. This means that internal data cannot be efficiently aligned to the RabbitMQ rigid format, hence further processing is required when building the message.

A more flexible RabbitMQ support

OpenSIPS 2.3 comes with a new rabbitmq module that integrates directly with RabbitMQ and offers a more complex and flexible way to customize the messages delivered to the message broker. Using the new module one can specify multiple connections to different RabbitMQ servers, each connection having its own properties (such as heartbeat interval). When publishing a message, you can choose any of these connections.

Messages sent to the RabbitMQ broker can also be fine tuned. The module allows you to route messages to a specified exchange using a custom routing_key. One can also tune the AMQP parameters such as the persistence mode (whether the message should survive a restart or not) on the RabbitMQ server and whether the message should be sent immediately to a consumer or not. The body of the message is now an opaque value with a customizable content type. Finally, the RabbitMQ message can also have a set of key-value headers stored in the AMQP message, that can be further used by the RabbitMQ server for taking routing decisions.

RabbitMQ module usage

To use the new rabbitmq module all you have to do is to specify a RabbitMQ server and publish the message from your script. The following OpenSIPS configuration file snippet publishes the SIP message’s body of every call to a local RabbitMQ server using the “body” routing-key:

...
# connection to the RabbitMQ server
modparam("rabbitmq", "server_id","[local] 
    uri = amqp://user:password@127.0.0.1; heartbeat = 5")
...
route {
    ...
    if (is_method("INVITE") && !has_totag())
        rabbitmq_publish("local", "body", "$rb", "$cT");
    ...
}
...

Remarks

The development of the new RabbitMQ module for OpenSIPS 2.3 has been sponsored by Voicenter – many thanks for supporting the OpenSIPS project!

2 thoughts on “RabbitMQ evolution with OpenSIPS 2.3

    1. Actually, the 0 at the end of the MI command is the expire parameter, which is irrelevant for the rabbitmq protocol – we might as well ignore it. A rabbitmq subscription does not expire.

      Like

Leave a comment