您当前的位置是:  首页 > 资讯 > 文章精选 >
 首页 > 资讯 > 文章精选 >

OpenSIPS学习笔记-dispatcher调度模块概要-失效呼叫处理逻辑及示例演示

2021-03-01 09:21:29   作者:james.zhu    来源:Asterisk开源派   评论:0  点击:


  根据OpenSIPS官方对OpenSIPS的定义,OpenSIPS或者Kamailio可以支持SIP软交换环境中的各种灵活的路由机制,就是我们通常使用的模块包括dispatcher和loadbalance模块。网上有各种对这两个模块的具体定义和说明,也包括其中文概念。在大部分的中文称谓中,我们将dispatcher 翻译为调度,loadbalance翻译为负载均衡。这里,为了方便使用,我们也使用这样的称谓。本人不是英文翻译人员,关于以上中文称谓是否正确,我们不做讨论。我们仅针对其具体使用进行分享。很多刚刚进入到IP领域的读者可能会对OpenSIPS中的dispatcher和loadbalance有一些误解,这种误解可能导致在部署OpenSIPS和其他第三方媒体服务器方面产生很多的疑问,也浪费了很多时间。另外,一些用户因为对这两个模块的功能了解不足,在后续的拓展支持和其更高级功能的处理上难以对其实行控制,导致很多项目部署的失控。为了更加明确dispatcher和loadbalance的使用场景和其潜在的应用风险,我们重点对diapatcher的概念,以及dispatcher和loadbalance的区别,dispatcher的使用以及dispatcher的呼叫失败处理,以及dispatcher模块配置示例做一个完整的分享。在后续章节中,笔者将对loadbalance的使用示例做更多分享。
  因此,在本文章的分享中,笔者将介绍dispatcher的基本概念,以及它和loadbalance的区别,dispatcher的处理以及呼叫失败处理逻辑处理和dispatcher配置示例做详细说明。
  OpenSIPS/Kamailio/媒体服务器路由调度模块集成示例
  说明:在配置示例的讨论中,笔者将使用dialpaln模块, drouting和其他的路由辅助模块和OpenSIPS的控制界面做必要的配置来实现调度功能示例演示,所以,用户如果需要实现调度功能示例的话,用户必须首先安装配置环境。
  除了使用开源OpenSIPS或者Kamailio的调度模块以外,用户可以选择freesbc作为一个媒体服务器的前端对呼叫进行路由调度处理。
  1、OpenSIPS的dispatcher模块的基本概念
  OpenSIPS也称为软交换。既然是软交换的话,它必须具备一定的dispatcher的调度功能。简单来说,dispatcher的调度可能主要是实现对呼叫进行呼叫目的地的调度管理。通过呼叫请求结合目的地选项实现呼出代理的路由管理。调度模块通过权重设置对呼叫目的地进行设置。实际上,调度模块可以实现一个无状态的负载均衡机制,它不会保证其最终路由结果。因此,调度模块实现的是一个简单的呼叫分发功能,不涉及呼叫最终结果的处理。关于dispatcher的完整描述,用户可以参考官方文档关于dispatcher的说明。
  2、dispatcher和loadbalance的区别
  前面笔者已经说明,在使用OpenSIPS时,很多用户仍然对调度和负载均衡有一些迷惑和误解。调度模块和负载均衡模块有一个共同之处-它们都是对呼叫进行分发处理。因为这个共同之处所以导致用户对两个模块的错误理解。这里,笔者简单介绍一下dispatcher和loadbalance的区别。它们两者之间有比较大的区别:
  Dispatching/调度:
  • 无负载目的地端任何信息,仅直接分发
  • 仅通过peer做一个概率性的数据路由分发
  • 假设所有目的地端是确定的,包括目的地端是正常工作状态
  • 处理速度快,无需获得返回消息,完全是一种“盲”或者无状态的处理
  Loadbalance/负载均衡:
  • 基于dialog模块,可对目的地端负载计数
  • 因为支持能力不同,目的地端可能完全不同(例如,媒体能力,业务功能不同)
  • 可收到目的地端的返回消息
  • 对目的地端无任何侦测的要求
  3、Dispatcher 其他讨论
  用户需要启用Dispatcher的话,它和其他的模块一样,也同样需要加载一些必要的参数和支持模块。具体的语法这里不再介绍,官方有完整的语法说明。笔者这里想介绍几个使用dispatch模块时几个特别需要说明的地方。
  针对呼叫目的地的调度路由,dispatcher 模块可以支持几种不同的路由方式,用户可以根据自己的业务场景来设置不同的路由:
  • 可以通过SIP URLS定义来进行路由
  • 可以通过组设置来进行路由
  • 在组设置中可以支持不同权重来定义调度路由
  • 可以通过MI CLI命令关闭/开启目的地组
  • 可以通过组设置中的优先级顺序来实现路由
  • 可以通过属性字符串的标识来定义路由
  针对dispatcher模块的数据处理,OpenSIPS支持的是实时的数据存储方式。路由目的地通过数据库存储的方式进行设置。数据库数据在OpenSIPS启动时加载的内存中的,在系统运行中不会再访问数据库获取数据。如果用户需要重新加载数据的话,可以通过MI CLI命令执行ds_reload 来实现数据加载。比较新的OpenSIPS版本(官方推荐使用2.3)可以支持针对dispatcher的数据实现分区的功能,调度模块的表可以和多个数据库资源进行访问支持。数据分区的功能目前支持dialplan,dispatcher和drouting。dispatcher模块可以同时对两种不同的业务场景实现不同的数据库访问来获取调度业务所需要的数据,具体cfg操作方式如下:
  modparam("dispatcher", "partition",
  "vprov:
  db_url = mysql://oss:oss@10.0.0.10/oss;
  table_name = dispatcher;
  attrs_avp = $avp(vprov_attr);")
  modparam("dispatcher", "partition",
  "pbx:
  db_url = postgres://admin:admin@192.168.10.10/opensips;
  table_name = dispatcher;
  attrs_avp = $avp(ds_media_attr);")
  在OpenSIPS平台中,Dispatcher路由可以支持多种方式(10种),这些方式也非常灵活。调度模块可以根据不同的业务场景执行不同的路由。dispatcher模块可以支持通过hash table的路由,也可以支持round-robin的路由方式。一般情况下,如果没有特别的业务要求,很多用户使用round-robin的方式。
  但是如果需要针对SIP用户限定等特别的业务功能支持的话,用户需要使用hash table来实现不同的路由。一些非常常用的场景也必须通过hash table方式来实现,例如:
  一个SIP用户的所有注册终端必须能够注册到同一注册服务器peer端,一般情况下,系统也不允许出现不同的注册目的地地址。
  SIP 用户如果呼叫的话,所有它们的呼叫始终呼叫到同一服务器目的地端。
  针对媒体会议服务器的端路由中,对每个会议服务器的会议室能够路由到正确的目的地端服务器地址
  在hash 表的路由中用户需要特别注意这些细微的区别, 通过不同的SIP 头确保其呼叫路由到正确的目的地:
  0-hash over callid-确保所有同一dialog的请求能够路由到同一目的地代理服务器。通过dialog中的callid来跟踪同一呼叫。
  • 1-hash over From URL-确保所有从同一用户发出的请求能够路由到同一代理服务器目的地。
  • 2-hash over To URL-确保一个AOR的所有注册能够路由到同一代理服务器地址。
  • 3-hash over Request-URL-确保所有对同一目的地的请求能够路由到同一目的地服务器
  为了满足会议服务器路由和其他正常语音呼叫的处理调度,可以通过Dispatch 脚本中针对具体会议服务器路由和正常路由进行处理的示例,使用了0和3参数设置:
  modparam("dispatcher", "db_ url",
  "mysql://opensips:opensipsrw@localhost/opensips")
  # 呼叫路由部分,仅支持初始INVITEs
  if ( $rU=~"^3[0-9][0-9]$") {
  # 呼叫到媒体服务器的电话会议室路由
  ds_selert_dst(l,3);
  # hash over RURI-3,组1
  }
  else {
  # 正常呼叫
  ds_select_dst(2, o);
  # hash over CalllD-0,组2;
  }
  t relayl();
  4
  Dispatcher 调度呼叫失效处理控制讨论
  Dispatcher模块实现的是一个非常简单的呼叫调度路由,dispatcher假设对端peer是正常状态,它本身不关心对端peer的呼叫是否成功或者失败。但是,在实际应用环境中,如果对端peer出现故障的话,用户如果使用了调度模块的话,系统仍然需要对peer进行检查,否则,系统对呼叫失去了控制。例如,对端媒体会议媒体服务器出现故障,如何对其进行检查等。那么,OpenSIPS 的dispatcher 模块如何实现对对端peer进行检测是一个非常重要的环节。OpenSIPS的dispatcher 模块可以通过一些几种方式对对端peer进行检测:
  • 无返回消息,例如可能是timeout 超时,peer出现故障。
  • 对端返回1xx,例如可能是媒体服务器没有足够的落地资源或者可用端口(例如,落地使用的FXO/E1端口正在被占用)。
  • 返回5xx消息,peer服务器内部错误
  • 返回6xx消息,可能是全局网络失败
  • 返回4xx消息,可能是其他能力支持问题,例如编码转换或者落地端口被占用,拥塞等。
  在dispatcher使用时,可以通过失败路由检测到脚本对peer进行检测,具体的cfg示例如下:
  failure_ route[ds_failed] {
  if(t_check_status( "[56][0-9][0-9]") ||
  # 对端 peer 错误
  (t_local_replied("all") &&t_check_status("408")) ||
  # 本地 408 错误
  t_ check_ status("409") )
  # 其他错误
  # 执行失效呼叫处理
  ]
  Dispatcher对对端peer的检测完成以后,仍然需要呼叫失效处理的逻辑脚本对失效呼叫进行二次处理,然后进行目的地状态更新以后的呼叫。针对OpenSIPS的dispatcher(负载均衡类似)失效处理的算法大概需要经过以下六个步骤:
  通过ds_select 获取一个初始对端peer的组顺序
  从路由组中选择第一个路由peer
  对可用的第一个目的地peer发送request请求
  如果检测到失败的话,对此peer做一个失败标识,关闭此peer,继续查询下一个可用的peer
  使用下一个peer,然后添加到branch中执行serial forking处理
  重复第三步
  根据以上流程,dispatcher的失效呼叫脚本处理流程示例如下:
  # dispatch的呼叫失效
  route[do_dispatching] {
  if(!ds_select_dst(2,0)){
  # 所有 calllD 跟踪
  send_reply(503,"Servlee Unavallable");
  exit;,
  t_on_failure("ds_failover");
  t relay();
  }
  failure route[ds_failover]{
  If (failure_condition) {
  ds_mark_dst);  # step 3
  #避免下一次再次选择此peer,标识为失败peer
  If(!ds_next_dst()){
  t_reply(503,"Servlce Unavallable");
  exit;
  }
  t_on_failure("ds fallover");
  t_relay() #必须对前面的relay重新发出告警
  }
  }
  笔者应该注意,以上的处理方式仅说明在使用dispatcher 模块时,opensips的呼叫失效的处理逻辑。mark的策略也可以做一定的调整,例如,检测到的参数,如果达到3次以上,就标识为一个关闭的peer。另外,marked peer也可以通过一定的周期性检测,超时设置重新激活其检测状态。当然,如果用户也可以在对端peer侧来设置基于自己业务层面的呼叫失效的处理流程。例如,如果对端是一个会议系统或者其他的媒体服务器的话,如果呼叫的终端出现异常,本身媒体服务器端也可以设置其他的策略来执行呼叫失效,例如,设置一个分机随行,呼叫其他的终端,或者转入语音邮箱等方式。
  OpenSIPS的dispatcher 模块可以支持多种对SIP对端peer的状态进行探测。此功能的使用方式和drouting类似。另外,MI CLI命令可以对ds_list 执行状态检测,包括活动状态,非活动状态和正在探测状态。MI CLI命令也可以对目的地状态进行管理,用户可以使用ds_set_state 进行修改。
  5、OpenSIPS的dispatcher/调度配置示例
  根据以上的讨论,笔者在此章节介绍一个使用调度模块配置动态路由的配置示例。在配置dispatcher模块之前,和其他的模块配置一样,用户需要修改cfg配置文件,加载必要的模块和参数,然后修改dispatch的路由设置,最后通过控制界面添加dispatcher的路由设置,重新启动OpenSIPS实现调度模块和呼叫失效设置。此示例中,前端是一个OpenSIPS,两个对端peer是媒体服务器。
  首先修改cfg配置文件,添加必要的参数设置和模块:
  loadmodule "dispatcher.so"
  modparam("dispatcher","db_url",
  "mysql://opensips:opensipsrw@localhost/opensips")
  modparam("dispatcher", "ds_ping_interval", 30)
  modparam("dispatcher", "ds_ping_from", "sip:ds@sip.domain.com")
  modparam("dispatcher", "ds_probing_threshhold", 1)
  然后修改to_media 逻辑块,实现调度处理:
  route[to_media] {
  xlog("routing to media servers via dispatcher\n");
  if (!ds_select_dst(1, 2,"f")) { # over To URI
  send_reply(500,"No route to Media");
  exit;
  }
  xlog("Using media server $du (RURI=$ru) \n");
  t_on_failure("media_failover");
  t_relay();
  exit;
  }
  添加一个对媒体服务器呼叫失效的处理逻辑:
  failure_route[media_failover] {
  if (t_was_cancelled()) exit;
  if ( t_check_status( "[56][0-9][0-9]" ) ||
  (t_local_replied("all") && t_check_status("408"))) {
  # 媒体服务器呼叫失效,标识为失败状态
  xlog("Media server routing failed with reply $T_reply_code\n");
  ds_mark_dst("p");
  # 如果有可用的媒体服务器,尝试另外一个媒体服务器
  if (!ds_next_dst()) {
  xlog("no more media servers available\n");
  t_reply(503,"Service Unavailable");
  exit;
  }
  # 发送呼叫到新的媒体服务器
  xlog("Trying the new $du media server\n");
  t_on_failure("media_failover");
  t_relay();
  }
  }
  重新启动OpenSIPS,然后登录OpenSIPS控制界面,添加修改的目的地地址和组设置。通过dispatcher菜单添加不同的两个媒体服务器地址。添加以后,重新刷新界面。如果对端设置正常的话,dispatcher模块会看到活动的peer状态。
  添加好dispatcher模块数据以后,用户可以进行呼叫测试。在呼叫测试时,用户同时还要需要添加dialplan来实现对拨号的控制,按照自己的设置,通过终端进行拨号测试。参数方式如下:
  如果同一号码,正常情况下,此终端的呼叫会一直在路由到同一媒体服务器。关闭另外一个调度路由设置,通过终端重新进行呼叫,检测呼叫是否可以正常通过。
  修改第一个路由的peer地址,修改为一个127.0.0.2,测试呼叫,强制呼叫失效处理,检查返回的消息。
  关闭其中一个媒体服务器或者在媒体服务器侧进行拨号规则修改,终端检查返回的SIP消息。
  通过以上不同的测试流程,OpenSIPS的调度模块的脚本处理产生不同的peer状态消息,用户可以通过MI CLI命令来检查其状态。如果一切配置成功的话,可以看到界面的演示是返回失效呼叫的逻辑的。
  6、总结
  在本文章中,笔者首先介绍了调度模块的一些简单比较知识,然后强调了几个调度模块和负载均衡模块的不同。接下来,笔者介绍了调度路由中特别需要关注的几个参数和其非常具体的应用场景。为了保证调度模块的完整实现,调度路由需要呼叫失效的处理,笔者又介绍了dispatcher中关于呼叫失效的处理机制和六个步骤,同时分享了cfg配置的逻辑脚本。最后,笔者分享了一个关于OpenSIPS的dispatcher模块的使用示例,在示例中,列出了具体的加载模块的代码和界面相关配置,并且提示用户如何使用SIP终端对dispatcher模块进行测试。
  通过本文章的介绍,笔者相信用户可能对OpenSIPS的调度模块和负载均衡模块区别有了新的认识,同时也更加深入了解了调度模块的使用和其呼叫失效的管理逻辑。通过完整的调度路由策略,结合完整的调度失效控制机制来实现完整强大的dispatcher模块集成,并且保证了媒体服务器端的呼叫稳定性和SIP路由的完整处理。
  为了完整介绍OpenSIPS的路由处理,在后续关于OpenSIPS的学习笔记中,笔者将进一步介绍负载均衡中的路由处理处理。
  参考资料:
  https://opensips.org/html/docs/modules/2.3.x/dispatcher.html
  www.freesbc.cn
  www.freepbx.org.cn
  https://blog.opensips.org/2017/08/18/how-to-use-database-partitions-in-opensips/
  • 关于Asterisk文档,参考:www.asterisk.org.cn
  • 融合通信/IPPBX/FreePBX商业解决方案:www.hiastar.com
  • 最新Asterisk完整中文用户手册详解:www.asterisk.org.cn
  • Freepbx/FreeSBC技术文档: www.freepbx.org.cn
  • 如何使用免费会话边界控制器-FreeSBC,qq技术分享群:334023047
  • 关注微信公众号:asterisk-cn,获得有价值的通信行业技术分享
【免责声明】本文仅代表作者本人观点,与CTI论坛无关。CTI论坛对文中陈述、观点判断保持中立,不对所包含内容的准确性、可靠性或完整性提供任何明示或暗示的保证。请读者仅作参考,并请自行承担全部责任。

专题

CTI论坛会员企业