2023年12月6日发(作者:)
OpenSips+FreeSwitch负载均衡
1. 基本配置
这个简单一点() 负载均衡可用的
opensipsctl fifo which
opensipsctl fifo lb_list # 查看负载均衡的配置是否生效
Wireshark软件的Telephony菜单里有一个VoIP Call菜单项,可以自动发现sip呼叫,可以整理出呼叫过程中,所有消息的流程图。分析流程图可以找到问题所在,然后去搜索解决方案,就
比较容易了。
FreeSwitch的三种媒体处理方式:
录音这个顺序很重要,不能把顺序和bridge的弄反了,否则会录音不成功:
vim /usr/local/freeswitch/conf/dialplan/
acl配置,注意是cidr而不是domain:
vim /usr/local/freeswitch/conf/autoload_configs/
脚本主要修改的地方:
# 注销掉location的查找,就可以不验证,直接打电话了。查找location会改变du、ru变量。
route[relay]
{
# for INVITEs enable some additional helper routes
if (is_method("INVITE"))
{
# 如果 INVITE 是从 FS 传回来的,则将找到的分级 relay
if($si=~"192.168.2.57")
{
xlog("xxxxxxxxxxxxxxxxx [$ru] [$du]n");
if (lookup("location","m"))
{
xlog("yyyyyyyyyyyyyyyy [$ru] [$du]n");
#$ru="sip:2001@192.168.2.160:5060";
}
}
else
{
# 第一次收到的 INVITE 要转给 FS
t_on_branch("per_branch_ops");
t_on_reply("handle_reply");
t_on_failure("missed_call");
# relay to FS
xlog("Alex6 ...... [$ru] [$si]n");
rewritehostport("192.168.2.57:5080");
}
}
if (! t_relay())
{
send_reply("500","Internal Error");
}
exit;
}
虽然依赖DAILOG模块,但是并没有太多的函数调用,只加了validate the sequential request against dialog 这个判断,应该也可以去掉,然后就是直接调用 if (! load_balance("1", "pstn"))
了,在数据库 load_balancer里面有配置。
#
# OpenSIPS residential configuration script
# by OpenSIPS Solutions
#
# This script was generated via "make menuconfig", from
# the "Residential" scenario.# You can enable / disable more features / functionalities by# re-generating the scenario with different options.### Please refer to the Core CookBook at:# /Resources/DocsCookbooks# for a explanation of possible statements, functions and parameters.######## Global Parameters #########log_level=3log_stderror=nolog_facility=LOG_LOCAL0children=4/* uncomment the following lines to enable debugging */#debug_mode=yes/* uncomment the next line to enable the auto temporary blacklisting of
not available destinations (default disabled) */#disable_dns_blacklist=no/* uncomment the next line to enable IPv6 lookup after IPv4 dns
lookup failures (default disabled) */#dns_try_ipv6=yes/* comment the next line to enable the auto discovery of local aliases based on reverse DNS on IPs */auto_aliases=nolisten=udp:192.168.2.160:5060 # CUSTOMIZE ME####### Modules Section #########set module pathmpath="/usr/local//lib64/opensips/modules/"db_default_url="mysql://opensips:opensipsrw@192.168.2.160:3306/opensips"#loadmodule "proto_"loadmodule "db_"loadmodule ""loadmodule "auth_"modparam("auth_db", "calculate_ha1", 1)modparam("auth_db", "use_domain", 1)modparam("auth_db", "password_column", "password")#### SIGNALING moduleloadmodule ""#### StateLess moduleloadmodule ""#### Transaction Moduleloadmodule ""modparam("tm", "fr_timeout", 5)modparam("tm", "fr_inv_timeout", 30)modparam("tm", "restart_fr_on_each_reply", 0)modparam("tm", "onreply_avp_mode", 1)#### Record Route Moduleloadmodule ""/* do not append from tag to the RR (no need for this script) */modparam("rr", "append_fromtag", 0)#### MAX ForWarD moduleloadmodule ""#### SIP MSG OPerationS moduleloadmodule ""#### FIFO Management Interfaceloadmodule "mi_"modparam("mi_fifo", "fifo_name", "/tmp/opensips_fifo")modparam("mi_fifo", "fifo_mode", 0666)#### URI moduleloadmodule ""modparam("uri", "use_uri_table", 0)#### USeR LOCation moduleloadmodule ""modparam("usrloc", "db_mode", 1)modparam("usrloc", "nat_bflag", "NAT_BFLAG")modparam("usrloc", "use_domain", 1)modparam("usrloc", "hash_size", 16)#modparam("usrloc", "nat_bflag", "NAT")#modparam("usrloc", "working_mode_preset", "single-instance-no-db")#### REGISTRAR moduleloadmodule ""modparam("registrar", "tcp_persistent_flag", "TCP_PERSISTENT")modparam("registrar", "max_contacts", 1)modparam("registrar", "min_expires", 30)modparam("registrar", "max_expires", 300)modparam("registrar", "default_expires", 120)/* uncomment the next line not to allow more than 10 contacts per AOR */#modparam("registrar", "max_contacts", 10)#### ACCounting moduleloadmodule ""/* what special events should be accounted ? */modparam("acc", "early_media", 0)modparam("acc", "report_cancels", 0)/* by default we do not adjust the direct of the sequential requests. if you enable this parameter, be sure to enable "append_fromtag" in "rr" module */modparam("acc", "detect_direction", 0)#### DIALOG moduleloadmodule ""modparam("dialog", "dlg_match_mode", 1)modparam("dialog", "default_timeout", 21600) # 6 hours timeoutmodparam("dialog", "db_mode", 2)modparam("dialog", "db_url", "mysql://opensips:opensipsrw@localhost/opensips") # CUSTOMIZE MEloadmodule "proto_"### load balanceloadmodule "load_"modparam("load_balancer", "db_url", "mysql://opensips:opensipsrw@192.168.2.160:3306/opensips")modparam("load_balancer", "probing_method", "OPTIONS")modparam("load_balancer", "probing_interval", 30)####### Routing Logic ######### main request routing logicroute{ if (! mf_process_maxfwd_header("10"))
{ send_reply("483","Too Many Hops"); exit; } if (is_method("OPTIONS")) { t_reply("200", "OK"); exit; }
$var(pTg) = has_totag(); xlog("method[$rm] has_totag = $var(pTg)"); if ($var(pTg) > 0)
{ if (loose_route())
{ xlog("loose_route ---> as receive message method[$rm]"); # route it out to whatever destination was set by loose_route() in $du (destination URI). route(relay); } else
{ if (is_method("ACK"))
{ if (t_check_trans()) { # non loose-route, but stateful ACK; must be an ACK after a 487 404 from upstream server xlog("receive message method[$rm] from [$ru] then do t_relay"); t_relay(); exit; } else { xlog("receive message method[$rm] no transaction , then exit"); exit; } } sl_send_reply("404","Not here"); } # validate the sequential request against dialog if ( $DLG_status!=NULL && !validate_dialog() ) { xlog("In-Dialog $rm from $si (callid=$ci) is not valid according to dialogn"); ## exit; } exit; } # CANCEL processing if (is_method("CANCEL")) { if (t_check_trans()) t_relay(); exit; } # absorb retransmissions, but do not create transaction t_check_trans(); if (!is_method("REGISTER|MESSAGE")) { record_route(); } if (is_method("PUBLISH|SUBSCRIBE")) { t_reply("405", "Method Not Allowed "); exit; } if (is_method("REGISTER"))
{ xlog("Alex1--Do REGISTER AUTH : [$rm] ci[$ci] si[$si] sp[$sp] rd[$rd] rU[$rU] fU[$fU]");` route(AUTH); } if ($rU==NULL)
{ # request with no Username in RURI send_reply("484","Address Incomplete"); exit; } route(relay);}branch_route[per_branch_ops]
{ xlog("new branch at Alex2 $ru $rUn");}onreply_route[handle_reply]
{ xlog("incoming reply [$ci] [$si:$sp] [$rs]n");}failure_route[missed_call]
{ if (t_was_cancelled())
{ exit; }}route[relay]
{ # for INVITEs enable some additional helper routes if (is_method("INVITE"))
{ if ($si=~"192.168.2.57") { xlog("Alex111 [$ru] [$du]n"); if (lookup("location","m"))
{ xlog("yyyyyyyyyyyyyyyy [$ru] [$du]n"); #$ru="sip:2001@192.168.2.160:5060"; } } else if($si=~"192.168.2.176")
{ xlog("Alex222 [$ru] [$du]n"); if (lookup("location","m"))
{ xlog("yyyyyyyyyyyyyyyy [$ru] [$du]n"); #$ru="sip:2001@192.168.2.160:5060"; } } else { t_on_branch("per_branch_ops"); t_on_reply("handle_reply"); t_on_failure("missed_call"); # relay to FS # rewritehostport("192.168.2.57:5080"); if (! load_balance("1", "pstn")) { xlog("Alex333 [$ru] [$si]n");
sl_send_reply("500", "Service full.");
exit;
}
}
}
if (! t_relay())
{
send_reply("500","Internal Error");
}
exit;
}
route[AUTH]
{
# the same as --> www_authorize("", "subscriber");
$var(authRslt) = www_authorize("$td", "subscriber");
xlog("register auth result [$var(authRslt)] rd [$rd] user[$fU] source ip[$si] Alex1: $rp");
switch ($var(authRslt))
{
case -1:
send_reply("404", "Not Found");
exit;
case -2:
case -5:
send_reply("403", "Forbidden");
exit;
case -3:
case -4:
###www_challenge("$td","1");
www_challenge("$td","0");
exit;
}
$var(pA) = is_ip_registered("location", "$tu", "$si");
if ($var(pA) < 0)
{
xlog("====SIP contact ct:[$ct] [$fu] ci:[$ci] did not registe on, then check registe status for fU:[$fU].");
if (is_registered("location"))
{
xlog("L_WARN", "====Forbid $ct to registe on, cuase by : exist another $fU has registed");
send_reply("403", "Occupied");
exit;
}
}
if (! save("location", "f"))
{
sl_reply_error();
}
$var(expire) = "0";
if ($hdrcnt(Expires) == 0)
{
$var(expire) = $(expires);
xlog("no expire header ,contact expire is [$var(expire)]");
}
else
{
$var(expire) = $hdr(Expires);
xlog("expires header , expire [$var(expire)]");
}
exit;
}
View Code
数据库的配置:
mysql> select * from load_balancer;
+----+----------+------------------------+-----------+------------+-------------+
| id | group_id | dst_uri | resources | probe_mode | description |
+----+----------+------------------------+-----------+------------+-------------+
| 1 | 1 | sip:192.168.2.57:5060 | pstn=500 | 1 | FS1 |
| 2 | 1 | sip:192.168.2.176:5060 | pstn=500 | 1 | FS2 |
+----+----------+------------------------+-----------+------------+-------------+
配置命令:
INSERT INTO `opensips`.`load_balancer` (`id`, `group_id`, `dst_uri`, `resources`, `probe_mode`, `description`) VALUES ('1', '1', 'sip:192.168.2.57:5060', 'pstn=500', '1', 'FS1');
INSERT INTO `opensips`.`load_balancer` (`id`, `group_id`, `dst_uri`, `resources`, `probe_mode`, `description`) VALUES ('2', '1', 'sip:192.168.2.176:5060', 'pstn=500', '1', 'FS2');
UPDATE `load_balancer` SET description='FS2' WHERE id=2;
opensipsctl dispatcher addgw 1 sip:192.168.2.57 5060 0 50 'FS1' '节点1'
opensipsctl dispatcher addgw 1 sip:192.168.2.176 5060 0 50 'FS2' '节点2'
opensipsctl dispatcher show # 查看负载均衡配置
opensipsctl fifo lb_status 2 1 # 将目的地2配置为可用的状态
sofia profile internal siptrace on # 在fs中执行,查看信令流
注意是 insert into 不是 info
2. 语音流和信令
补充小任务:配置FS,使其支持无限回放,即一条腿的情况。


发布评论