SIP代理、SIP集群和媒体集群调研

最近在调研SIP代理、SIP集群和媒体集群的能力,了解到OV500这个项目,对理解Freeswitch的能力,Kamailio作为信令代理的配置等实现的学习还是很有帮助的,这个GITHUB项目地址:OV500 , 架构模型如图:

呱牛笔记

OV500环境搭建如果是有外网的情况下,还是很快的,另外借助docker的方式,可以通过起3个容器快速完成上面的架构部署;

环境部署过程中,其实容易出现的问题就是遗漏了安装过程中提到的某步或者某几步,导致出现问题,所以需要很细心的配置,另外,出现问题了也能快速定位解决,出现了几个很低级的问题:

1、nginx代理php的管理用户和文件权限问题,需要将php程序包拷贝到/var/www路径下,不能使用/home,/usr等路径;

2、iptable没关,导致网络不通;


另外,OV500提供了强大的计费管理,话单管理,对理解完整的业务链条很有帮助,建议做VOIP业务后台的同学可以细致的分析这块的完整业务;


服务部署完后,需要通过OV500的管理后台(后台管理账户可以通过查表找到,admin/123456,文档中没有说明,所以需要全面的了解,然后就不会在某块被阻塞住)添加用户,这块如果英文不好还是很难加全的,因为需要添加计费,费率,企业和企业的用户,另外,要把一些包括codec检查的开关关掉,不然呼叫可能就不通,呼叫不通这快需要看Freeswitch的日志和kamailio的日志;


单个kamailio代理多个freeswitch时,freeswitch由于收不到ACK,导致30s自动挂断问题解决,主要通过升级kamailio 到5.3.3版本解决,原来的版本号是:4.4.6,调通一对一的语音通话和会议模式通话;

呱牛笔记


多个kamailio集群时,能进行语音通话,主要在freeswitch收到sip代理转发的呼叫后,通过location定位被叫用户在sip代理的位置,进行转接呼叫,调通呼叫;

修改OV500-master/portal/api/lib/OVS.php程序:
    function main($REQUEST) {
    
                $this->Hunt_Network_Addr = $this->request['Hunt-Network-Addr'];//在这行后面,主要修改这个地址为目标sip所在的kamailio服务器ip
        $this->Hunt_Network_PORT = 5063; 
        //update the target hunt network  
        $query = sprintf("select domain, contact, username, callid, socket from location where username = '%s';", $this->destination_number); 
        $this->writelog($query);
        $this->query('KAMAILIO', $query);
        $rs = $this->resultset();
        if (count($rs) >= 1) {
            $result = $rs[0];
            $socket_target = $result['socket'];//udp:11.12.117.200:5061
            //$index = strpos($socket_target, ':') ;
            $arr = explode(':', $socket_target);
            if (count($arr) == 3){
                $this->Hunt_Network_Addr = $arr[1];//substr($socket_target, $index + 1);   
                $this->Hunt_Network_PORT = $arr[2];
                $this->writelog("lyz get target, $this->Hunt_Network_Addr:".$this->Hunt_Network_PORT);
            }
        }else{
            $this->writelog("lyz get target, retun null");
	    }
        //ADD END.
        
    }
        
        代码中所有涉及bridge的地方进行替换修改:
        
        $this->Gateway_XML_incoming .= "\n <action application=\"bridge\" data=\"sofia/internal/" . $this->incomingcarrierdst . "@" . $lb . ":".$this->Hunt_Network_PORT. "\"/>";


会议模式的实现,会议号统一使用conf开头的前缀,在拨号计划生成的入口处,修改拨号计划的返回即可;

关键是下面两行:

       $this->Gateway_XML .= "\n<action application=\"answer\"/>"; 

       $this->Gateway_XML .= "\n<action application=\"conference\" data=\"".$this->destination_number."-" . $lb ."@default\"/>";    

修改OV500-master/portal/api/lib/OVS.php程序:
    function main($REQUEST) {
        //判断是否是会议模式,如果是,则直接返回报文就可以,会议模式以conf开头
        $index = strpos($this->destination_number, "conf_");
        if (false !== $index){
            $this->writelog("lyz add enter conference");
            $this->destination_number = substr($this->destination_number, $index + 5);

            $responce = $this->conferencecallxml(); 
            return $responce;
        }
         //add end
    }        
  function conferencecallxml() {
        $lb = $this->request['FreeSWITCH-IPv4'];//$this->Hunt_Network_Addr;  
        $this->Gateway_XML .= "\n <action application=\"set\" data=\"sip_h_X-MEDIATRA=1\"/>";
        $this->Gateway_XML .= "\n <action application=\"export\" data=\"sip_h_X-MEDIATRA=1\"/>";
        $this->Gateway_XML .= "\n<action application=\"set\" data=\"bypass_media=false\"/>";
        $this->Gateway_XML .= "\n<action application=\"set\" data=\"proxy-media=true\"/>"; 
        $route_callid = $this->uuid;

        $this->Gateway_XML .= "\n<action application=\"export\" data=\"effective_caller_id_number=" . $route_callid . "\"/>";
        $this->Gateway_XML .= "\n<action application=\"export\" data=\"effective_caller_id_name=" . $route_callid . "\"/>";
        $this->Gateway_XML .= "\n<action application=\"set\" data=\"effective_caller_id_number=" . $route_callid . "\"/>";
        $this->Gateway_XML .= "\n<action application=\"set\" data=\"effective_caller_id_name=" . $route_callid . "\"/>";
        $this->Gateway_XML .= "\n <action application=\"set\" data=\"sip_h_X-FROMURI=" . $route_callid . "\"/>"; 
        $this->Gateway_XML .= "\n<action application=\"set\" data=\"call_timeout=30\"/>";
        $this->Gateway_XML .= "\n<action application=\"set\" data=\"continue_on_fail=FALSE\"/>";
        $this->Gateway_XML .= "\n<action application=\"set\" data=\"hangup_after_bridge=true\"/>";  
        $this->Gateway_XML .= "\n<action application=\"set\" data=\"media_mix_inbound_outbound_codecs=true\"/>";  
        $this->Gateway_XML .= "\n<action application=\"answer\"/>"; 
        $this->Gateway_XML .= "\n<action application=\"conference\" data=\"".$this->destination_number."-" . $lb ."@default\"/>";   

 
        $responce .= "<?xml version = \"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
                            <document type=\"OvSwitch/xml\">";
                             
        $responce .= "<section name=\"dialplan\" description=\"RE Dial Plan For OvSwitch\">";
        $responce .= "\n<context name=\"default\">";
        $responce .= "\n<extension name=\"outbound_international\">
                <condition field=\"destination_number\" expression=\"^(.+)$\">";
        $responce .= "\n<action application=\"set\" data=\"SWITCH_ISSUE=0\"/>";
        $responce .= "\n<action application=\"export\" data=\"SWITCH_ISSUE=0\"/>";
        $responce .= "\n<action application=\"set\" data=\"hangup_after_bridge=TRUE\"/>";
        $responce .= "\n<action application=\"pre_answer\"/>"; 
        $responce .= "\n<action application=\"set\" data=\"common_uuid=" . $this->uuid . "\"/>";
        $responce .= "\n<action application=\"export\" data=\"common_uuid=" . $this->uuid . "\"/>";
        $responce .= "\n<action application=\"set\" data=\"caller_callid=" . $this->caller_callid . "\"/>";
        $responce .= "\n<action application=\"export\" data=\"caller_callid=" . $this->caller_callid . "\"/>";  
        $responce .= $this->Gateway_XML;
 
        $responce .= "\n
                </condition>
                    </extension>
                    </context>
                    </section>
                    </document>";


        RETURN $responce;
    }


通话建立不了可能和codec不匹配有关系,所以对freeswitch输出的日志需要有分析能力。


最后,验证一种场景,kamailio+rtpproxy, 通过rtpproxy隐藏freeswitch核心交换媒体流的ip,也就是freeswitch只在中心骨干网内部流转,验证确实是可行的,但kamailio+rtpproxy对ICE的报文修改存在问题,只支持sdp中m字段的端口修改,需要扩展对ICE地址修改的支持;这种组网情况下,kamailio在边沿节点作为SIP的接入注册和位置服务器,mysql在中心网内作为分布式数据库存在,所有kamailio的节点都指向同一个mysql的数据库,媒体代理在后端提供媒体交换的能力,示意框图如下图;

呱牛笔记


知识点:

SIP代理的作用是提供SIP信令的入口、授权、访问控制,位置存储、媒体路由和媒体的负载功能;

SIP代理的主要开源产品有:opensips、kamailio、opensers,单台sip代理服务器能注册1W的用户;

媒体服务器主要提供媒体协商、转码和RTP数据交换功能;

媒体服务器的主要开源产品有Asterisk、Freeswitch,都是擅长做媒体软交换;


Freeswitch性能测试数据,使用sipp来测试,CSDN上有篇文章值得看:Linux-sipp3.6测试Freeswitch

 

[root@localhost test]# sipp -sf caller_with_auth.xml 11.12.117.200:5060 -i 11.12.115.239 -p 26045 -inf data.csv -r 150  -rp 1000 -l 1000 -m 1000 -d 60000 -oocsn ooc_default -trace_err

               

-------------------------+---------------------------+--------------------------

  Successful call        |        0                  |      608                 

  Failed call            |        0                  |      592                 

-------------------------+---------------------------+--------------------------

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                                            

19865 root      10 -10 5018876   2.6g   5264 S 387.7 33.9  53:23.79 freeswitch   

       

[root@localhost test]# sipp -sf caller_with_auth.xml 11.12.117.200:5060 -i 11.12.115.239 -p 26045 -inf data.csv -r 150  -rp 500 -l 500 -m 500 -d 60000 -oocsn ooc_default -trace_err

-------------------------+---------------------------+--------------------------

  Successful call        |        0                  |      234                 

  Failed call            |        0                  |      266                 

-------------------------+---------------------------+--------------------------


[root@localhost test]# sipp -sf caller_with_auth.xml 11.12.117.200:5060 -i 11.12.115.239 -p 26045 -inf data.csv -r 100  -rp 1000 -l 300 -m 300 -d 60000 -oocsn ooc_default -trace_err

-------------------------+---------------------------+--------------------------

  Successful call        |        0                  |      282                 

  Failed call            |        0                  |       18                 

-------------------------+---------------------------+--------------------------

-------------------------+---------------------------+--------------------------

  Successful call        |        0                  |      290                 

  Failed call            |        0                  |       10                 

-------------------------+---------------------------+--------------------------


[root@localhost test]# sipp -sf caller_with_auth.xml 11.12.117.200:5060 -i 11.12.115.239 -p 26045 -inf data.csv -r 50  -rp 1000 -l 200 -m 200 -d 60000 -oocsn ooc_default -trace_err

-------------------------+---------------------------+--------------------------

  Successful call        |        0                  |      193                 

  Failed call            |        0                  |        7                 

-------------------------+---------------------------+--------------------------

测试呼叫,呼叫保持30s,发送30srtp数据,单台Freeswitch 能支持每秒100路左右通话,每分钟连接的通话数在200路,连续发送200路通话,FreeswitchCPU300%,但内存不高;


本文为呱牛笔记原创文章,转载无需和我联系,但请注明来自呱牛笔记 ,it3q.com

请先登录后发表评论
  • 最新评论
  • 总共0条评论