
1、Event Notification的使用背景
在介紹整個事件推送到場景之前,我們首先大概介紹一下事件推送到使用背景。在1998年, 一些相關的技術研究人員就提出了在SIP拓展場景中使用Subscribe和Notify method方式。通過這種方式可以獲悉對端的狀態(tài)和通知等。另外一種比較容易理解的使用場景就是中國用戶經常使用的QQ。QQ也使用了類似的工作方式來實現(xiàn)QQ對端用戶的在線狀態(tài),這是我們非常熟悉的環(huán)境。

在很多的SIP通信場景中,本地SIP終端需要獲得對端的狀態(tài)以便SIP終端進行環(huán)境的處理。通過事件的方式進行SIP終端之間的互相不斷互發(fā)跟蹤其分機狀態(tài)。比較典型的例子就是Presence(在線狀態(tài))的使用。如果本端(watcher)想獲得對端狀態(tài)的話,本端必須對其遠端(publisher)進行一個事件訂閱,這樣,本端就可以實時獲取到對端的狀態(tài)。對端的狀態(tài)包括了多種形態(tài)和多種數(shù)據(jù)狀態(tài)屬性,本地用戶終端必須要通知對端所訂閱的事件狀態(tài)。訂閱產生以后,遠端的狀態(tài)和狀態(tài)數(shù)據(jù)都會根據(jù)遠端的環(huán)境變化而隨著產生不同的事件和數(shù)據(jù)。現(xiàn)在問題來了,因為遠端的終端的狀態(tài)是隨時發(fā)生變化的,同時會產生不同的事件,遠端終端可能無法獲知本地終端究竟需要那個事件的數(shù)據(jù),因此本地終端必須對遠端事件進行特別的訂閱,通過訂閱具體的事件來獲取相應的返回數(shù)據(jù),否則遠端會發(fā)送返回錯誤。通過訂閱具體的事件ID就不會產生錯誤的返回消息,遠端可以及時推送相應的事件和事件類型。
在具體的訂閱流程中,可能產生不同的數(shù)據(jù),不同時間攜帶了不同的數(shù)據(jù)格式(XML格式),通過豐富的數(shù)據(jù)格式來表示當前的終端狀態(tài)。終端之間的訂閱實現(xiàn)方式可以支持點對點的訂閱和通過服務器處理的訂閱方式來處理。我們會在下面的章節(jié)中做進一步的介紹。
2、SIP Event Notification的工作原理
介紹了一些基本的背景知識以后,我們這里重點介紹一下事件提示的基本工作原理。Event Notification本身可以使用在很多的系統(tǒng)中,SIP技術對其進行了擴展支持。通過Subscribe和Notify的方式,它可以應用在以下幾個方面的語音場景中:
- Presence/IM 即時消息系統(tǒng)環(huán)境
- 緊急狀態(tài)提示
- SIP的會議控制
- 其他應用
前面我們已經討論了關于事件的類型,如果不知道事件類型的話,本地終端沒有辦法獲取到對端具體的數(shù)據(jù)數(shù)據(jù)。因此,我們需要首先介紹一下event的類型和其需要遵守的相關的兩個規(guī)則。
需要遵守SIP協(xié)議規(guī)則,因為Event Notification通過SIP來進行協(xié)商,因此,它必須遵守SIP消息的處理流程。

需要遵守事件類型以及響應數(shù)據(jù)屬性的規(guī)則,在攜帶的數(shù)據(jù)中包括了事件名稱和數(shù)據(jù)的其他屬性數(shù)值,因此它必須遵守相關的XML語法規(guī)范和數(shù)據(jù)規(guī)范。
在實際的應用場景中,事實上事件類型包括了很多類型。我們比較常見的類型包括:Presence,Reg等。RFC6665對具體的事件類型的定義有非常詳細的介紹。我們這里羅列了一個匯總表方便讀者了解各種事件類型。

各種事件類型都有其相應的SIP header,pay load,數(shù)據(jù)結構和屬性參數(shù)。讀者如果想進一步了解這些具體的規(guī)范的話,可以自己研究。因為篇幅的問題,我們僅介紹幾個比較常用的事件和數(shù)據(jù)類型。
在Event Notification的介紹中,筆者建議讀者首先需要了解到是RFC3842規(guī)范,此規(guī)范具體定義了message summary和MWI數(shù)據(jù)包的結構。通過此規(guī)范可以基本掌握了事件訂閱,數(shù)據(jù)類型等必要的基礎知識。以下示例是一個RFC3842的規(guī)范示例,本端SIP分機對遠端SIP分機在一定時間內進行一個訂閱請求處理。雙方通過發(fā)送SIP消息,數(shù)據(jù)和確認同步來獲取對端的狀態(tài)信息。

如果對端狀態(tài)消息更新以后,本地可以收到回復信息和相關的數(shù)據(jù)內容。具體內容屬性根據(jù)不同的數(shù)據(jù)不同而產生不同的數(shù)據(jù)(以上示例中A13的消息內容)。

3、關于Notification的相關RFC規(guī)范
當我們討論Event Notification時,我們討論了多個rfc規(guī)范。這些規(guī)范是SIP協(xié)議的一些擴展協(xié)議,需要結合RFC3261來進一步學習。為了能夠專注于我們經常使用的幾個場景進行討論,我們這里僅討論幾個經常使用的規(guī)范,方便讀者可以進行進一步學習,它們包括:
RFC6665, 它是SIP的拓展協(xié)議,提供了一個拓展框架,SIP節(jié)點可請求一個notification來表示某些事件已發(fā)生。
RFC3903,它是一個SIP拓展協(xié)議,在SIP event中支持pblish event狀態(tài)。
RFC3842,它提供對SIP Event數(shù)據(jù)包描述信息,支持對感興趣的用戶傳輸消息等待狀態(tài)和消息summaries。
以上三種規(guī)范是我們經常使用的規(guī)范,讀者在使用過程中需要根據(jù)其語法結構和傳輸方式進行,結合其具體的請求方式來進行分析。
4、SIP Reg 中的事件包分析討論
在前面的討論中我們曾經提到了reg事件包,現(xiàn)在我們根據(jù)其規(guī)范定義來具體討論一下SIP注冊的event 數(shù)據(jù)包的語法和示例場景。通過SIP注冊的支持,Event 數(shù)據(jù)包可以創(chuàng)建,修改和刪除注冊packages。很多情況下,SIP終端需要不斷更新其狀態(tài)來實現(xiàn)第三方的定義需求。在SIP注冊中,這個數(shù)據(jù)包的名稱是reg,它出現(xiàn)在Event頭中,支持SUBSCRIBE和NOTIFY請求中。reg支持了事件包的各種屬性和其狀態(tài),具體的狀態(tài)如下:
三種狀態(tài)分別代表:
- Init: 沒有注冊狀態(tài)
- Active:已注冊狀態(tài)
- Terminated: 已不再注冊狀態(tài)
在消息體中,此規(guī)范定義了消息的數(shù)據(jù)格式和數(shù)據(jù)包名稱,其規(guī)范內容如下:
All subscribers and notifiers MUST support the "application/reginfo+xml" format
https://tools.ietf.org/html/rfc3680
其示例如下:

消息內容如下:
- SUBSCRIBE sip:joe@example.com SIP/2.0
- Via: SIP/2.0/UDP app.example.com;branch=z9hG4bKnashds7
- From: sip:app.example.com;tag=123aa9
- To: sip:joe@example.com
- Call-ID: 9987@app.example.com
- CSeq: 9887 SUBSCRIBE
- Contact: sip:app.example.com
- Event: reg
- Max-Forwards: 70
- Accept: application/reginfo+xml
返回的Notify消息內容:
- NOTIFY sip:app.example.com SIP/2.0
- Via: SIP/2.0/UDP server19.example.com;branch=z9hG4bKnasaii
- From: sip:joe@example.com;tag=xyzygg
- To: sip:app.example.com;tag=123aa9
- Call-ID: 9987@app.example.com
- CSeq: 1288 NOTIFY
- Contact: sip:server19.example.com
- Event: reg
- Max-Forwards: 70
- Content-Type: application/reginfo+xml
- Content-Length: …
- <?xml version="1.0"?>
- <reginfo xmlns="urn:ietf:params:xml:ns:reginfo"
- version="0" state="full">
- <registration aor="sip:joe@example.com" id="a7" state="init" />
- </reginfo>
讀者注意這里的event(reg)和state,因為示例中的SIP終端還沒有注冊,因此它的狀態(tài)是init的狀態(tài)。一段時間后,分機注冊以后,NOTIFY的數(shù)據(jù)包發(fā)生了變化,分機注冊成功,其狀態(tài)信息也隨之發(fā)生了變化,狀態(tài)修改為“active”狀態(tài):
- NOTIFY sip:app.example.com SIP/2.0
- Via: SIP/2.0/UDP server19.example.com;branch=z9hG4bKnasaij
- From: sip:joe@example.com;tag=xyzygg
- To: sip:app.example.com;tag=123aa9
- Call-ID: 9987@app.example.com
- CSeq: 1289 NOTIFY
- Contact: sip:server19.example.com
- Event: reg
- Max-Forwards: 70
- Content-Type: application/reginfo+xml
- Content-Length: …
- <?xml version="1.0"?>
- <reginfo xmlns="urn:ietf:params:xml:ns:reginfo"
- version="1" state="partial">
- <registration aor="sip:joe@example.com" id="a7" state="active">
- <contact id="76" state="active" event="registered"
- duration-registered="0">
- <uri>sip:joe@pc34.example.com</uri>
- </contact>
- </registration>
- </reginfo>
在此示例中,筆者介紹了關于reg的結果比較關鍵的知識點。關于reg的規(guī)范,讀者可以查閱rfc3680進行進一步的學習。
5、如何使用Subscribe,Notify和Publish
在前面的章節(jié)的討論中,我們大部分的討論在peer-to-peer的環(huán)境中進行討論。一端是訂閱端,另外一方發(fā)送Notify端。但是,這種使用方式僅僅限于一些小并發(fā)的SIP用戶場景中,使用的方式可能也僅限于呼叫狀態(tài)的一些基本的狀態(tài)功能。相等于點對點的處理方式,大家可能已經猜到,那就是服務器處理或中央處理方式的事件發(fā)布方式。服務器端可以支持多種事件類型,根據(jù)不同的用戶訂閱方式提供不同的事件類型。其用戶包括(Presence User Agent,PUA)和Subscribers(watchers)。服務區(qū)作為一個Event State Compositor (ESC)。ESC記錄不同的事件類型和其狀態(tài)屬性參數(shù)。訂閱方定時對服務器訂閱數(shù)據(jù)進行提取更新。RFC3903中的關于ESC的處理示例流程圖:

ESC服務器通過設置定時器和超時設置,不斷刷新其數(shù)據(jù)庫數(shù)據(jù)。如果PUA狀態(tài)發(fā)生了變化,就會對ESC發(fā)送數(shù)據(jù)。然后,ESC對訂閱方發(fā)生狀態(tài)更新數(shù)據(jù)。

所有的數(shù)據(jù)交換都必須通過服務器來進行處理,不同于點對點的使用方式,ESC的處理方式就可以實現(xiàn)多種方式的訂閱和大并發(fā)呼叫使用。
6、Subscribe,Notify和Publish的工作機制
上面的討論中,我們了解了ESC的大概工作原理,這里,我們再次根據(jù)具體的交換數(shù)據(jù)做一些討論。為了讓PUA支持數(shù)據(jù)發(fā)送,首先,PUA需要對ESC服務器發(fā)送一個Pubish的請求,請求中標識了event的類型和其數(shù)據(jù)屬性狀態(tài)。

如果其他的SIP終端對ESC發(fā)送了其他的事件包數(shù)據(jù),也可以通過ESC服務器進行更新,這里的XML數(shù)據(jù)中的狀態(tài)也發(fā)生了變化。訂閱方就可以提取到某個特定PUA的數(shù)據(jù)更新狀態(tài)。

7、Event Notification對SIP服務器的性能影響
通過以上介紹,我們基本了解了Event Notification的處理機制,數(shù)據(jù)格式和傳輸方式。大家通過這些介紹可以知道,事實上,服務器和終端之間傳輸?shù)臄?shù)據(jù)量是非常大的。這取決于幾個主要的要素:SIP終端數(shù)量,定時器設置,訂閱數(shù)量和消息體構成等。這些要素設置可能會影響服務器的性能以及其穩(wěn)定性。具體的表現(xiàn)為數(shù)據(jù)傳輸延遲,狀態(tài)更新不準確,消息丟失等問題。Georgios Panagiotou 曾經對其設計架構發(fā)表了一篇論文,讀者可以查閱來討論。Erkki Harjula在很早以前的論文中也對部署方式帶來的服務器的影響進行了研究,可以作為讀者學習的資料。

當然,因為互聯(lián)網(wǎng)技術的發(fā)展和網(wǎng)絡帶寬的增加,一些問題可能逐步得到了解決。針對peer-to-peer或者ESC場景,如果SIP端通過一定的優(yōu)化,也許可能會降低一些數(shù)據(jù)的傳輸和頻率,例如設置一些數(shù)據(jù)過濾機制,定時器時間進行調整等方法。
8、總結
在本文章中,筆者根據(jù)SIP應用的場景首先對SIP 事件消息推送做了比較簡單的背景知識介紹,通過介紹,讓讀者了解了Event Notification的作用。然后,我們介紹了基本的知識和其相關的協(xié)議規(guī)范。筆者通過reg event package的示例說明了事件創(chuàng)建,更新和數(shù)據(jù)屬性的構成。筆者通過討論點對點部署方式和服務器部署方式討論了Subscribe, Notify和Publish的工作機制,并且針對服務器的性能做了進一步的分析和優(yōu)化討論。
以上這些討論具有一定的局限性,沒有涉及每一個eventpackage的使用場景,所以難免會出現(xiàn)一些錯誤的表述,因此,讀者最好根據(jù)自己的實際場景和相關的規(guī)范來做更專業(yè)的分析,這里,僅是拋磚引玉。
參考資料:
http://www.mediateam.oulu.fi/publications/pdf/814.pdf
https://people.kth.se/~devlic/publications/SNCNW2009.pdf
https://tools.ietf.org/html/rfc3903
https://tools.ietf.org/html/rfc6665
FreeSBC


關注微信公眾號:asterisk-cn,獲得有價值的Asterisk行業(yè)分享
Asterisk freepbx 中文官方論壇:http://bbs.freepbx.cn/forum.php
Asterisk freepbx技術文檔: www.freepbx.org.cn
融合通信商業(yè)解決方案,協(xié)同解決方案首選產品:www.hiastar.com
Asterisk/FreePBX中國合作伙伴,官方qq技術分享群(3000千人):589995817