在SIP网络环境中,除了语音质量,并发处理等问题以外,Event 事件的处理其实也是一个非常重要的话题。在很多的使用场景中,SIP终端需要通过事件来获得对端或者其他相关终端的状态信息。今天,我们就Event事件的处理做一些比较深入的讨论。在本章节中,我们将涉及Event事件的基本原理,事件类型,相关RFC官方和注册Reg的示例,以及关于对Event事件处理方式等话题分别进行讨论。
01
Event Notification的使用背景
在介绍整个事件推送到场景之前,我们首先大概介绍一下事件推送到使用背景。在1998年, 一些相关的技术研究人员就提出了在SIP拓展场景中使用Subscribe和Notify method方式。通过这种方式可以获悉对端的状态和通知等。另外一种比较容易理解的使用场景就是中国用户经常使用的QQ。QQ也使用了类似的工作方式来实现QQ对端用户的在线状态,这是我们非常熟悉的环境。
在很多的SIP通信场景中,本地SIP终端需要获得对端的状态以便SIP终端进行环境的处理。通过事件的方式进行SIP终端之间的互相不断互发跟踪其分机状态。比较典型的例子就是Presence(在线状态)的使用。如果本端(watcher)想获得对端状态的话,本端必须对其远端(publisher)进行一个事件订阅,这样,本端就可以实时获取到对端的状态。对端的状态包括了多种形态和多种数据状态属性,本地用户终端必须要通知对端所订阅的事件状态。订阅产生以后,远端的状态和状态数据都会根据远端的环境变化而随着产生不同的事件和数据。现在问题来了,因为远端的终端的状态是随时发生变化的,同时会产生不同的事件,远端终端可能无法获知本地终端究竟需要那个事件的数据,因此本地终端必须对远端事件进行特别的订阅,通过订阅具体的事件来获取相应的返回数据,否则远端会发送返回错误。通过订阅具体的事件ID就不会产生错误的返回消息,远端可以及时推送相应的事件和事件类型。
在具体的订阅流程中,可能产生不同的数据,不同时间携带了不同的数据格式(XML格式),通过丰富的数据格式来表示当前的终端状态。终端之间的订阅实现方式可以支持点对点的订阅和通过服务器处理的订阅方式来处理。我们会在下面的章节中做进一步的介绍。
02
SIP Event Notification的工作原理
介绍了一些基本的背景知识以后,我们这里重点介绍一下事件提示的基本工作原理。Event Notification本身可以使用在很多的系统中,SIP技术对其进行了扩展支持。通过Subscribe和Notify的方式,它可以应用在以下几个方面的语音场景中:
Presence/IM 即时消息系统环境
紧急状态提示
SIP的会议控制
其他应用
前面我们已经讨论了关于事件的类型,如果不知道事件类型的话,本地终端没有办法获取到对端具体的数据数据。因此,我们需要首先介绍一下event的类型和其需要遵守的相关的两个规则。
需要遵守SIP协议规则,因为Event Notification通过SIP来进行协商,因此,它必须遵守SIP消息的处理流程。
需要遵守事件类型以及响应数据属性的规则,在携带的数据中包括了事件名称和数据的其他属性数值,因此它必须遵守相关的XML语法规范和数据规范。
在实际的应用场景中,事实上事件类型包括了很多类型。我们比较常见的类型包括:Presence,Reg等。RFC6665对具体的事件类型的定义有非常详细的介绍。我们这里罗列了一个汇总表方便读者了解各种事件类型。
各种事件类型都有其相应的SIP header,pay load,数据结构和属性参数。读者如果想进一步了解这些具体的规范的话,可以自己研究。因为篇幅的问题,我们仅介绍几个比较常用的事件和数据类型。
在Event Notification的介绍中,笔者建议读者首先需要了解到是RFC3842规范,此规范具体定义了message summary和MWI数据包的结构。通过此规范可以基本掌握了事件订阅,数据类型等必要的基础知识。以下示例是一个RFC3842的规范示例,本端SIP分机对远端SIP分机在一定时间内进行一个订阅请求处理。双方通过发送SIP消息,数据和确认同步来获取对端的状态信息。
如果对端状态消息更新以后,本地可以收到回复信息和相关的数据内容。具体内容属性根据不同的数据不同而产生不同的数据(以上示例中A13的消息内容)。
03
关于Notification的相关RFC规范
当我们讨论Event Notification时,我们讨论了多个rfc规范。这些规范是SIP协议的一些扩展协议,需要结合RFC3261来进一步学习。为了能够专注于我们经常使用的几个场景进行讨论,我们这里仅讨论几个经常使用的规范,方便读者可以进行进一步学习,它们包括:
RFC6665, 它是SIP的拓展协议,提供了一个拓展框架,SIP节点可请求一个notification来表示某些事件已发生。
RFC3903,它是一个SIP拓展协议,在SIP event中支持pblish event状态。
RFC3842,它提供对SIP Event数据包描述信息,支持对感兴趣的用户传输消息等待状态和消息summaries。
以上三种规范是我们经常使用的规范,读者在使用过程中需要根据其语法结构和传输方式进行,结合其具体的请求方式来进行分析。
04
SIP Reg 中的事件包分析讨论
在前面的讨论中我们曾经提到了reg事件包,现在我们根据其规范定义来具体讨论一下SIP注册的event 数据包的语法和示例场景。通过SIP注册的支持,Event 数据包可以创建,修改和删除注册packages。很多情况下,SIP终端需要不断更新其状态来实现第三方的定义需求。在SIP注册中,这个数据包的名称是reg,它出现在Event头中,支持SUBSCRIBE和NOTIFY请求中。reg支持了事件包的各种属性和其状态,具体的状态如下:
三种状态分别代表:
Init: 没有注册状态
Active:已注册状态
Terminated: 已不再注册状态
在消息体中,此规范定义了消息的数据格式和数据包名称,其规范内容如下:
All subscribers and notifiers MUST support the "application/reginfo+xml" format
其示例如下:
消息内容如下:
SUBSCRIBEsip:joe@example.com SIP/2.0Via:SIP/2.0/UDP app.example.com;branch=z9hG4bKnashds7From:sip:app.example.com;tag=123aa9To:sip:joe@example.comCall-ID:9987@app.example.comCSeq:9887 SUBSCRIBEContact:sip:app.example.comEvent:regMax-Forwards:70Accept: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=123aa9Call-ID:9987@app.example.comCSeq:1288NOTIFY Contact: sip:server19.example.comEvent: regMax-Forwards:70Content-Type: application/reginfo+xmlContent-Length: ... </reginfo>
读者注意这里的event(reg)和state,因为示例中的SIP终端还没有注册,因此它的状态是init的状态。一段时间后,分机注册以后,NOTIFY的数据包发生了变化,分机注册成功,其状态信息也随之发生了变化,状态修改为“active”状态:
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"?>sip:joe@pc34.example.com
在此示例中,笔者介绍了关于reg的结果比较关键的知识点。关于reg的规范,读者可以查阅rfc3680进行进一步的学习。
05
如何使用Subscribe,Notify和Publish
在前面的章节的讨论中,我们大部分的讨论在peer-to-peer的环境中进行讨论。一端是订阅端,另外一方发送Notify端。但是,这种使用方式仅仅限于一些小并发的SIP用户场景中,使用的方式可能也仅限于呼叫状态的一些基本的状态功能。相等于点对点的处理方式,大家可能已经猜到,那就是服务器处理或中央处理方式的事件发布方式。服务器端可以支持多种事件类型,根据不同的用户订阅方式提供不同的事件类型。其用户包括(Presence User Agent,PUA)和Subscribers(watchers)。服务区作为一个Event State Compositor (ESC)。ESC记录不同的事件类型和其状态属性参数。订阅方定时对服务器订阅数据进行提取更新。RFC3903中的关于ESC的处理示例流程图:
ESC服务器通过设置定时器和超时设置,不断刷新其数据库数据。如果PUA状态发生了变化,就会对ESC发送数据。然后,ESC对订阅方发生状态更新数据。
所有的数据交换都必须通过服务器来进行处理,不同于点对点的使用方式,ESC的处理方式就可以实现多种方式的订阅和大并发呼叫使用。
06
Subscribe,Notify和Publish的工作机制
在上面的讨论中,我们了解了ESC的大概工作原理,这里,我们再次根据具体的交换数据做一些讨论。为了让PUA支持数据发送,首先,PUA需要对ESC服务器发送一个Pubish的请求,请求中标识了event的类型和其数据属性状态。
如果其他的SIP终端对ESC发送了其他的事件包数据,也可以通过ESC服务器进行更新,这里的XML数据中的状态也发生了变化。订阅方就可以提取到某个特定PUA的数据更新状态。
07
Event Notification对SIP服务器的性能影响
通过以上介绍,我们基本了解了Event Notification的处理机制,数据格式和传输方式。大家通过这些介绍可以知道,事实上,服务器和终端之间传输的数据量是非常大的。这取决于几个主要的要素:SIP终端数量,定时器设置,订阅数量和消息体构成等。这些要素设置可能会影响服务器的性能以及其稳定性。具体的表现为数据传输延迟,状态更新不准确,消息丢失等问题。Georgios Panagiotou 曾经对其设计架构发表了一篇论文,读者可以查阅来讨论。Erkki Harjula在很早以前的论文中也对部署方式带来的服务器的影响进行了研究,可以作为读者学习的资料。
当然,因为互联网技术的发展和网络带宽的增加,一些问题可能逐步得到了解决。针对peer-to-peer或者ESC场景,如果SIP端通过一定的优化,也许可能会降低一些数据的传输和频率,例如设置一些数据过滤机制,定时器时间进行调整等方法。
08
总结
在本文章中,笔者根据SIP应用的场景首先对SIP 事件消息推送做了比较简单的背景知识介绍,通过介绍,让读者了解了Event Notification的作用。然后,我们介绍了基本的知识和其相关的协议规范。笔者通过reg event package的示例说明了事件创建,更新和数据属性的构成。笔者通过讨论点对点部署方式和服务器部署方式讨论了Subscribe, Notify和Publish的工作机制,并且针对服务器的性能做了进一步的分析和优化讨论。
以上这些讨论具有一定的局限性,没有涉及每一个eventpackage的使用场景,所以难免会出现一些错误的表述,因此,读者最好根据自己的实际场景和相关的规范来做更专业的分析,这里,仅是抛砖引玉。
参考资料:
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行业分享
Asterisk freepbx 中文官方论坛:http://bbs.freepbx.cn/forum.php
Asterisk freepbx,FreeSBC 技术文档: www.freepbx.org.cn
融合通信商业解决方案,协同解决方案首选产品:www.hiastar.com
Asterisk/FreePBX中国合作伙伴,官方qq技术分享群(3000人):589995817
网友评论