We’ve talked about using a few different modules, like a SIP Registrar and Htable, that rely on data stored in Kamailio’s memory, the same is true for all the Stateful proxy discussion last week.
But what if you want to share this data between multiple Kamailio instances? This allows distributing workload and every server having the same information and therefore any server is able to process any request.
Enter DMQ the Distributed Messaging Queue,
This allows memory data to be shared between multiple Kamailio instances (aka “Nodes”), so for example if you are storing data in Htable on one Kamailio box, all the other boxes/nodes in the DMQ pool will have the same HTable data.
Kamailio uses SIP to transfer DMQ messages between DMQ nodes, and DNS to discover DMQ nodes.
For this example we’ll share user location data (usrloc) between Kamailio instances, so we’ll create a very simple setup to store location data:
####### Routing Logic ########
/* Main SIP request routing logic
* - processing of any incoming SIP request starts with this route
* - note: this is the same as route { ... } */
request_route {
#Enable record_routing so we see the BYE / Re-INVITE etc
if(is_method("REGISTER")){
save("location");
}else{
sl_reply("500", "Nope");
}
}
Now if we register a SIP endpoint we should be able to view it using Kamcmd’s ul.dump call, as we talked about in the Kamailio SIP Registrar tutorial.
Next we’ll setup DMQ to allow this data to be shared to other nodes, so they also have the same userloc data available,
First we’ll begin by binding to an extra port for the DMQ messages to go to, to make it a bit clearer what is normal SIP and what’s DMQ,
So for this we’ll add a new line in the config to listen on port 5090:
/* uncomment and configure the following line if you want Kamailio to
* bind on a specific interface/port/proto (default bind on all available) */
listen=udp:0.0.0.0:5060
listen=tcp:0.0.0.0:5060
listen=udp:0.0.0.0:5090
Next we’ll load the DMQ modules and set them up:
loadmodule "dmq.so"
loadmodule "dmq_usrloc.so"
# ---- dmq params ----
modparam("dmq", "server_address", "sip:0.0.0.0:5090")
modparam("dmq", "notification_address", "sip:dmq.nickvsnetworking.com:5090")
modparam("dmq", "multi_notify", 1)
modparam("dmq_usrloc", "enable", 1)
The server_address means we’re listening on any IP on port 5090. In production you may have an IP set here of a private NIC or something non public facing.
The notification address resolves to 2x A records, one is the IP of this Kamailio instance / node, the other is the IP of the other Kamailio instance / node, I’ve just done this in /etc/hosts
root@dmq1:/etc/kamailio# nslookup dmq.nickvsnetworking.com Server: 127.0.0.53 Address: 127.0.0.53#53 Non-authoritative answer: Name: dmq.nickvsnetworking.com Address: 192.168.3.121 Name: dmq.nickvsnetworking.com Address: 192.168.3.116
Finally we’ll add some routing logic to handle the DMQ messages coming in on port 5090:
####### Routing Logic ########
/* Main SIP request routing logic
* - processing of any incoming SIP request starts with this route
* - note: this is the same as route { ... } */
request_route {
if (is_method("KDMQ") && $Rp == 5090)
{
dmq_handle_message();
}
#Enable record_routing so we see the BYE / Re-INVITE etc
if(is_method("REGISTER")){
save("location");
}else{
sl_reply("500", "Nope");
}
}
We’ll put the same config on the other Kamailio instance and restart Kamailio on both.
We can now check the DMQ node status to confirm they’re talking to each other.
root@dmq1:/etc/kamailio# kamcmd dmq.list_nodes { host: 192.168.3.116 port: 5090 resolved_ip: 192.168.3.116 status: active last_notification: 0 local: 0 } { host: 192.168.3.121 port: 5090 resolved_ip: 192.168.3.121 status: active last_notification: 0 local: 0 } { host: 0.0.0.0 port: 5090 resolved_ip: 0.0.0.0 status: active last_notification: 0 local: 1 }
Bingo they are,
Now if I register to one of these two instances, I can run a kamcmd ul.dump on either and they’ll both have the same data. Magic!