您当前的位置是:  首页 > 资讯 > 国内 >
 首页 > 资讯 > 国内 >

opensips学习笔记-关于stateless和stateful 模式讨论和retransmissions演示

2021-01-05 10:19:05   作者:james.zhu    来源:Asterisk开源派   评论:0  点击:


  在SIP协议中针对UAS有两个非常关键的定义stateless和stateful模式。笔者在以前的历史文章中多次通过各种方式做了一些比较粗浅的介绍,为了更进一步了解其具体应用的场景和语法,笔者再次结合一些非常基础的概念和重传示例来帮助读者了解stateless(无状态)和stateful(有状态)模式。首先,我们了解一下有状态和无状态代理在SIP协议规范中的定义。RFC3261-16.11 定义了关于Stateful Proxy的细节,具体说明如下:
  When stateful, a proxy is purely a SIP transaction processing engine.
  Stateful  模式下,opensips会保持所有transaction 事务状态的消息内容,所有消息会存储在内存中。因此,当然,有状态模式会消耗大量的系统资源。
  RFC3261-16.2定义了关于Stateless Proxy的细节:读者可以参考:SIP协议规范RFC3261中文分享-12
  1state是什么意思?
  根据前面的介绍,我们知道,其实这个state是针对transaction 来定义的。那么,transaction又是什么意思呢?关于transaction 建议读者参考:
  Kamailio/OpenSIPS学习笔记-SIP相关基础
  SIP讲座系列-各种SIP服务器介绍
  实际上,我们在前面的文章中已经使用了opensips的transaction 模块,包括
  Kamailio/OpenSIPS学习笔记-如何测试SIP 408响应超时,调用了$T_fr_timeout等变量。opensips中的tm 模块是一个非常重要的模块,支持的配置功能也非常灵活,相对比较复杂。因为篇幅关系,这里不再做太多介绍。
  实话说,stateless 目前生产环境中没有看到太多的应用场景。在某些环境可能被使用,例如,作为一个SBC,SIP发起方可能对SIP服务器端不断发送option消息验证其是否是存活状态,OpenSIPS可以设置为一个stateless状态,检测到是option以后,然后丢弃。很多时候,如果用户ping 运营商的SBC的话,为了防止系统过载,SBC可能没有返回任何消息。
  Stateful 模式是SIP UAS或者proxy主要的应用场景。它可以支持SIP呼叫场景基本上所有必要的相关应用, 例如,处理重传,失败路由处理,定时器调整,NAT转换处理,CDR/计费,CANCELs和ACKs消息的路由管理等。我们花费一点时间重点介绍在有状态模式下的处理流程。
  2OpenSIPS中stateless和stateful的两种状态
  首先读者一定要明确,默认环境下,opensips是以stateless 状态启动的。在stateless模式下,opensips通过core 模块提供SIP的信令功能,具体的函数包括forward()和sl_send_reply()。stateful模式的函数功能由transaction module提供,包括t_relay()和t_reply()。绝大部分的应用环境中,opensips是在有状态的模式下工作的,但是,默认opensips启动时又是一个无状态的模式,如果opensips需要从stateless切换到stateful 状态的话,opensips需要通过调用事务模块的函数从无状态模式切换到有状态模式。接下来,笔者介绍一下从无状态模式切换到有状态模式的两种方式。
  3启动stateful状态的两种方式
  启动opensips的有状态模式可以通过以下两种方式。一种是手动通过明确的外部调用函数-t_newtrans()的方式来启动opensips的有状态模式; 另外一种是自动启动的方式,通过t_relay()和t_reply()函数来自动启动有状态模式。
  这里,读者需要注意,前一种方式是对请求创建了一个事务状态,但是它执行的是无SIP信令处理;后一种方式是如果没有创建有状态模式事务的话,它们会自动创建一个事务,并且执行SIP 信令操作。
  4retransmissions测试示例
  retransmissions是SIP网络环境中经常遇到的一个问题。如果opensips要处理retransmissions的话,opensips需要在有状态模式中进行处理。retransmissions支持两种retransmissions,一种是incoming 请求的检测和重新传输; 入局的请求通过检测可以再进行处理,否则的话,重传流程可能进入到其他的cfg脚本中,或者查询数据库等流程,这样就会耗费更多的系统资源。因此,opensips进行重传检测是非常必要的,如果发现是一个重传递请求,则系统可能直接回复相关的响应即可。另外一种retransmissions基本上是针对被呼叫方来进行的,opensips获得被呼叫方的回复以后再进行其他的业务流程处理。
  为了演示如何使用t_new_tran(),这里,我们提供重传的示例演示,呼叫入局时,如果检测到一个不存在的地址以后,如何进行重传处理。具体的配置步骤如下:
  首先,需要在cfg文件中加载-loadmodule "cfgutils.so" 模块。
  添加cfg脚本处理流程:
  ## requests for my domain
  if (is_method("PUBLISH|SUBSCRIBE")) {
  send_reply(503, "Service Unavailable");
  exit;
  }
  if ($rU==NULL) {
  # request with no Username in RURI
  send_reply(484,"Address Incomplete");
  exit;
  }
  #发送呼叫1002到地址 地址1.1.1.1
  if ($rU=="1002") {
  #设置request uri是 1.1.1.1
  $rd="1.1.1.1";
  t_relay();
  exit;
  }
  // 创建一个新的事务,切换到有状态模式。
  t_newtran();
  #进行呼叫,休眠2秒钟。
  if(is_method("INVITE")) {
  sleep(2);
  }
  以上脚本中,我们伪造了一个不存在的地址是1.1.1.1。使用一个SIP 终端呼叫另外一个终端1002的话,这里的目的地地址是一个不存在的地址,用户可能感觉到呼叫流程相对比较慢,因为在呼叫中添加了一个休眠时间。
  5总结
  在本文章中,笔者讨论了关于opensips中关于UAS的两种状态的具体使用方式和函数调用,以及价格应该注意到示例语法。首先,笔者介绍了stateless和stateful的基本区别,以及各自的应用场景,包括函数调用方式。接下来,笔者主要重点介绍了在无状态启动的情况下,opensips如何切换为有状态模式环境,以及两种切换方式和各自的不同。最后,笔者通过retransmissions的应用场景介绍了如何使用 t_newtran()实现opensips从无状态模式切换到有状态模式的示例,通过一个示例说明opensips如何在有状态环境中对入局呼叫进行处理。
  参考资料:
  https://opensips.org/html/docs/modules/1.8.x/tm.html
  www.freesbc.cn
  www.asterisk.org.cn
  
【免责声明】本文仅代表作者本人观点,与CTI论坛无关。CTI论坛对文中陈述、观点判断保持中立,不对所包含内容的准确性、可靠性或完整性提供任何明示或暗示的保证。请读者仅作参考,并请自行承担全部责任。

专题

CTI论坛会员企业