找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

3364

积分

0

好友

444

主题
发表于 昨天 20:54 | 查看: 3| 回复: 0

Kamailio 作为主流的开源 SIP 软交换,虽历经多年发展,但在 SIP 和 IMS 网络业务场景中依然举足轻重。其关键能力之一,便是在高并发环境中对 SIP 呼叫进行灵活的均衡负载处理。本文将围绕 Kamailio 的均衡负载模块,提供从安装、配置到实际测试的完整分享。

以下是基于本文配置所实现的 Kamailio 均衡负载测试示例(视频略)。

实际上,关于 SIP 协议相关的开源项目,我们已有诸多讨论,基本安装配置大多涉及过,甚至也介绍过基于 OpenSIPS 的均衡负载配置。感兴趣的朋友可以参考历史文档进行学习:Kamailio技术全解

相关文章回顾:

提醒:若您是商业用户,对开源产品并不熟练,且需要稳定可靠的均衡负载能力与专业的商业服务,建议考虑安装商业版 SBC。

实现 Kamailio 的均衡负载场景,用户需要完成几个关键步骤:配置数据库、设置调度模块的路由地址,以及在配置脚本中添加均衡负载的路由逻辑。在此过程中可能会遇到一些问题,例如 dispatcher 模块启动时的 DNS 解析错误,或者 kamctl dispatcher rm 命令无法删除 IP 地址的异常(疑似 bug)。本文的最后,我们将通过软电话呼叫 Kamailio 和媒体服务器,完成双向均衡负载的实际测试。

1. 安装 Kamailio 与 PostgreSQL 数据库

安装环境可以通过多种方式来实现,比如源代码编译、GUI 界面安装、或者软件包管理器直接安装。数据库方面,除 PostgreSQL 外,你也可以选择 MySQL。此处我们基于 Debian 环境,使用安装包的方式,因为这对大多数用户来说最为简单:

root@debian:~# apt install --yes kamailio kamailio-postgres-modules postgresql
Reading package lists... Done

安装完毕后,执行以下命令查看 Kamailio 的安装详情:

root@debian:~# kamailio -v
version: kamailio 5.6.3 (x86_64/linux)
flags: USE_TCP, USE_TLS, USE_SCTP, TLS_HOOKS, USE_RAW_SOCKS, DISABLE_NAGLE, USE_MCAST, DNS_IP_HACK, SHM_MMAP, PKG_MALLOC, Q_MALLOC, F_MALLOC, TLSF_MALLOC, DBG_SR_MEMORY, USE_FUTEX, FAST_LOCK-ADAPTIVE_WAIT, USE_DNS_CACHE, USE_DNS_FAILOVER, USE_NAPTR, USE_DST_BLOCKLIST, HAVE_RESOLV_RES, TLS_PTHREAD_MUTEX_SHARED
ADAPTIVE_WAIT_LOOPS 1024, MAX_RECV_BUFFER_SIZE 262144, MAX_URI_SIZE 1024, BUF_SIZE 65535, DEFAULT PKG_SIZE 8MB
poll method support: poll, epoll_lt, epoll_et, sigio_rt, select.
id: unknown
compiled with gcc 12.2.0

2. 检查端口监听状态

通过 kamailio -c 来检查配置并确认端口监听:

root@debian:~# kamailio -c
Listening on
             udp: 127.0.0.1:5060
             udp: 172.27.0.179:5060
             tcp: 127.0.0.1:5060
             tcp: 172.27.0.179:5060  // 绑定的网口地址
Aliases:
             tcp: debian.lan:5060
             tcp: localhost:5060
             udp: debian.lan:5060
             udp: localhost:5060

config file ok, exiting...

3. 配置 PostgreSQL 数据库

首先登录 PostgreSQL 并设置数据库密码。这里我们为了演示方便,使用较为简单的密码 test123

root@debian:~# sudo -u postgres -H psql
could not change directory to "/root": Permission denied
psql (15.5 (Debian 15.5-0+deb12u1))
Type "help" for help.

设置密码:

postgres=# \password
Enter new password for user "postgres": // 输入密码:test123
Enter it again:
postgres=#

接着,需要修改 PostgreSQL 配置文件以实现密码认证。在终端中,先用 ls 列出目录,然后使用 nano 编辑 pg_hba.conf 文件:

修改PostgreSQL客户端认证配置文件,将认证方法改为md5

在配置文件中,根据绿色文字“修改为md5”的提示,将相关连接项的认证方法调整为 md5

数据库配置文件内容,高亮显示将scram-sha-256/peer改为md5

修改完成后,重启 postgres 服务让配置生效:

root@debian:/etc/postgresql/15/main# systemctl restart postgresql

然后,创建数据库密码文件并赋予相应权限,以便 Kamailio 能通过密码访问数据库:

root@debian:~# vim ~/.pgpass
root@debian:~# chmod 600 ~/.pgpass

~/.pgpass 文件中,按照 主机名:端口:数据库名:用户名:密码 的格式填写。同时,也需要为 kamailio 用户对应的数据库配置连接信息:

编辑pgpass配置文件,录入localhost:5432:kamailio:kamailio:test123

接下来修改 Kamailio 的数据库配置文件 kamctlrc,将数据库引擎设置为 PGSQL,并填入相关的主机、端口、用户名和密码参数:

Kamailio控制工具配置文件,设置数据库类型为PGSQL及连接参数

配置完毕,创建 Kamailio 数据库:

root@debian:/etc/kamailio# kamdbctl create
-e \E[37;33mINFO: creating database kamailio ...
-e \E[37;33mINFO: Core Kamailio tables successfully created.
Install presence related tables? (y/n): y
-e \E[37;33mINFO: creating presence tables into kamailio ...
^[a-e \E[37;33mINFO: Presence tables successfully created.
Install tables for imc cpl siptrace domainpolicy carrierroute
                drouting userblocklist htable purble uac pipelimit mtree sca mohqueue
                rtpproxy rtpengine secfilter? (y/n): y
-e \E[37;33mINFO: creating extra tables into kamailio ...
-e \E[37;33mINFO: Extra tables successfully created.
root@debian:/etc/kamailio#

重新启动 Kamailio 并使用 kamcmd 进入 CLI 后台查看运行状态,确认各子进程启动正常:

systemctl restart kamailio
root@debian:/etc/kamailio# kamailio -c
Listening on
             udp: 127.0.0.1:5060
             udp: 172.27.0.179:5060
             tcp: 127.0.0.1:5060
             tcp: 172.27.0.179:5060
Aliases:
             tcp: debian.lan:5060
             tcp: localhost:5060
             udp: debian.lan:5060
             udp: localhost:5060

root@debian:~# kamcmd
kamcmd> tm.stats
{
        current: 0
        waiting: 0
        total: 0
        ...
}

4. 呼入均衡负载配置

在 Kamailio 的配置脚本中,均衡负载的逻辑通常放在自定义路由块中。以下是一个典型的呼入处理片段,当接收到10位号码的 INVITE 时,调度器会从组 1 中选择一个网关进行路由:

#!ifdef WITH_VOICEMAIL
    if(!is_method("INVITE|SUBSCRIBE")) return;

    # check if VoiceMail server IP is defined
    if (strempty($sel(cfg_get.voicemail.srv_ip))) {
        xlog("SCRIPT: VoiceMail routing enabled but IP not defined\n");
        return;
    }
    if(is_method("INVITE")) {
        if($avp(oexten)==$null) return;

        $ru = "sip:" + $avp(oexten) + "@" + $sel(cfg_get.voicemail.srv_ip)
                + ":" + $sel(cfg_get.voicemail.srv_port);
    } else {
        if($rU==$null) return;

        $ru = "sip:" + $rU + "@" + $sel(cfg_get.voicemail.srv_ip)
                + ":" + $sel(cfg_get.voicemail.srv_port);
    }
    route(RELAY);
    exit;
#!endif

    return;
}
// load balance, 均衡负载处理,仅支持十位数号码呼入,然后路由到其他媒体服务器
route[DISPATCHER]{
# only dispatch if the number has 10 digits
    if(!($rU处理)) {
        return;
    }
    # round robin dispatcher on gateways group '1'
    if(!ds_select_dst("1","4")) {
        send_reply("404","No destination");
        exit;   
    }
    xlog(" -- DISPATCH: Going to <$rU> via <$du>\n");
    route(RELAY);
    exit;
}

# Manage outgoing branches
branch_route[MANAGE_BRANCH] {
    xdbg("new branch [$T_branch_idx] to $ru\n");
    route(NATMANAGE);
    return;
}

# Manage incoming replies

完成脚本配置后,使用 kamailio -DE 进行前台调试运行,检查 dispatcher 模块的加载情况。如果数据库中没有路由数据,会看到 no dispatching data in the db 的警告。

接着,通过 kamctl dispatcher 命令添加媒体服务器的地址。例如,向组 1 中添加两个媒体服务器:

root@debian:/etc/kamailio# kamctl dispatcher add 1 sip:freepbx1.kamailio.org:5080 0 0 "" "media server 1"
-e pgsql_query: /usr/bin/psql  -A -q -t -P fieldsep='   ' -h localhost -U kamailio kamailio -c 'insert into dispatcher   (                                                       setid, destination, flags, priority, attrs, description )                     VALUES (1,'sip:freepbx1.kamailio.o                                                      rg:5080',0,0,'','media server 1');'

root@debian:/etc/kamailio# kamctl dispatcher add 1 sip:freepbx2.kamailio.org:5060 0 0 "" "media server 2"
-e pgsql_query: /usr/bin/psql  -A -q -t -P fieldsep='   ' -h localhost -U kamailio kamailio -c 'insert into dispatcher                          ( setid, destination, flags, priority, attrs, description )                     VALUES (1,'sip:freepbx2.kamailio.org:5060',0,0,'','media server 2');'

root@debian:/etc/kamailio# kamctl dispatcher show
-e dispatcher gateways
1|1|sip:freepbx1.kamailio.org:5080|0|0||media server 1
2|1|sip:freepbx2.kamailio.org:5060|0|0||media server 2

故障排查:DNS 解析错误

kamctl dispatcher reload 或 Kamailio 启动时出现“could not resolve”之类的错误,通常是因为 dispatcher 模块无法解析你提供的域名。此时最简单的解决办法是直接使用 IP 地址。先删除原有的域名记录,再添加 IP:

root@debian:~# kamctl dispatcher rm 1
root@debian:~# kamctl dispatcher rm 2
root@debian:~# kamctl dispatcher add 1 sip:172.27.0.196:5080 0 0 "" "media server 1"
root@debian:~# kamctl dispatcher add 1 sip:172.27.0.105:5060 0 0 "" "media server 2"
root@debian:~# kamctl dispatcher reload
{
  "jsonrpc":  "2.0",
  "result": "Ok. Dispatcher successfully reloaded.",
  "id": 2973
}

5. 呼入测试

在两台媒体服务器(例如 FreePBX)上配置好分机并确保注册状态正常。

两台运行中的MicroSIP软电话界面,显示在线状态及号码

使用软电话(如 Zoiper5 或 MicroSIP)呼叫 Kamailio 的 IP 地址,号码必须符合配置中的位数规则(本例为10位)。

Zoiper5和MicroSIP正在进行VoIP通话,号码为3451234563,时长21秒

多次呼叫后,可以在截图和通话记录中看到,呼叫被均衡负载到了不同的媒体服务器上。

呼叫记录列表显示多个已接通的通话

通过 sngrep 工具抓包,能清晰地看到 SIP 信令交互流程。

SIP抓包分析界面,包含INVITE请求、180 Ringing、200 OK等信令

从分析图中可以看到,呼叫被路由到了不同的媒体服务器(IP 和端口各异),实现了预期的均衡负载效果。

另一组SIP信令流程,展示呼叫至不同媒体服务器

使用 kamcmdtm.stats 命令可以查看事务处理统计:

执行tm.stats后的统计数据输出

6. 呼出均衡负载配置

在某些场景下,例如最低资费路由或运营商流量分发,我们需要 IPPBX 将呼叫送至 Kamailio,再由 Kamailio 均衡负载到不同的运营商线路。配置逻辑与呼入类似,核心是向新的组(例如组 2)添加运营商地址:

root@debian:~# kamctl dispatcher add 2  sip:172.27.0.106 0 0 "" "Carrier server 1"
root@debian:~# kamctl dispatcher add 2  sip:172.27.0.107 0 0 "" "Carrier server 2"

kamctl dispatcher reload 重新加载后,通过 kamcmd dispatcher.list 可以看到组 2 的详细信息:

kamcmd> dispatcher.list
{
        NRSETS: 2
        RECORDS: {
                SET: {
                        ID: 2
                        TARGETS: {
                                DEST: {
                                        URI: sip:172.27.0.107
                                        FLAGS: AX
                                        PRIORITY: 0
                                }
                                DEST: {
                                        URI: sip:172.27.0.106
                                        FLAGS: AX
                                        PRIORITY: 0
                                }
                        }
                }
                SET: {
                        ID: 1
                        ...
                }
        }
}

故障排查:dispatcher rm 命令无效

如果kamctl dispatcher rm <id>命令无法删除记录,这可能是版本的一个小 bug。此时可以直接登录 PostgreSQL 数据库进行手动删除。

在终端操作数据库,手动删除dispatcher表中的记录

postgres=# \c kamailio
You are now connected to database "kamailio" as user "postgres".
kamailio=# delete from dispatcher where setid='2';
DELETE 3
kamailio=# SELECT * FROM dispatcher;
 id | setid |      destination      | flags | priority | attrs |   description
----+-------+-----------------------+-------+----------+-------+------------------
  3 |     1 | sip:172.27.0.196:5080 |     0 |        0 |       | media server 1
  4 |     1 | sip:172.27.0.105:5060 |     0 |        0 |       | media server 2
(2 rows)

删除后重新用 kamctl dispatcher add 添加即可。

测试呼出,可以看到第一次呼叫路由到了鼎信通达的 UC350 IPPBX(作为模拟的运营商节点),第二次则成功路由到了另一个运营商地址。

SIP抓包显示403 Forbidden,可能是测试运营商节点返回

SIP呼叫流程分析图,展示INVITE到另一个运营商地址的全过程

总结

本文详细介绍了 Kamailio 调度器(dispatcher)模块的使用,并通过一个完整的示例,演示了从环境搭建、数据库配置到双向呼叫均衡负载测试的全过程。相信读者可以基于自己的 IPPBX、分机注册等场景,部署出符合自己需求的负载均衡系统。

除去 dispatcher 模块,目的地地址与地址组的管理还可通过 permission 模块或其他自定义写入的方式实现。此外,用户也可以选择结合 Kamailio 管理界面与配置脚本来灵活控制。

@云栈社区 提醒您,负载均衡管理是一个系统性工程,它不仅涉及本文讨论的路由逻辑,还牵扯到号码位数匹配、IPPBX 呼入呼出路由设置、终端兼容性、运营商对接能力、编解码协商、NAT 穿越以及 DNS 解析等诸多因素。实际部署时,还需根据自己的业务场景进行更详尽、更有针对性的测试。




上一篇:舱驾融合下的区域控制器:连接、能量与控制的边缘三要素
下一篇:简历空窗期分三类,这样解释面试官很难拒绝
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-5-4 03:05 , Processed in 0.830828 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表