容错VoIP流量平衡。 高峰时间在数据中心之间进行负载切换

关于我们做什么的几句话。 DINS致力于为企业客户在国际市场上开发和支持UCaaS服务。 小型公司,初创公司以及大型企业都使用该服务。 客户端通过TCP,TLS或WSS上的SIP协议通过Internet连接。 这造成了相当大的负载:来自终端设备的近150万个连接-Polycom / Cisco / Yealink电话以及PC / Mac / IOS / Android的软件客户端。


在本文中,我将讨论VoIP入口点的排列方式。


背景知识


在系统外围(在终端设备和内核之间)是商用SBC(会话边界控制器)。


自2012年以来,我们一直使用Acme Packet的解决方案,后来被Oracle收购。 在此之前,我们使用了NatPASS。


简要列出我们使用的功能:


•NAT遍历;
•B2BUA;
•SIP规范化(允许/禁止的标头,标头操作规则等)
•TLS和SRTP卸载;
•传输转换(在系统内部,我们使用基于UDP的SIP);
•MOS监控(通过RTCP-XR);
•ACL,Bruteforce检测;
•由于接触过期时间的增加而减少了注册流量(访问端的过期时间低,核心端的访问量高);
•按方法的SIP消息限制。


商业系统具有明显的优点(即装即用的功能,商业支持)和缺点(价格,交货时间,缺乏机会或实施我们所需的新功能的期限太长,解决问题的期限等)。 逐渐地,缺陷开始被弥补,并且很明显,开发我们自己的解决方案的需求已经成熟。


一年半前开始开发。 在边界子系统中,我们传统上区分两个主要组件:SIP和媒体服务器; 每个组件上方的负载均衡器。 我在这里研究入口点/平衡器,因此我将尝试谈论它们。


要求条件


  • 容错:如果数据中心或整个数据中心中的一个或多个实例发生故障,系统应提供服务
  • 可维护性:我们希望能够将负载从一个数据中心切换到另一个数据中心
  • 可扩展性:我想快速而廉价地增加容量

平衡


我们在IPIP(流量隧道)模式下选择了IPVS(又名LVS)。 我将不对NAT / DR / TUN / L3DSR进行比较分析(例如,您可以在此处阅读有关模式的信息 ),我仅提及原因:


  • 我们不想对后端施加与LVS处于同一子网的要求(池包含来自我们自己和远程数据中心的后端);
  • 后端必须接收客户端的原始源IP(或其NAT),换句话说,源NAT不适合;
  • 后端必须支持同时与多个VIP一起工作。

我们正在平衡媒体流量(事实证明这很困难,我们将拒绝),因此数据中心中的当前部署方案如下:



当前的IPVS平衡策略是“ sed”(最短的预期延迟),更多。 与加权轮循/加权最少连接不同,它允许您在达到特定阈值之前不将流量传输到权重较低的后端。 最短的预期延迟是使用公式(Ci +1)/ Ui计算的,其中Ci是后端i上的连接数,Ui是后端的权重。 例如,如果池中有权重为50,000和2的后端,则第一个连接将分配新的连接,直到每个服务器达到25,000个连接或达到阈值(连接总数的限制)为止。
阅读有关man ipvsadm中的平衡策略的更多信息。


IPVS池如下所示(此处和下面列出了虚拟IP地址):


# ipvsadm -ln Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 1.1.1.1:5060 sed -> 10.11.100.181:5060 Tunnel 50000 5903 4 -> 10.11.100.192:5060 Tunnel 50000 5905 1 -> 10.12.100.137:5060 Tunnel 2 0 0 -> 10.12.100.144:5060 Tunnel 2 0 0 

VIP上的负载分配给权重为50,000的服务器(它们与特定的LVS实例部署在同一数据中心中),如果它们超载或进入黑名单,则负载将转到池的备份部分-权重为2的服务器,位于邻近的数据中心。


在相邻的数据中心中配置了完全相同的池,但是规模却相反(在生产系统上,后端的数量当然要大得多)。


通过ipvs sync同步连接可以使备用LVS知道所有当前连接。


对于数据中心之间的同步,应用了一种“脏”技术,但效果很好。 IPVS同步仅通过多播工作,这对我们来说很难正确地传递到相邻的DC。 代替多播,我们通过iptables目标TEE复制从ipvs主站到ip-ip隧道到相邻DC中服务器的同步流量,并且可能有多个目标主机/数据中心:


 #### start ipvs sync master role: ipvsadm --start-daemon master --syncid 10 --sync-maxlen 1460 --mcast-interface sync01 --mcast-group 224.0.0.81 --mcast-port 8848 --mcast-ttl 1 #### duplicate all sync packets to remote LVS servers using iptables TEE target: iptables -t mangle -A POSTROUTING -d 224.0.0.81/32 -o sync01 -j TEE --gateway 172.20.21.10 # ip-ip remote lvs server 1 iptables -t mangle -A POSTROUTING -d 224.0.0.81/32 -o sync01 -j TEE --gateway 172.20.21.14 # ip-ip remote lvs server 2 #### start ipvs sync backup role: ipvsadm --start-daemon backup --syncid 10 --sync-maxlen 1460 --mcast-interface sync01 --mcast-group 224.0.0.81 --mcast-port 8848 --mcast-ttl 1 #### be ready to receive sync sync packets from remote LVS servers: iptables -t mangle -A PREROUTING -d 224.0.0.81/32 -i loc02_srv01 -j TEE --gateway 127.0.0.1 iptables -t mangle -A PREROUTING -d 224.0.0.81/32 -i loc02_srv02 -j TEE --gateway 127.0.0.1 

实际上,我们的每台LVS服务器都同时扮演两个角色(主服务器和备用服务器),这很方便,因为它消除了切换流量时的角色变化,另一方面,这是必需的,因为每个DC默认情况下都会处理其组流量公众贵宾。


数据中心之间的负载切换


在正常操作中,每个公用IP地址都可以从Internet上的任何地方(在此图中从两个数据中心)发布。 目前,使用BGP属性MED(多出口鉴别符)为主动DC和备用DC设置不同的值,将传入VIP的流量路由到我们目前需要的DC。 同时,如果活动DC发生故障,Backup DC始终准备接受流量:



通过更改BGP MED的值并使用跨位置IPVS-sync,我们有机会将流量从一个数据中心的后端无缝地传输到另一个数据中心,而不会影响已建立的电话,这早晚会自然终止。 该过程是完全自动化的(对于每个VIP,我们在管理控制台中都有一个按钮),如下所示:


  1. SIP-VIP在DC1(左)中处于活动状态,DC2(右)中的集群是冗余的,这要归功于ipvs-synchronization,它在其内存中具有有关已建立连接的信息。 左侧宣布活动VIP的价值为MED 100,右侧-宣布价值为500:


  2. 开关按钮引起了所谓的变化 “ Target_state”(内部概念,它在给定时间声明BGP MED的值)。 这里我们不希望DC1处于正常状态并准备好处理流量,因此DC2中的LVS进入“强制激活”状态,将MEDs值降低到50,从而将流量拖到自身上。 如果DC1中的后端处于活动状态且可用,则呼叫不会中断。 所有新的tcp连接(注册)将发送到DC2中的后端:


  3. DC1收到了新的target_state复制,并设置了备份值MEDs(500)。 当DC2发现此问题时,将对其值进行归一化(50 => 100)。 它仍然等待DC1中所有活动调用的完成并中断已建立的tcp连接。 DC1中的SBC实例将必要的服务引入了所谓的 “正常关机”状态:“ 503”响应下一个SIP请求并断开连接,但不接受新连接。 同样,这些实例也被列入LVS的黑名单中。 断开时,客户端建立一个新的注册/连接,该注册/连接已在DC2中出现:


  4. DC2中的所有流量都将结束该过程。


  5. DC1和DC2切换角色。



事实证明,在入口点持续承受高负载的情况下,能够随时切换流量非常方便。 如果备用DC突然开始接收流量,则相同的机制将自动启动。 同时,为了防止拍打,仅在一个方向上触发一次切换,并且将锁设置为自动切换,要移除它,需要人工干预。


里面有什么


VRRP集群和IPVS管理器:保持生命力。 Keepalived负责在群集内交换VIP,以及后端健康检查/列入黑名单。


BGP堆栈:ExaBGP。 他负责通告通往VIP地址的路由,并粘贴相应的BGP MED。 由管理服务器完全控制。 正在积极开发用Python编写的可靠BGP守护程序;它可以100%执行其任务。


管理服务器(API /监视/子组件管理):Pyro4 + Flask。 它是用于Keepalived和ExaBGP的资源调配服务器,管理所有其他系统设置(sysctl / iptables / ipset / etc),提供监视(gnlpy),按需添加和删除后端(它们与API通信)。


人物


具有四核Intel Xeon Gold 6140 CPU @ 2.30GHz的虚拟机可提供300Mbps / 210Kpps的流量(媒体流量,通过它们处理大约3000个高峰时间的同时呼叫)。 同时CPU利用率-60%。


现在,这足以支持多达10万个终端设备(台式电话)的流量。 为了服务所有流量(超过一百万个终端设备),我们在几个数据中心中构建了大约10对这样的集群。

Source: https://habr.com/ru/post/zh-CN436404/


All Articles