背景介绍
kamailio 的dispatcher模块提供负载均衡功能,可以采用轮询,负载上的权重,通话负载分发和哈希方式。
该模块比较轻量,适合高并发场景。但是不能分发REGISTER
请求。
它和opensips
的dispatcher
不一样,opensips的dispatcher
可以分发REGISTER
请求。
它更像是opensips的load_balancer
。
这个模块既可以使用数据库,也可以使用文件来配置。官方文档地址:dispatcher
kamailio的版本:
version: kamailio 5.8.5 (x86_64/linux)
重要参数解析
|
|
重要函数
ds_select_dst(set, alg[, limit])
从地址集中选择一个地址,然后把地址设置到$du
,
- set
表dispatcher的
setid
- alg
负载均衡算法,可多个叠加:
- “0”: 哈希
callid
- “1”: 哈希
from URI
- “2”: 哈希
to URI
- “3”: 哈希
request-URI user
- “4”: 轮询
- “5”: 哈希
authorization-username
,如果没有此字段,使用轮询
- “6”: 随机
- “7”: 哈希
PVs
,必须设置hash_pvar
- “8”: 使用
dispatcher
表里按照priority
排序的gateway - “9”:
权重分发
,使用dispatcher
表里按照weight
排序的gateway - “10”: 使用
通话负载分发
,必须设置ds_hash_size
和dispatcher
表的attrs
添加duid
,速度很快 - “11”: 使用
相对权重分发
,dispatcher
表的attrs
添加rweight
, 相对于权重分发
,如果有gateway不活跃了,每次会重新计算权重 - “12”: 分发所有节点
- “13”: 延迟分发
ds_ping_latency_stats
, 使用的是轮询分发
- “0”: 哈希
ds_next_dst()
获取下一个地址,并设置$du
。
ds_set_dst()
把当前的地址设置为$du
。
ds_select_domain(set, alg[, limit])
从地址集中选择一个地址,然后重写R-URI
里的host
和Port
,其他参数和ds_select_dst
一致。
ds_next_domain()
获取下一个地址,并设置R-URI
。
ds_set_domain()
把当前的地址设置为R-URI
。
ds_select(set, alg[, limit])
从地址集中选择一个地址,存在XAVP变量里,不会重写R-URI
和$du
ds_select_routes(rules, mode [, limit])
按照规则从地址集中选择一个地址
- rules
匹配规则,格式为
grp1=alg1;grp2=alg2
- mode
选择的地址推到哪里
- ‘0’,’d’,‘D’: 修改$du
- ‘1’,‘r’,‘R’: 修改R-URI
- ‘2’,‘x’,‘X’: 存储在XAVP变量
ds_mark_dst([state])
标记上次使用的地址状态
- state
- “a”,“A”: 活跃状态
- “i”,“I”: 非活跃状态
- “t”,“T”: 尝试状态
- “p”,“P”: 可探测状态
实战
本次测试的场景是:
- 软电话1008注册到freeswitch A(
172.18.11.187
)上, A配置网关转发请求到kamailio (172.16.4.111
) - 1008拨打1003, kamailio(
172.16.4.111
)收到请求, dispatcher分发给freeswitch B(172.16.4.113
)或 freeswitch C(172.16.4.114
) - 两个软电话分别向freeswitch B和freeswitch C注册1003
- B或者C收到请求,拨打软电话,电话接通
从文件读取
- dispatcher.list
|
|
这里要介绍一下attributes
参数:
- class=4 接受错误码为400~499的响应
- strip=3 从被叫号码(R-URI)中去除前3位
- prefix=86 在被叫号码(R-URI)前加上86
- duid=abc 唯一标识目标节点
- maxload=30 最大负载值,超过则拒绝
- weight=5 1~100,权重,总和为100,权重越大,请求越多
- rweight=5 1~100,相对权重,总和为100
- socket=udp:127.0.0.1:5060
定义分发请求的socket,覆盖
ds_default_socket
- socketname=xxx 定义分发请求的socket name
- ping_from
定义ping的
From
URI,覆盖ds_ping_from
- obproxy
- latency
- 配置示例:
|
|
测试效果
ping
kamailio 分别往两个节点发送OPTIONS
请求
- 172.16.4.113机器:
- 172.16.4.114机器:
正常拨打电话
可以看到
ds_select_dst
配置的是轮询
,所以不管第一通172.16.4.113
是否接通,第二通都会转到172.16.4.114节点
注意: 一定不要配置modparam("dispatcher", "use_default", 1)
, 否则不管配置的策略是什么,都只会往一个节点发送请求。
当其中一个节点停掉
停掉172.16.4.113
节点的freeswitch,在dispatcher
未标记此节点为非活跃状态
之前,请求还是会发往此节点的。
dispatcher
标记172.16.4.113
状态为非活跃状态
之后,所有的请求只会转到172.16.4.114
节点。
存在的问题
dispatcher
模块目前没有找到配置可以让服务一启动就开始ping
节点。
这就会导致服务启动后,在ping
的定时器开始之前,如果有请求过来,不会分发请求。
当然可以缩短ds_ping_interval
间隔,但是这样的话,ping
的频率会变高。