Featured image of post freeswitch 负载均衡分发

freeswitch 负载均衡分发

背景

kamailio,opensips分别有dispatcher,load_balancer模块来实现sip信令负载均衡和分发功能。 那么作为全能型的freeswitch,也有mod_distributor模块来实现该功能。

mod_distributor只支持invite不支持register请求的负载均衡和分发。官方文档

本次测试的freeswitch版本为:

1.10.7-release+git20211024T163933Z883d2cb662~64bit

测试

编译

freeswitch的源码编译目录下的文件modules.conf中取消注释:

1
applications/mod_distributor

重新编译源码,这样就能编译mod_distributor模块。

配置

  1. freeswitch运行路径下的conf/autoload_configs/modules.conf.xml中,加载mod_distributor模块:
1
<load module="mod_distributor"/>
  1. conf/autoload_configs/distributor.conf.xml中,配置分发策略, 原始示例内容为:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<configuration name="distributor.conf" description="Distributor Configuration">
  <lists>
    <!-- every 10 calls to test you will get foo1 once and foo2 9 times...yes NINE TIMES! -->
    <!-- this is not the same as 100 with 10 and 90 that would do foo1 10 times in a row then foo2 90 times in a row -->
    <list name="test">
      <node name="foo1" weight="1"/>
      <node name="foo2" weight="9"/>
    </list>
  </lists>
</configuration>

修改配置为:

1
2
3
4
5
6
7
8
<configuration name="distributor.conf" description="Distributor">
  <lists>
    <list name="2gw" total-weight="2">
      <node name="gw1" value="sofia/gateway/gw1" weight="1"/>
      <node name="gw2" value="sofia/gateway/gw2" weight="1"/>
    </list>
  </lists>
</configuration>

可以通过调整weight值来改变分发策略,总数之和为total-weight

  1. conf/sip_profiles/external/中,参考example.xml,分别创建两个网关文件:gw1.xml,gw2.xml

一个转到172.16.4.113上,一个转到172.16.4.114上。gw1.xml的示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<include>
  <gateway name="gw1">
  <param name="realm" value="172.16.4.113:5060"/>
  <param name="expire-seconds" value="60"/>
  <!--/// do not register ///-->
  <param name="register" value="false"/>
  <!-- which transport to use for register -->
  <param name="register-transport" value="udp"/>
  <!--How many seconds before a retry when a failure or timeout occurs -->
  <param name="retry-seconds" value="30"/>
  <!--Use the callerid of an inbound call in the from field on outbound calls via this gateway -->
  <param name="caller-id-in-from" value="true"/>
  <!--send an options ping every x seconds, failure will unregister and/or mark it down-->
  <param name="ping" value="25"/>
  </gateway>
</include>

这里配置了ping功能,25秒检测一次网关是否可用,用于后面dead gateways功能测试。

  1. conf/dialplan/default.xml中, 配置拨号计划, 示例内容为:
1
2
3
4
5
6
7
<extension name="3-way gateway distributor"> 
  <condition field="destination_number" expression="9980$"> 
    <action application="set" data="continue_on_fail=true"/> 
    <action application="set" data="hangup_after_bridge=true"/> 
    <action application="bridge" data="sofia/gateway/${distributor(2gw)}/1004" loop="2"/> 
  </condition> 
</extension>
  1. 重启服务

运行

软电话A1003注册到上面设置的拨号计划的sip服务器172.16.4.111上, 软电话B和C用户1004分别注册到172.16.4.113(gw1)172.16.4.114(gw2)sip服务器上。

然后A软电话拨打9980号码, 此时会拨打gw1上,如果gw1有该坐席,不管是接通还是挂断, 都不会再拨打gw2上的1004用户。但是如果在gw1INVITE返回了错误的信令, 则会拨打gw2上的1004用户。

正常的信令图: 正常的信令图

gw1失败,gw2成功: gw1失败,gw2成功

正常情况会按照轮询策略来分发invite请求。 轮询策略

可以看到,第一通电话转gw1,第二通电话转gw2,第三通电话转gw1,依次轮询。

如果其中一个网关不通,能否不再往该网关发送invite请求呢?

也是可以的,使用dead gateways,修改conf/dialplan/default.xml中, 配置拨号计划, 示例内容为:

1
2
3
4
5
6
7
8
9
<extension name="3-way gateway distributor"> 
  <condition field="destination_number" expression="9980$"> 
    <action application="set" data="continue_on_fail=true"/> 
    <action application="set" data="hangup_after_bridge=true"/> 
    <action application="bridge"
        data="sofia/gateway/${expand(distributor 2gw ${sofia(profile external gwlist down)})}/1004"
        loop="2"/>
  </condition> 
</extension>

停掉gw1网关,当看到日志[WARNING] sofia.c:6503 Ping failed gw1 with code 503 - count 1/0/1, state DOWN, 然后A软电话拨打9980号码, 此时只会拨打gw2上的1004用户。

可以看到信令交互上,确是如此。 gw1失败,gw2成功

总结

  1. mod_distributor只能使用简单的轮询权重策略来分发invite请求。
  2. 使用网关的功能,可以自动检测到下线的网关,然后不再往该网关发送invite请求。
本博客已稳定运行
发表了72篇文章 · 总计126.91k字
本站总访问量 次 · 您是本站第 位访问者
粤ICP备2025368587号-1| 使用 Hugo 构建
主题 StackJimmy 设计