因此,在本文章的分享中,筆者將介紹dispatcher的基本概念,以及它和loadbalance的區(qū)別,dispatcher的處理以及呼叫失敗處理邏輯處理和dispatcher配置示例做詳細(xì)說(shuō)明。
OpenSIPS/Kamailio/媒體服務(wù)器路由調(diào)度模塊集成示例
說(shuō)明:在配置示例的討論中,筆者將使用dialpaln模塊, drouting和其他的路由輔助模塊和OpenSIPS的控制界面做必要的配置來(lái)實(shí)現(xiàn)調(diào)度功能示例演示,所以,用戶如果需要實(shí)現(xiàn)調(diào)度功能示例的話,用戶必須首先安裝配置環(huán)境。
除了使用開(kāi)源OpenSIPS或者Kamailio的調(diào)度模塊以外,用戶可以選擇freesbc作為一個(gè)媒體服務(wù)器的前端對(duì)呼叫進(jìn)行路由調(diào)度處理。
1、OpenSIPS的dispatcher模塊的基本概念
OpenSIPS也稱為軟交換。既然是軟交換的話,它必須具備一定的dispatcher的調(diào)度功能。簡(jiǎn)單來(lái)說(shuō),dispatcher的調(diào)度可能主要是實(shí)現(xiàn)對(duì)呼叫進(jìn)行呼叫目的地的調(diào)度管理。通過(guò)呼叫請(qǐng)求結(jié)合目的地選項(xiàng)實(shí)現(xiàn)呼出代理的路由管理。調(diào)度模塊通過(guò)權(quán)重設(shè)置對(duì)呼叫目的地進(jìn)行設(shè)置。實(shí)際上,調(diào)度模塊可以實(shí)現(xiàn)一個(gè)無(wú)狀態(tài)的負(fù)載均衡機(jī)制,它不會(huì)保證其最終路由結(jié)果。因此,調(diào)度模塊實(shí)現(xiàn)的是一個(gè)簡(jiǎn)單的呼叫分發(fā)功能,不涉及呼叫最終結(jié)果的處理。關(guān)于dispatcher的完整描述,用戶可以參考官方文檔關(guān)于dispatcher的說(shuō)明。
2、dispatcher和loadbalance的區(qū)別
前面筆者已經(jīng)說(shuō)明,在使用OpenSIPS時(shí),很多用戶仍然對(duì)調(diào)度和負(fù)載均衡有一些迷惑和誤解。調(diào)度模塊和負(fù)載均衡模塊有一個(gè)共同之處-它們都是對(duì)呼叫進(jìn)行分發(fā)處理。因?yàn)檫@個(gè)共同之處所以導(dǎo)致用戶對(duì)兩個(gè)模塊的錯(cuò)誤理解。這里,筆者簡(jiǎn)單介紹一下dispatcher和loadbalance的區(qū)別。它們兩者之間有比較大的區(qū)別:
Dispatching/調(diào)度:
- 無(wú)負(fù)載目的地端任何信息,僅直接分發(fā)
- 僅通過(guò)peer做一個(gè)概率性的數(shù)據(jù)路由分發(fā)
- 假設(shè)所有目的地端是確定的,包括目的地端是正常工作狀態(tài)
- 處理速度快,無(wú)需獲得返回消息,完全是一種“盲”或者無(wú)狀態(tài)的處理
Loadbalance/負(fù)載均衡:
- 基于dialog模塊,可對(duì)目的地端負(fù)載計(jì)數(shù)
- 因?yàn)橹С帜芰Σ煌,目的地端可能完全不同(例如,媒體能力,業(yè)務(wù)功能不同)
- 可收到目的地端的返回消息
- 對(duì)目的地端無(wú)任何偵測(cè)的要求
3、Dispatcher 其他討論
用戶需要啟用Dispatcher的話,它和其他的模塊一樣,也同樣需要加載一些必要的參數(shù)和支持模塊。具體的語(yǔ)法這里不再介紹,官方有完整的語(yǔ)法說(shuō)明。筆者這里想介紹幾個(gè)使用dispatch模塊時(shí)幾個(gè)特別需要說(shuō)明的地方。
針對(duì)呼叫目的地的調(diào)度路由,dispatcher 模塊可以支持幾種不同的路由方式,用戶可以根據(jù)自己的業(yè)務(wù)場(chǎng)景來(lái)設(shè)置不同的路由:
- 可以通過(guò)SIP URLS定義來(lái)進(jìn)行路由
- 可以通過(guò)組設(shè)置來(lái)進(jìn)行路由
- 在組設(shè)置中可以支持不同權(quán)重來(lái)定義調(diào)度路由
- 可以通過(guò)MI CLI命令關(guān)閉/開(kāi)啟目的地組
- 可以通過(guò)組設(shè)置中的優(yōu)先級(jí)順序來(lái)實(shí)現(xiàn)路由
- 可以通過(guò)屬性字符串的標(biāo)識(shí)來(lái)定義路由
針對(duì)dispatcher模塊的數(shù)據(jù)處理,OpenSIPS支持的是實(shí)時(shí)的數(shù)據(jù)存儲(chǔ)方式。路由目的地通過(guò)數(shù)據(jù)庫(kù)存儲(chǔ)的方式進(jìn)行設(shè)置。數(shù)據(jù)庫(kù)數(shù)據(jù)在OpenSIPS啟動(dòng)時(shí)加載的內(nèi)存中的,在系統(tǒng)運(yùn)行中不會(huì)再訪問(wèn)數(shù)據(jù)庫(kù)獲取數(shù)據(jù)。如果用戶需要重新加載數(shù)據(jù)的話,可以通過(guò)MI CLI命令執(zhí)行ds_reload 來(lái)實(shí)現(xiàn)數(shù)據(jù)加載。比較新的OpenSIPS版本(官方推薦使用2.3)可以支持針對(duì)dispatcher的數(shù)據(jù)實(shí)現(xiàn)分區(qū)的功能,調(diào)度模塊的表可以和多個(gè)數(shù)據(jù)庫(kù)資源進(jìn)行訪問(wèn)支持。數(shù)據(jù)分區(qū)的功能目前支持dialplan,dispatcher和drouting。dispatcher模塊可以同時(shí)對(duì)兩種不同的業(yè)務(wù)場(chǎng)景實(shí)現(xiàn)不同的數(shù)據(jù)庫(kù)訪問(wèn)來(lái)獲取調(diào)度業(yè)務(wù)所需要的數(shù)據(jù),具體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平臺(tái)中,Dispatcher路由可以支持多種方式(10種),這些方式也非常靈活。調(diào)度模塊可以根據(jù)不同的業(yè)務(wù)場(chǎng)景執(zhí)行不同的路由。dispatcher模塊可以支持通過(guò)hash table的路由,也可以支持round-robin的路由方式。一般情況下,如果沒(méi)有特別的業(yè)務(wù)要求,很多用戶使用round-robin的方式。
但是如果需要針對(duì)SIP用戶限定等特別的業(yè)務(wù)功能支持的話,用戶需要使用hash table來(lái)實(shí)現(xiàn)不同的路由。一些非常常用的場(chǎng)景也必須通過(guò)hash table方式來(lái)實(shí)現(xiàn),例如:
一個(gè)SIP用戶的所有注冊(cè)終端必須能夠注冊(cè)到同一注冊(cè)服務(wù)器peer端,一般情況下,系統(tǒng)也不允許出現(xiàn)不同的注冊(cè)目的地地址。
SIP 用戶如果呼叫的話,所有它們的呼叫始終呼叫到同一服務(wù)器目的地端。
針對(duì)媒體會(huì)議服務(wù)器的端路由中,對(duì)每個(gè)會(huì)議服務(wù)器的會(huì)議室能夠路由到正確的目的地端服務(wù)器地址
在hash 表的路由中用戶需要特別注意這些細(xì)微的區(qū)別, 通過(guò)不同的SIP 頭確保其呼叫路由到正確的目的地:
0-hash over callid-確保所有同一dialog的請(qǐng)求能夠路由到同一目的地代理服務(wù)器。通過(guò)dialog中的callid來(lái)跟蹤同一呼叫。
- 1-hash over From URL-確保所有從同一用戶發(fā)出的請(qǐng)求能夠路由到同一代理服務(wù)器目的地。
- 2-hash over To URL-確保一個(gè)AOR的所有注冊(cè)能夠路由到同一代理服務(wù)器地址。
- 3-hash over Request-URL-確保所有對(duì)同一目的地的請(qǐng)求能夠路由到同一目的地服務(wù)器
為了滿足會(huì)議服務(wù)器路由和其他正常語(yǔ)音呼叫的處理調(diào)度,可以通過(guò)Dispatch 腳本中針對(duì)具體會(huì)議服務(wù)器路由和正常路由進(jìn)行處理的示例,使用了0和3參數(shù)設(shè)置:
modparam("dispatcher", "db_ url",
"mysql://opensips:opensipsrw@localhost/opensips")
# 呼叫路由部分,僅支持初始INVITEs
if ( $rU=~"^3[0-9][0-9]$") {
# 呼叫到媒體服務(wù)器的電話會(huì)議室路由
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 調(diào)度呼叫失效處理控制討論
Dispatcher模塊實(shí)現(xiàn)的是一個(gè)非常簡(jiǎn)單的呼叫調(diào)度路由,dispatcher假設(shè)對(duì)端peer是正常狀態(tài),它本身不關(guān)心對(duì)端peer的呼叫是否成功或者失敗。但是,在實(shí)際應(yīng)用環(huán)境中,如果對(duì)端peer出現(xiàn)故障的話,用戶如果使用了調(diào)度模塊的話,系統(tǒng)仍然需要對(duì)peer進(jìn)行檢查,否則,系統(tǒng)對(duì)呼叫失去了控制。例如,對(duì)端媒體會(huì)議媒體服務(wù)器出現(xiàn)故障,如何對(duì)其進(jìn)行檢查等。那么,OpenSIPS 的dispatcher 模塊如何實(shí)現(xiàn)對(duì)對(duì)端peer進(jìn)行檢測(cè)是一個(gè)非常重要的環(huán)節(jié)。OpenSIPS的dispatcher 模塊可以通過(guò)一些幾種方式對(duì)對(duì)端peer進(jìn)行檢測(cè):
- 無(wú)返回消息,例如可能是timeout 超時(shí),peer出現(xiàn)故障。
- 對(duì)端返回1xx,例如可能是媒體服務(wù)器沒(méi)有足夠的落地資源或者可用端口(例如,落地使用的FXO/E1端口正在被占用)。
- 返回5xx消息,peer服務(wù)器內(nèi)部錯(cuò)誤
- 返回6xx消息,可能是全局網(wǎng)絡(luò)失敗
- 返回4xx消息,可能是其他能力支持問(wèn)題,例如編碼轉(zhuǎn)換或者落地端口被占用,擁塞等。
在dispatcher使用時(shí),可以通過(guò)失敗路由檢測(cè)到腳本對(duì)peer進(jìn)行檢測(cè),具體的cfg示例如下:
failure_ route[ds_failed] {
if(t_check_status( "[56][0-9][0-9]") ||
# 對(duì)端 peer 錯(cuò)誤
(t_local_replied("all") &&t_check_status("408")) ||
# 本地 408 錯(cuò)誤
t_ check_ status("409") )
# 其他錯(cuò)誤
# 執(zhí)行失效呼叫處理
]
Dispatcher對(duì)對(duì)端peer的檢測(cè)完成以后,仍然需要呼叫失效處理的邏輯腳本對(duì)失效呼叫進(jìn)行二次處理,然后進(jìn)行目的地狀態(tài)更新以后的呼叫。針對(duì)OpenSIPS的dispatcher(負(fù)載均衡類似)失效處理的算法大概需要經(jīng)過(guò)以下六個(gè)步驟:
通過(guò)ds_select 獲取一個(gè)初始對(duì)端peer的組順序
從路由組中選擇第一個(gè)路由peer
對(duì)可用的第一個(gè)目的地peer發(fā)送request請(qǐng)求
如果檢測(cè)到失敗的話,對(duì)此peer做一個(gè)失敗標(biāo)識(shí),關(guān)閉此peer,繼續(xù)查詢下一個(gè)可用的peer
使用下一個(gè)peer,然后添加到branch中執(zhí)行serial forking處理
重復(fù)第三步
根據(jù)以上流程,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,標(biāo)識(shí)為失敗peer
If(!ds_next_dst()){
t_reply(503,"Servlce Unavallable");
exit;
}
t_on_failure("ds fallover");
t_relay() #必須對(duì)前面的relay重新發(fā)出告警
}
}
筆者應(yīng)該注意,以上的處理方式僅說(shuō)明在使用dispatcher 模塊時(shí),opensips的呼叫失效的處理邏輯。mark的策略也可以做一定的調(diào)整,例如,檢測(cè)到的參數(shù),如果達(dá)到3次以上,就標(biāo)識(shí)為一個(gè)關(guān)閉的peer。另外,marked peer也可以通過(guò)一定的周期性檢測(cè),超時(shí)設(shè)置重新激活其檢測(cè)狀態(tài)。當(dāng)然,如果用戶也可以在對(duì)端peer側(cè)來(lái)設(shè)置基于自己業(yè)務(wù)層面的呼叫失效的處理流程。例如,如果對(duì)端是一個(gè)會(huì)議系統(tǒng)或者其他的媒體服務(wù)器的話,如果呼叫的終端出現(xiàn)異常,本身媒體服務(wù)器端也可以設(shè)置其他的策略來(lái)執(zhí)行呼叫失效,例如,設(shè)置一個(gè)分機(jī)隨行,呼叫其他的終端,或者轉(zhuǎn)入語(yǔ)音郵箱等方式。
OpenSIPS的dispatcher 模塊可以支持多種對(duì)SIP對(duì)端peer的狀態(tài)進(jìn)行探測(cè)。此功能的使用方式和drouting類似。另外,MI CLI命令可以對(duì)ds_list 執(zhí)行狀態(tài)檢測(cè),包括活動(dòng)狀態(tài),非活動(dòng)狀態(tài)和正在探測(cè)狀態(tài)。MI CLI命令也可以對(duì)目的地狀態(tài)進(jìn)行管理,用戶可以使用ds_set_state 進(jìn)行修改。
5、OpenSIPS的dispatcher/調(diào)度配置示例
根據(jù)以上的討論,筆者在此章節(jié)介紹一個(gè)使用調(diào)度模塊配置動(dòng)態(tài)路由的配置示例。在配置dispatcher模塊之前,和其他的模塊配置一樣,用戶需要修改cfg配置文件,加載必要的模塊和參數(shù),然后修改dispatch的路由設(shè)置,最后通過(guò)控制界面添加dispatcher的路由設(shè)置,重新啟動(dòng)OpenSIPS實(shí)現(xiàn)調(diào)度模塊和呼叫失效設(shè)置。此示例中,前端是一個(gè)OpenSIPS,兩個(gè)對(duì)端peer是媒體服務(wù)器。
首先修改cfg配置文件,添加必要的參數(shù)設(shè)置和模塊:
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 邏輯塊,實(shí)現(xiàn)調(diào)度處理:
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;
}
添加一個(gè)對(duì)媒體服務(wù)器呼叫失效的處理邏輯:
failure_route[media_failover] {
if (t_was_cancelled()) exit;
if ( t_check_status( "[56][0-9][0-9]" ) ||
。╰_local_replied("all") && t_check_status("408"))) {
# 媒體服務(wù)器呼叫失效,標(biāo)識(shí)為失敗狀態(tài)
xlog("Media server routing failed with reply $T_reply_code\n");
ds_mark_dst("p");
# 如果有可用的媒體服務(wù)器,嘗試另外一個(gè)媒體服務(wù)器
if (!ds_next_dst()) {
xlog("no more media servers available\n");
t_reply(503,"Service Unavailable");
exit;
}
# 發(fā)送呼叫到新的媒體服務(wù)器
xlog("Trying the new $du media server\n");
t_on_failure("media_failover");
t_relay();
}
}
重新啟動(dòng)OpenSIPS,然后登錄OpenSIPS控制界面,添加修改的目的地地址和組設(shè)置。通過(guò)dispatcher菜單添加不同的兩個(gè)媒體服務(wù)器地址。添加以后,重新刷新界面。如果對(duì)端設(shè)置正常的話,dispatcher模塊會(huì)看到活動(dòng)的peer狀態(tài)。
添加好dispatcher模塊數(shù)據(jù)以后,用戶可以進(jìn)行呼叫測(cè)試。在呼叫測(cè)試時(shí),用戶同時(shí)還要需要添加dialplan來(lái)實(shí)現(xiàn)對(duì)撥號(hào)的控制,按照自己的設(shè)置,通過(guò)終端進(jìn)行撥號(hào)測(cè)試。參數(shù)方式如下:
如果同一號(hào)碼,正常情況下,此終端的呼叫會(huì)一直在路由到同一媒體服務(wù)器。關(guān)閉另外一個(gè)調(diào)度路由設(shè)置,通過(guò)終端重新進(jìn)行呼叫,檢測(cè)呼叫是否可以正常通過(guò)。
修改第一個(gè)路由的peer地址,修改為一個(gè)127.0.0.2,測(cè)試呼叫,強(qiáng)制呼叫失效處理,檢查返回的消息。
關(guān)閉其中一個(gè)媒體服務(wù)器或者在媒體服務(wù)器側(cè)進(jìn)行撥號(hào)規(guī)則修改,終端檢查返回的SIP消息。
通過(guò)以上不同的測(cè)試流程,OpenSIPS的調(diào)度模塊的腳本處理產(chǎn)生不同的peer狀態(tài)消息,用戶可以通過(guò)MI CLI命令來(lái)檢查其狀態(tài)。如果一切配置成功的話,可以看到界面的演示是返回失效呼叫的邏輯的。
6、總結(jié)
在本文章中,筆者首先介紹了調(diào)度模塊的一些簡(jiǎn)單比較知識(shí),然后強(qiáng)調(diào)了幾個(gè)調(diào)度模塊和負(fù)載均衡模塊的不同。接下來(lái),筆者介紹了調(diào)度路由中特別需要關(guān)注的幾個(gè)參數(shù)和其非常具體的應(yīng)用場(chǎng)景。為了保證調(diào)度模塊的完整實(shí)現(xiàn),調(diào)度路由需要呼叫失效的處理,筆者又介紹了dispatcher中關(guān)于呼叫失效的處理機(jī)制和六個(gè)步驟,同時(shí)分享了cfg配置的邏輯腳本。最后,筆者分享了一個(gè)關(guān)于OpenSIPS的dispatcher模塊的使用示例,在示例中,列出了具體的加載模塊的代碼和界面相關(guān)配置,并且提示用戶如何使用SIP終端對(duì)dispatcher模塊進(jìn)行測(cè)試。
通過(guò)本文章的介紹,筆者相信用戶可能對(duì)OpenSIPS的調(diào)度模塊和負(fù)載均衡模塊區(qū)別有了新的認(rèn)識(shí),同時(shí)也更加深入了解了調(diào)度模塊的使用和其呼叫失效的管理邏輯。通過(guò)完整的調(diào)度路由策略,結(jié)合完整的調(diào)度失效控制機(jī)制來(lái)實(shí)現(xiàn)完整強(qiáng)大的dispatcher模塊集成,并且保證了媒體服務(wù)器端的呼叫穩(wěn)定性和SIP路由的完整處理。
為了完整介紹OpenSIPS的路由處理,在后續(xù)關(guān)于OpenSIPS的學(xué)習(xí)筆記中,筆者將進(jìn)一步介紹負(fù)載均衡中的路由處理處理。
參考資料:
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/
- 關(guān)于Asterisk文檔,參考:www.asterisk.org.cn
- 融合通信/IPPBX/FreePBX商業(yè)解決方案:www.hiastar.com
- 最新Asterisk完整中文用戶手冊(cè)詳解:www.asterisk.org.cn
- Freepbx/FreeSBC技術(shù)文檔: www.freepbx.org.cn
- 如何使用免費(fèi)會(huì)話邊界控制器-FreeSBC,qq技術(shù)分享群:334023047
- 關(guān)注微信公眾號(hào):asterisk-cn,獲得有價(jià)值的通信行業(yè)技術(shù)分享