Featured image of post kamailio 集群(DMQ)介绍

kamailio 集群(DMQ)介绍

背景介绍

当kamailio需要做集群或者主备时, 需要对集群节点做数据同步。

  1. DMQ_USRLOC用来对注册用户信息做同步
  2. DMQ用来实现数据同步的方式
  3. Dialog会话信息

本次以常见的两个节点方式为例介绍,kamailio的节点并没有主备的概念,这点和opensips有点不一样。

节点1 节点2
172.16.4.111 172.16.4.113

kamailo版本:

version: kamailio 5.8.5 (x86_64/linux)

DMQ 模块介绍

DMQ 用于节点之间使用SIP消息(KDMQ)进行同步, 新节点可以通过发送可用的消息通知来加入集群, 如果节点不响应其他活跃节点的消息,那么就会被踢出集群。 集群节点的kamailio版本必须一致。

DMQ 参数解析

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# 本地发送和接收DMQ 消息的地址
modparam("dmq", "server_address", "sip:172.16.4.111:5464")
# 本地监听DMQ消息的地址,默认 NULL
modparam("dmq", "server_socket", "udp:172.16.4.111:5464")
# 通知备节点地址,默认 NULL
modparam("dmq", "notification_address", "sip:172.16.4.113:5464")
# 通知消息通道,默认"notification_peer"
modparam("dmq", "notification_channel", "peers")
# 是否可以解析多个IPv4/IPv6地址,0,只解析第一个地址;非0,通过host解析所有的ip. 默认 0
modparam("dmq", "multi_notify", 1)

# DMQ工作线程数量,默认 2
modparam("dmq", "num_workers", 4)
# DMQ工作线程休眠时间,默认0 
modparam("dmq", "worker_usleep", 0)
# DMQ心跳时间,默认 60 秒
modparam("dmq", "ping_interval", 90)

要提前监听listen=udp:172.16.4.111:5462

DMQ 重要函数

  1. dmq_handle_message()

处理DMQ 消息, 可以用在REQUEST_ROUTE

  1. dmq_process_message()

dmq_handle_message()类似,但是处理是立即的,不再是copy这个请求到共享内存中给DMQ workers去处理。

  1. dmq_send_message(channel, node, body, content_type)

发送DMQ消息到单节点,示例:

dmq_send_message("channel1", "sip:10.0.0.21:5060", "Message body...", "text/plain");

  1. dmq_bcast_message(channel, body, content_type)

发送DMQ消息到所有节点,示例: dmq_bcast_message("channel1", "Message body...", "text/plain");

  1. dmq_t_replicate()

复制当前的SIP消息到所有节点。只能用在REQUEST_ROUTE

  1. dmq_is_from_node()

判断当前请求是不是被其他的节点发送过。示例:

1
2
3
4
5
6
7
8
9
if(is_method("REGISTER")) {
    if (dmq_is_from_node()) {
        # coming from a DMQ node - already authenticated there
        # now just save contact, etc...
    } else {
        # coming from end point - authenticate, save contact, etc...
        dmq_t_replicate("1"); # source address checked, skip the loop test
    }
}

DMQ 实战

为方便观察server_socketserver_address的区别,特意把这两个的端口设置不同, 以及两个节点的ping_interval时间不一样。

  1. 1节点 172.16.4.111配置
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
listen=udp:172.16.4.111:5465
loadmodule "dmq.so"

modparam("dmq", "server_address", "sip:172.16.4.111:5464")
modparam("dmq", "server_socket", "udp:172.16.4.111:5465")
modparam("dmq", "notification_address", "sip:172.16.4.113:5464")
modparam("dmq", "notification_channel", "peers")
modparam("dmq", "num_workers", 4)
modparam("dmq", "ping_interval", 30)
...

request_route {
    ...
    if(is_method("KDMQ")) {
        dmq_process_message();
    }
    ...
}
  1. 2节点 172.16.4.113配置
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
listen=udp:172.16.4.113:5464

loadmodule "dmq.so"
modparam("dmq", "server_address", "sip:172.16.4.113:5464")
modparam("dmq", "server_socket", "udp:172.16.4.113:5465")
modparam("dmq", "notification_address", "sip:172.16.4.111:5464")
modparam("dmq", "notification_channel", "peers")
modparam("dmq", "num_workers", 4)
modparam("dmq", "ping_interval", 40)
...
request_route {
    ...
    if(is_method("KDMQ")) {
        dmq_process_message();
    }
    ...
}

172.16.4.111 发送请求的sip信令图如下: 111

可以看到KDMQ消息发送是通过server_socket发出的,其中的sip信令填充了server_address

172.16.4.113 发送请求的sip信令图如下: 113

同理,和111的情况一致。

所以为避免占用较多的端口, 可以把server_socketserver_address设置为同一个端口。

当节点2服务停掉之后,得到的信令图: 111

可以看到sip消息少了节点2的活跃信息

DMQ_USRLOC 模块介绍

DMQ_USRLOC 参数解析

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# 是否开启DMQ_USRLOC模块,默认 0,不开启
modparam("dmq_usrloc", "enable", 1)
# 是否在服务一启动时就同步数据,默认 0,不启动同步
modparam("dmq_usrloc", "sync", 0)
# 批量同步数据条数,同步之后进入batch_usleep时间, 默认0,不开启批量同步
modparam("dmq_usrloc", "batch_size", 4000)
# 批量同步休眠时间,默认 0,不开启批量同步
modparam("dmq_usrloc", "batch_usleep", 1000)
# 设置同步消息的大小,最大65536,默认60000
modparam("dmq_usrloc", "batch_msg_size", 500000)
# 批量同步联系人条数,默认1,最大150
modparam("dmq_usrloc", "batch_msg_contacts", 50)
# usrloc domain同步参数
modparam("dmq_usrloc", "usrloc_domain", "location")
# 是否同步socker信息,默认 0,不同步;1,同步proto:host:port;2,同步socket name;
modparam("dmq_usrloc", "replicate_socket_info", 1)
# 是否同步删除信息,默认 1,同步;0,不同步删除动作,当usrloc的过期时间很短时,此时设置为0,让其自己删除更高效。
modparam("dmq_usrloc", "usrloc_delete", 0)

DMQ_USRLOC 实战

  1. 1节点72.16.4.111配置:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
listen=udp:172.16.4.111:5460
listen=udp:172.16.4.111:5464
loadmodule "dmq.so"
modparam("dmq", "server_address", "sip:172.16.4.111:5464")
modparam("dmq", "server_socket", "udp:172.16.4.111:5464")
modparam("dmq", "notification_address", "sip:172.16.4.113:5464")
modparam("dmq", "notification_channel", "peers")
modparam("dmq", "num_workers", 4)
modparam("dmq", "ping_interval", 30)

loadmodule "dmq_usrloc.so"
modparam("dmq_usrloc", "enable", 1)
modparam("dmq_usrloc", "sync", 1)
modparam("dmq_usrloc", "batch_msg_contacts", 50)  # 50 contacts / message
modparam("dmq_usrloc", "batch_size", 10000)       # 10000 contacts / batch
modparam("dmq_usrloc", "batch_usleep", 500000)
...
request_route {
    ...
    if(is_method("KDMQ")) {
        dmq_handle_message();
    }
    ...
}
  1. 2节点 172.16.4.113配置:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
listen=udp:172.16.4.113:5460
listen=udp:172.16.4.113:5464
loadmodule "dmq.so"
loadmodule "dmq_usrloc.so"

modparam("dmq", "server_address", "sip:172.16.4.113:5464")
modparam("dmq", "server_socket", "udp:172.16.4.113:5464")
modparam("dmq", "notification_address", "sip:172.16.4.111:5464")
modparam("dmq", "notification_channel", "peers")
modparam("dmq", "num_workers", 4)
modparam("dmq", "ping_interval", 30)

modparam("dmq_usrloc", "enable", 1)
modparam("dmq_usrloc", "sync", 1)
modparam("dmq_usrloc", "batch_msg_contacts", 50)  # 50 contacts / message
modparam("dmq_usrloc", "batch_size", 10000)       # 10000 contacts / batch
modparam("dmq_usrloc", "batch_usleep", 500000)
...
request_route {
    ...
    if(is_method("KDMQ")) {
        dmq_handle_message();
    }
    ...
}

使用软电话注册到172.16.4.111:5460,sip信令图如下: 111

172.16.4.111同步注册数据到172.16.4.113的信令图如下: 111

通过kamctl ul show分别查看111和113机器上存储的usrloc数据:

  • 172.16.4.111机器: 111
  • 172.16.4.113机器: 113

可以知道同步到113机器上的过期时间和111机器上的过期时间不一致。

Dialog 模块介绍

dialog的其他参数暂时不介绍,新增以下配置:

1
2
3
4
5
modparam("dialog", "enable_dmq", 1)
...
if (is_method("INVITE")) {
    dlg_manage();
}

dialog 集群效果

使用两个软电话1003,1008注册到172.16.4.111:5460机器上,1003拨打1008, 然后使用kamctl dialog show分别查看两台机器上的dialog信息。

DMQ发送的sip同步信令: dialog

查看两台机器上的dialog信息:

  • 172.16.4.111机器: 111
  • 172.16.4.113机器: 113

存在的问题

目前当113这个机器上使用 如下的配置:

1
2
3
if(is_method("KDMQ")) {
    dmq_handle_message();
}

DMQ在发送dialog消息时可以返回200Ok

但是如果用的是dmq_process_message(),此时会报错 400 Bad Request. 113机器上提示没有解析到content length,目前在github上已提bug了.

本博客已稳定运行
发表了26篇文章 · 总计45.09k字
本站总访问量 次 · 您是本站第 位访问者
粤ICP备2025368587号-1| 使用 Hugo 构建
主题 StackJimmy 设计