本文概述
- 介绍
- 有什么问题?
- 入门
- 我的多播视频流解决方案
- 提高视频流性能:混合使用Python, RTMP和C
- 系统级, 体系结构和硬件问题
- 总结
并且要处理这种巨大的流量非常困难。更麻烦的是, 色情网站提供的大部分内容都是由低延迟的实时视频流组成, 而不是简单的静态视频内容。但是对于所涉及的所有挑战, 我很少了解承担这些挑战的python开发人员。因此, 我决定写自己的工作经历。
有什么问题? 几年前, 我在世界上访问量排名第26(当时)的网站上工作, 而不仅仅是色情行业:世界。
当时, 该网站使用实时消息协议(RTMP)满足了色情视频流请求。更具体地说, 它使用了Adobe构建的Flash Media Server(FMS)解决方案, 为用户提供实时流。基本过程如下:
- 用户请求访问某些直播
- 服务器回复播放所需素材的RTMP会话
- 我们在其上运行FMS的每台计算机的Windows许可证。
- 约$ 4K FMS专用许可, 由于我们的规模, 我们不得不购买其中的数百个(每天都更多)。
最后, 我设法使我们的服务效率提高了大约20倍。
入门 涉及两个核心问题:首先, RTMP和其他Adobe协议和格式未公开(即公开可用), 这使它们难以使用。如何以一种你一无所知的格式反向或解析文件?幸运的是, 我们的工作基于公共领域(不是由Adobe而是由OS Flash组成的, 现已不存在的组织)做出的一些逆转努力。
注意:Adobe后来发布了” 规范” , 其中所包含的信息没有在非Adobe生产的反向Wiki和文档中公开的信息。他们的(Adobe)规范质量低得令人荒唐, 几乎无法实际使用他们的库。此外, 该协议本身有时似乎是有意误导的。例如:
- 他们使用29位整数。
- 它们包括带有大字节序格式的协议标头, 处处都是大字节序格式, 除了特定(尚未标记)字段(小字节序)外。
- 他们在传输9k视频帧时以计算能力为代价将数据压缩到更少的空间中, 这几乎没有意义, 因为它们一次赚回了比特或字节, 对于这种文件大小而言, 这是微不足道的。
文章图片
我的多播视频流解决方案 考虑到这一点, 我决定将典型的响应流重新打包/解析为FLV” 标签” (“ 标签” 只是一些视频, 音频或元数据)。这些FLV标签可以在RTMP内传输, 几乎没有问题。
这种方法的好处:
- 我们只需要重新打包一次流(由于缺少上面概述的规范和协议怪癖, 重新打包是一场噩梦)。
- 我们可以为客户之间的任何流重新使用, 只需为它们提供FLV标头即可, 而只需要为它们提供很少的问题, 而指向FLV标签的内部指针(以及某种偏移量则表明它们在流中的位置)允许访问内容。
提高视频流性能:混合使用Python, RTMP和C 在对代码进行性能分析之后, 我选择将性能关键的功能移到完全用C编写的Python模块中。这是相当底层的内容:具体地说, 它利用内核的epoll机制来提供对数增长顺序。
在异步套接字编程中, 有一些工具可以为你提供给定套接字是否可读/可写/错误填充的信息。过去, 开发人员使用select()系统调用来获取此信息, 该信息的伸缩性很差。 Poll()是select的一个更好的版本, 但是它仍然没有那么好, 因为你每次调用时都必须传入一堆套接字描述符。
Epoll令人惊叹, 因为你要做的就是注册一个套接字, 系统会记住该套接字, 并在内部处理所有详细信息。因此, 每次调用都没有传递参数的开销。它还具有更好的伸缩性, 并且只返回你关心的套接字, 这比遍历100k套接字描述符的列表来查看它们是否具有带位掩码的事件要好得多, 如果使用其他解决方案, 则需要这样做。
但是, 为了提高性能, 我们付出了代价:这种方法采用了与以前完全不同的设计模式。该网站以前的方法(如果我没记错的话)是一个整体流程, 该流程在接收和发送时受阻;我当时正在开发一个事件驱动的解决方案, 因此我必须重构其余的代码以适应这个新模型。
具体来说, 在我们的新方法中, 我们有一个主循环, 它按以下方式处理接收和发送:
文章图片
- 接收到的数据(作为消息)一直传递到RTMP层。
- 解剖RTMP并提取FLV标签。
- FLV数据被发送到缓冲和多播层, 由缓冲层和多播层组织流并填充发送者的低级缓冲区。
- 发送方为每个客户端保留一个结构, 并带有最后发送的索引, 并尝试向客户端发送尽可能多的数据。
系统级, 体系结构和硬件问题 但是我们遇到了另一个问题:内核的上下文切换正成为一种负担。结果, 我们选择仅每100毫秒写入一次, 而不是立即写入。这聚集了较小的数据包并防止了上下文切换的爆发。
也许更大的问题在于服务器体系结构领域:我们需要一个负载平衡和具有故障转移功能的群集-由于服务器故障而导致用户流失并不是一件好事。最初, 我们采用了独立导演方法, 即指定的” 导演” 将尝试通过预测需求来创建和销毁广播公司的供稿。这失败了。实际上, 我们尝试的所有操作都相当失败。最后, 我们选择了一种相对蛮力的方法, 在群集节点之间随机共享广播者, 以平衡流量。
这行得通, 但有一个缺点:尽管一般情况下处理得很好, 但当站点上的每个人(或不成比例的用户)观看单个广播电台时, 我们看到了糟糕的性能。好消息:这绝不会在营销活动之外发生。我们实施了一个单独的集群来处理这种情况, 但实际上, 我们认为破坏付费用户的体验以进行营销工作是没有意义的—实际上, 这并不是真正的情况(尽管处理所有可以想象的情况都很好)案件)。
总结 来自最终结果的一些统计数据:群集上的每日流量在高峰时(负载为60%)约为10万用户, 平均约为50, 000。我管理两个集群(HUN和US);他们每个人处理大约40台机器来分担负载。群集的总带宽约为50 Gbps, 在峰值负载时, 它们使用的带宽约为10 Gbps。最后, 我设法轻松地将每台机器的速度提高了10 Gbps。理论上1, 这个数字可能高达每台机器30 Gbps, 这意味着大约30万用户同时从一台服务器观看流。
现有的FMS集群包含200台以上的计算机, 可以替换为我的15台计算机, 其中只有10台可以完成任何实际工作。这使我们大致提高了200/10 = 20倍。我可能从Python视频流传输项目中获得的最大收获是, 我不应该因为必须学习新技能而受挫。尤其是, Python, 转码和面向对象的编程都是所有概念, 在从事此多播视频项目之前, 我具有非常专业的经验。
那, 以及推出自己的解决方案可能会付出巨大的代价。
【我如何通过Python视频流使Porn效率提高20倍】1后来, 当我们将代码投入生产时, 我们遇到了硬件问题, 因为我们使用的旧sr2500 Intel服务器由于PCI带宽低而无法处理10 Gbit以太网卡。取而代之的是, 我们将它们用于1-4× 1 Gbit以太网绑定(将多个网络接口卡的性能汇总为虚拟卡)。最终, 我们得到了一些较新的sr2600 i7 Intel, 它们在光学上可提供10 Gbps的传输速度, 而没有任何性能纠结。所有预计的计算都参考此硬件。
推荐阅读
- 不断进步(使用此开源代码执行自己的队列分析)
- 终极优化!数千个并发请求
- Trie数据结构(被忽视的宝石)
- 深度学习教程(从感知器到深度网络)
- python|第二届网刃杯网络安全大赛(re部分)
- html|html css js php python_#3。使用HTML+CSS+JS制作网页,使用Python mask框架(一),htmlcssjs,番外篇,pythonflask,I...
- 测试|django管理后台--models 模型层
- django|Django xadmin快速搭建后台管理系统(一)
- 创建在类路径资源[applicationcontext]中定义名为“工厂”的bean时出错。:在设置bean属性“dataSource”时,无法解析对bean“dataSource”的引用;嵌套异常是