【发布时间】:2015-10-29 03:24:46
【问题描述】:
有一些 SIP 服务器可以处理几千个订阅者,而另一些可以处理具有类似底层硬件的数百万个订阅者。实现能够处理如此大量流量的 SIP 服务器需要考虑哪些设计和开发因素?
【问题讨论】:
标签: sip voip pjsip sip-server
有一些 SIP 服务器可以处理几千个订阅者,而另一些可以处理具有类似底层硬件的数百万个订阅者。实现能够处理如此大量流量的 SIP 服务器需要考虑哪些设计和开发因素?
【问题讨论】:
标签: sip voip pjsip sip-server
首先,我假设您对构建自己的 SIP 信令应用程序感兴趣,因此您的问题是针对 SIP 应用程序服务器以及在它们之上运行的应用程序。我不会谈论像 Asterisk 这样的产品。对于包含 SIP servlet 容器的 Java 应用程序服务器,没有太多选择。基本上三巨头是 IBM 的 WebSphere 服务器、Oracle 的通信服务器和 Mobicents。我最熟悉 WebSphere,您可以在 www.wasdev.net 免费下载它,但我确信所有这些产品都可以很好地在信令方面进行扩展。远远超过几千个端点,如果您愿意将可以支持的服务器集群到每秒数千个调用中,则相当容易。这就是 AT&T 等一级供应商将其 Voip 服务扩展到大量端点的方式。
如果您在问题中包含媒体处理,那么您很快就会开始遇到可扩展性问题。服务器端媒体处理(录制/播放、多路混合、SFU 等)可能是处理器密集型的。在 SIP servlet 世界中,媒体服务器通过媒体控制 API (JSR 309) 进行控制,该 API 将信令平面从媒体平面描绘出来。因此,如果不进一步了解您的 SIP 服务器需要托管的应用程序类型,就很难回答您的问题。
有很多因素会影响依赖于 SIP servlet 容器的 SIP servlet 应用程序的可伸缩性。线程是关键。您要确保您永远不会阻塞应用程序代码中的线程。一切都必须是异步的才能扩展。对于不习惯编写异步代码的开发人员来说,这可能需要一点时间来适应,但在进行任何实时信号开发之前弄清楚这一点至关重要。在 Java 服务器方面,您还希望调整 JVM 以获得最佳结果。这不仅仅是确保您有足够的堆空间来容纳服务器必须支持的每秒调用数。有许多 JVM 垃圾收集 (GC) 旋钮可以转动以调整 Nursery 大小等。GC 配置适合您的服务器至关重要。大多数 JVM 还具有特定的 GC 算法,旨在更好地为实时应用程序工作。例如,与 IBM WebSphere 一起使用的 JVM 支持一种称为节拍器的 GC 算法,该算法以 GC 活动换取低延迟。
这是一个巨大的主题,所以如果您能提供更多关于您尝试使用 SIP 服务器完成的任务的详细信息,我可能会提供更多见解。
【讨论】:
从纯标准 -rfc3261- 的角度来看,SIP 服务器处理 SIP 流量的目的是路由(查找用户或其他服务器),仅此而已。我假设我们在这里讨论的是 SIP 代理服务器。
传入的请求在 SIP 服务器上使用 stateful 或 stateless 模式进行处理。
您可以从 rfc3261 中获得两者的定义:
Stateful Proxy: A logical entity that maintains the client and
server transaction state machines defined by this specification
during the processing of a request, also known as a transaction
stateful proxy. The behavior of a stateful proxy is further
defined in Section 16. A (transaction) stateful proxy is not
the same as a call stateful proxy.
Stateless Proxy: A logical entity that does not maintain the
client or server transaction state machines defined in this
specification when it processes requests. A stateless proxy
forwards every request it receives downstream and every
response it receives upstream.
进入有状态代理服务器的传入 SIP 请求通常会存在很短的时间。这个持续时间通常很短。例如,路由 BYE 将需要分配 2 个事务:一个传入和一个传出。如 rfc3261 的 图 6 和 图 8 中所述,它将一直存在于内存中,直到两者都达到“终止”状态。使用 TCP,Timer J 和 Timer K 为 0 秒,因此,理论上的持续时间比接收答案的时间长一点。对于 UDP,Timer J 为 32 秒,因此,分配的事务上下文必须在收到最后一个答案后至少存在 32 秒(以处理重传)。
为了优化内存,走得更快,可以使用无状态处理。然而,这意味着重传将需要一个新的计算来找出与第一次处理完全相同的结果。在高丢失或低流量的情况下,与有状态模式相比,这会增加 CPU 使用率。无状态模式还要求始终以完全相同的方式处理请求,并且通常用于拒绝不需要的/损坏的流量:这可能(?)帮助,例如抵抗 DDOS 攻击,拒绝有语法问题的消息,或拒绝禁止的流量。
当然,下一个问题是关于实现的:你需要使用一个好的操作系统、好的线程、好的异步非阻塞 DNS 或套接字操作、关心内存使用、分配等等......
您报告说存在处理数千个订阅者和其他数百万个订阅者的服务器:事实上,没有理由真正的代理 SIP 服务器不能处理数百万个(当然,如果编码良好)。处理“仅”几千个订阅者的服务器通常充当端点(如星号):它们根本不是 rfc3261 中描述的 SIP 服务器,即:SIP 代理服务器。
作为旁注,即使是真正的代理服务器通常也能够欺骗并插入媒体中继:处理 RTP 中继。虽然现在这是处理媒体建立所必需的(如果您没有 ICE),但这会在带宽方面引入严重限制:95%(或其他?)的流量将变为 RTP 而不是仅 SIP,带宽将是您的服务器的限制。
当然,查看与 ser 相关的项目(ser、kamailio、opensips...)将展示上述所有内容:
【讨论】: