OpenSIPS的应用场景非常广泛,特别是在运营级的生产环境中,OpenSIPS发挥着非常重要的功能。用户可以使用OpenSIPS作为简单的SBC来使用,也可以作为一个注册服务器来使用。在SIP注册服务器的部署方案中,用户不可能始终使用一台服务器来支持配置,随着用户数量不断增加,用户属性越来越复杂,用户就必须考虑其可拓展性和可靠性的机制来保证运营平台的稳定性。
作为运营级的开源SIP软交换平台,OpenSIPS本身设计了一些模块配合数据库和no SQL实现了针对某些场景的支持。今天,笔者针对OpenSIPS集群的机制和使用场景以及各自的优缺点对集群做一个分享,并且通过配置示例来说明如何使用OpenSIPS集群解决方案。在本文章中,笔者会首先介绍关于集群的一些背景知识和其他关于集群升级的思路。另外,笔者将进一步介绍OpnSIPS的定义,OpenSIPS所使用的专门的协议,集群部署的拓扑场景讨论,集群部署的两种方式(动态和静态部署),关于SIP注册的集群实现方式以及其优缺点,针对Full sharing 集群部署的讨论,OpenSIPS环境中Federated no SQL的处理机制,关于dialog的集群部署的问题,最后,笔者分享读者最关心的针对OpenSIPS中集群部署的配置,查看工具,测试和注册集群部署示例分享。
说明:此部署示例需要安装最新的OpenSIPS以及其控制界面。另外,如果配置集群示例的话,用户需要在本地或者云平台安装几个测试实例,并且全部所有实例在同一网络环境(最好在同一区域的内网环境,保证所需要的端口和网络可以互相正常连接)。为了方便读者阅读,本文章分为两个部分,第一部分主要针对集群解决方案的基本讨论,然后配合集群注册部署的各种机制进行讨论。第二部分将继续介绍呼叫中dialog的集群处理和OpenSIPS环境中集群部署的设置和相关配置示例以及一些集群检查命令。
关于OpenSIPS环境中的集群的背景知识
集群在大规模部署的互联网场景中是一个非常普遍的应用场景。同样,在VoIP的应用场景中,集群也是必不可少的一个需要考虑的解决方案。针对语音环境,或者SIP部署的场景中,集群可应用在SIP终端注册环境,呼叫流程中的dialog处理,在线状态的处理和其他场景。除了OpenSIPS自己本身的集群模块需要配置以外,笔者以上所说的SIP场景需要通过集群机制的各种其他的实现方式来配合,例如数据库和no sql DB的支持。
此图例以及以下图例均来自于互联网资源
集群是一个永远完成不可能完成对的任务。很多用户不顾公司业务和技术实力以及资源的限制,它们盲目跟风,最后可能因为很多潜在的风险,最终导致方案的失败。在部署之前,用户一定要彻底考虑清楚其未来隐藏的一些技术风险,一定要根据公司本身的业务需求,技术实力和资源来逐步推进慎重地考虑问题。如果我们比较宽泛地说,在cluster的解决方案主要目的是支持其场景的可扩展性和高可靠性(HA)。为了保证集群服务的稳定性,在集群部署中仍然需要考虑更多集群以外的保障问题,例如,添加了其他服务点的同时,集群服务器可以互相发现其新的集群点,如果其中一个node出现故障以后,集群网络能够自动智能地发现其工作状态,某些node之间的连接出现故障以后,集群机制如何能够智能地路由到正常的节点。这些都是在集群部署场景中必须考虑到要素。除了笔者前面讨论的这些问题以外,集群机制还要考虑存储方式的可扩展性和稳定性,包括未来为了保证集群采用的其他第三方的技术的成熟度等。
一些客户为了实现其高可靠性也使用其他的方式或者最新的方式来对VoIP平台进行管理,例如,SBC前端对接内网IPPBX,使用容器来实现自动化部署和备份处理,利用目前最新技术SD-WAN实现边缘智能终端的部署和管理来满足终端的配置要求。
OpenSIPS cluster集群讨论的主要问题
笔者在前面的章节中已经说明,在部署集群方案时一定要完整考虑整个方案的可行性,通过一定的论证,并且结合公司自己本身的资源来实现。部署方案尽量在自己本身可控的环境中实现,同时尽量降低对第三方工具的依赖。在部署OpenSIPS集群解决方案时,我们同样也面临这样的挑战-如何在一个可控的平台满足集群的要求。在一定资源和技术范围内,OpenSIPS基本上具备了集群解决方案的要求,用户可以实现用户的拓展性支持等功能。通过OpenSIPS本身的cluster 模块结合数据库的机制对集群方案实现支持。本章节中,笔者主要简单介绍关于OpenSIPS的集群的引擎,SIP用户集群服务器的共享注册的机制讨论,共享呼叫时dialog的讨论。OpenSIPS通过集群引擎和其他相关的支持协议实现注册共享集群处理,呼叫时dialog的共享处理机制。接下来的章节中笔者将讨论关于集群的定义。
OpenSIPS关于cluster集群的定义
OpenSIPS中集群是一个非常重要的模块,官方文档对其定义有非常详细说明,这里不再做太多的介绍。笔者可以查看OpenSIPS官方文档了解。我们这里的介绍是为了后续章节的内容做一个内容回顾,帮助读者能够快速了解其基本的定义。
简单来说,OpenSIPS的cluster 就是多个OpenSIPS 实例节点具有同样的配置文件,通过共享同样的配置文件实现多实例一体管理的机制,进一步来说,在OpenSIPS中,多个实例集群在一起看作一个整体平台。节点之间通过协议进行对接和数据同步。为了实现集群的统一性和同步能力,因此,每个节点必须通过共享数据库方式或者其他的自定义通道共享数据,这些数据可能包括:
各种记录,例如注册记录,dialog记录信息网关状态的分享,互相之间可以获悉周边节点的状态信息,包括是否出现故障,是否断开连接等。节点之间必须能够实时获悉周边节点的状态,能够及时智能地路由到其他相关节点。对用户属性文件计数和一些限制设置
OpenSIPS中集群使用的协议
针对OpenSIPS cluster 集群解决方案,OpenSIPS主要使用了binary protocol 通过TCP方式和集群节点进行通信。用户需要加载模块proto_bin.so ,通过异步方式实现节点之间的通信。其基本工作机制是通过心跳检测机制,在应用层不断对其他节点发送消息数据来获悉周边节点的状态,从而保证整个集群服务器之间的通信和数据共享。
OpenSIPS平台环境下的集群的拓扑讨论
集群部署涉及到整体集群节点的互联互通,不同节点和周边节点也必须保证其数据的稳定性和可连接性。另外,节点之间可以智能地自己发现自己周边的节点为将来中集群路由做最佳路径的路由做准备。
在节点之间的连接中,节点一定要那个对失效的连接进行重新路由设置,保证你连接能够抵达正确的节点。
集群平台增加了一个新的节点以后,其他周边的节点通过动态或者静态方式可以发现靠近自己的节点,例如,节点6。
集群cluster 动态和静态添加节点的实现方式
OpenSIPS的集群可以通过动态和静态两种方式来实现。在动态方式中,每个节点可以自己通过动态方式获悉周边节点。但是在动态方式中,节点启动管理就非常困难。动态用户节点之间需要非常好的同步配合并且需要经过一定的时间互相学习才能获得周边节点数据。配置方式如下:
loadmodule “proto_ bin.so"listen = bin:10.0.0.15:5555# node3 连接 节点 4配置loadmodule “dusterer.somodparam('clusterer”“my node id”,3) // 自己是node 3modparam(“clusterer” “db mode”,0)modparam’clustererl’my node info”,“cluster id=1, node id=3, urbin:10.0.0 155555”)# 邻居节点 node 4modparam"“cluster id=1, node id=4,urlbin:10.0.0.205555”)
在静态方式的配置中,在初始阶段,所有节点都清楚知道周边节点的状态,其部署拓扑场景是一种静态方式,它们都可以被重新加载。存储在数据库中的静态node 数据:
在后续的配置示例中,我们将通过OpenSIPS 控制界面静态添加几个节点的测试数据和节点IP地址。
OpenSIPS平台下SIP集群注册的实现方式
在前面章节中笔者已经说明,集群节点之间必须可以共享数据才能实现集群功能。SIP 用户注册集群的数据就是一个集群解决方案中使用比较广泛的示例。在大规模部署场景中,SIP用户可能发布在不同地区,通过不同的注册服务器进行注册,然后再进行呼叫。因此,OpenSIPS需要对其用户的位置进行管理。OpenSIPS通过集群注册的方式可以实现其灵活集群管理和部署。在集群注册的实现场景中,OpenSIPS需要同步注册信息,位置信息和数据库同步。Cluster通过数据库同步查询或者no SQL DB方式实现其注册用户的数据准确性。因为数据库的访问处理能力根据集群部署的逐步扩展,其处理性能也会面对很大的挑战,因此OpenSIPS在数据库支持方面通过数据库全共享方式和局部共享方式进行支持。
如上图所示,如果SIP 用户A 和SIP 用户B在不同的地区注册到不同的SIP服务器,通过同一VOIP运营商进行呼叫时,两个SIP用户实现需要进行验证,保证它们是注册成功的状态。在集群注册的环境中,运营商需要首先确认SIP 用户A注册到了一个SIP 服务器,SIP 用户B注册到了另外一个集群的SIP 服务器中,然后才允许它们之间的呼叫。因此,运营商需要把集群的SIP 服务器看作为一个整体SIP注册服务器。在OpenSIPS的集群注册的实现方式中,可以采用Full sharing (全共享数据)方式,也可以采用部分共享的方式(Federated-no SQL)来实现集群注册。接下来,笔者将逐一知道full sharing 的处理方式和部分共享的实现方式和各自的优缺点进行讨论。
OpenSIP平台关于full sharing的处理方式
OpenSIPS集群注册的部署方式中,Full sharing 或者全共享方式是集群注册的其中一种部署方式。对于full sharing来说,它主要包括几个基本的特性:
所有注册的SIP数据都保存到所有的注册节点(所以称之为全共享)通过BIN协议复制数据,通过usrloc模块存储数据所有节点可能会同步所有的节点数据节点需要对周边集群节点执行ping处理
加载集群注册的全共享模式示例如下:
loadmodule "usrloc.so"modparam(“usrloc”, “working_ mode_ _preset”,“full-sharing-cluster”)modparam(“usrloc”, “location cluster”, 1)
从cfg加载配置看的话,集群注册的看起来非常简单。其实,部署环境需要经过SBC的管理才能实现完整的高可靠性集群注册部署。很多情况下,一些节点可能存在NAT问题,不同的节点对NAT的配置也可能不同。为了完整实现对所有节点的支持,在集群注册的解决方案中需要通过SBC实现管理。SBC针对不同的NAT进行SIP头的管理。
如果其中几个节点出现故障以后,高可靠性解决方案仍然可以通过其他的节点数据进行注册,然后通过SBC进行调度策略的管理。
除了需要节点来进行全共享以外,各个节点需要不断进行ping处理,对其他的节点进行检测,通过ping(发送Option消息)获取其他节点状态。
在以上的示例中,节点3和节点6支持了内网NAT的两个分机(Alice和Bob)。如果两个节点出现故障或者其中一个节点出现故障以后,其他的节点(例如节点1和节点4)可以接管分机的注册。但是,我们部署任何解决方案都需要提前预知其优势和风险。在以上全共享的解决方案中,我们可以全共享复制所有的节点数据,针对中小型部署中的可靠性支持部署非常方便,我们仅需要OpenSIPS本身的技术架构可以完整实现全部的功能需求。但是,全共享部署方式也存在着一些需要注意到地方,例如,节点之间需要产生大量的option数据,解决方案本身缺乏集群注册的可拓展性(需要考虑数据库的集群)。随着注册用户的contact数据增加,每个节点的注册数据都需要复制,因此会增加数据库的负担,数据库的处理性能也会逐步降低。
OpenSIPS环境中Full share和noSQL DB的实现方式
在上面的章节中,笔者讨论了通过full sharing 实现全部节点数据的共享。当然,OpenSIPS启动以后,所有的数据都通过内存存储的方式实现数据查询。虽然内存存储的方式非常方便快捷,但是如果集群注册的用户不断增长的话,通过复制所有数据实现扩展的可能性会降低。另外一种相对支持扩展性比较好的方式是通过noSQL 数据库来存储数据。所有节点数据仍然对所有节点可见,数据存储在noSQL 数据库中。
另外,在noSQL 数据库处理的环境中,ping仍然是一个重要的节点状态通信工具。ping数据需要通过noSQL 数据库访问查询,可能通过外部的分布式数据库进行处理。因此,和通过内存获取ping状态数据的方式来说,显然,通过noSQL 数据库处理相对比较复杂。当然,和通过内存存储的方式相比,如果使用noSQL 数据库的话,用户仍然需要考虑分布式数据库的部署和数据的一致性处理。
因为节点之间的数据是通过noSQL 数据库实现的访问,并且节点之间也不存在数据同步的问题,因此,如果其中一个opensips 节点重新启动或者重新加载系统的话,节点之间的数据不会受到重新启动的影响。不像通过内存存储数据的方式,重新启动其中一个实例节点的话,全部节点的全部数据都需要进行同步处理。因此,相比前面章节中的通过内存方式存储的实现方式来说,通过noSQL 数据库外部处理以后,OpenSIPS的性能瓶颈会极大改善。用户可以对数据库进行优化和数据分区处理,根据业务需求对数据读写的控制,从而提升I/O性能,最终实现良好的可拓展性,并且能够比较好的支持高可靠性部署方式。当然,因为节点之间的ping 检测的需要,所有节点的option消息都会通过数据库进行查询处理,主要会导致数据库访问的瓶颈问题。如何优化大量的ping 数据查询需要读者进行更深度优化。针对,full sharing中使用noSQL 数据库实现数据存储的方式,其具体的加载方式比较简单:
loadmodule "usrloc.somodparam(“usrloc”, “working model preset”, "full-sharing-cachedb-clustemodparam(“usrloc”, “location cluster”, 1)modparam(“usrloc’, cachedb url”, "mongodb://localhost:27017/opensipsB.userlocatio
OpenSIPS环境下Federated-no SQL讨论
笔者花费了多个章节介绍在OpenSIPS环境中对集群注册使用full sharing 包括内存存储方式和noSQL 数据库存储方式的介绍和讨论,并且,笔者也详细说明了Full sharing中的一些优缺点。这些劣势实际上无论使用何种方式处理,它们仍然会面对数据大量复制所产生的网络瓶颈。这是Full sharing技术架构所带来的天生属性,没有其他办法可以避免网络数据所产生的连接问题。为了解决full sharing的根本问题,OpenSIPS在针对集群部署中使用了另外一种解决思路,这个解决办法就是使用Federated 和noSQL数据库配合的方式。Federated使用no SQL数据库的基本思路是:
每个节点仅保存自己本身的注册信息节点通过noSQL数据库共享meta data数据,在数据库中对AOR和节点进行映射匹配处理每个节点针对注册消息有属于自己的ping 方式,不再对全部节点进行数据广播Federated需要一个内部节点路由机制
通过以上基本思路,读者可以看出,使用Federated 结合noSQL数据库的话,可以降低数据库存储数量,可以降低内存中注册信息的存储依赖度,同时也可以降低对全节点广播所产生的ping消息数据,降低了网络拥塞的可能。但是,为了实现以上全部的优势,Federated需要一个内部节点的额外的路由功能。
通过以上讨论和介绍,如果使用基于Federated 使用noSQL 数据库实现的节点集群注册的话,因为对数据共享进行了最小的优化处理,它本身支持了尽可能少的数据共享,解决了IP的限制,支持了比较好的可拓展性,每个节点数据相对比较独立。这样处理的缺点当然也比较明显,用户需要对内部节点路由做失效处理,因为每个节点数据比较独立,同时需要对每个节点做备份处理,防止节点故障以后出现节点不能还原的问题。使用基于Federated 使用noSQL 数据库是加载方式如下:
loadmodule "usrloc. so"modparam(“usrloc”, “working_ mode preset”, “federation cachedb cluster”)modparam(“usrloc”, “location cluster”, 1)modparam(“usrloc”, “cachedb url”, “mongodb://localhost:27017/opensipsDB.userlocation”)
总结
本文章介绍了关于OpenSIPS平台中集群部署的背景知识和集群使用的几个主要场景,包括集群注册的处理,注册时使用的full sharing 内存处理,数据库处理的详解。另外针对Federated 使用noSQL 数据库方式对集群注册的思路也进行了讨论。用户在部署以上两种方式是需要考虑各自的优缺点,同时需要在部署过程中对外部数据库的优化和部署也要增加处理机制。在后续章节中,笔者将继续讨论呼叫中集群dialog的机制,并且会分享关于OpenSIPS 集群部署的设置,命令监控和具体的测试示例。
参考资料:
https://opensips.org/html/docs/modules/2.4.x/clusterer.html
https://www.researchgate.net/publication/261427896_Secure_cluster-based_SIP_service_over_Ad_hoc_networks/link/549dbcce0cf2fedbc31198cb/download
https://opensips.org/Documentation/Tutorials-Distributed-User-Location-Federation
https://blog.opensips.org/2018/03/27/clustering-presence-services-with-opensips-2-4/
www.freesbc.cn
www.asterisk.org.cn