最近在调研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,发送30s的rtp数据,单台Freeswitch 能支持每秒100路左右通话,每分钟连接的通话数在200路,连续发送200路通话,Freeswitch的CPU到300%,但内存不高;
-------------------广告线---------------
项目、合作,欢迎勾搭,邮箱:promall@qq.com
本文为呱牛笔记原创文章,转载无需和我联系,但请注明来自呱牛笔记 ,it3q.com