作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.
Gergely卡尔曼
验证专家 在工程

Gergely曾担任Alexa 50强网站的首席开发人员,该网站每月有数百万独立访问者.

以前在

环球音乐集团
分享

色情是一种 大工业. 互联网上没有多少网站可以与它最大的竞争者的流量相媲美.

应付如此庞大的交通是很困难的. 让事情变得更加困难, 色情网站提供的大部分内容都是由低延迟的实时视频流组成,而不是简单的静态视频内容. 但对于所有涉及的挑战,我很少读到关于 python开发人员 谁来对付他们?. 所以我决定写一下我自己的工作经历.

有什么问题吗??

几年前,我是 工作 这是世界上访问量最大的第26个网站(当时)——不仅仅是色情行业,而是整个世界.

当时, 该网站通过实时消息协议(RTMP)提供色情视频流请求。. 更具体地说, 它使用了Flash Media Server (FMS)解决方案, 由Adobe公司建造, 为用户提供直播. 基本流程如下:

  1. 用户请求访问某个直播流
  2. 服务器以播放所需素材的RTMP会话作为响应

有几个原因, FMS对我们来说不是一个好的选择, 先从成本说起, 其中包括购买两者:

  1. Windows许可用于我们运行FMS的每台机器.
  2. ~$ 4,000 fms专用许可证, 由于我们的规模,我们不得不购买数百个(每天更多).

所有这些费用开始逐渐增加. 撇开成本不谈,FMS是一款缺乏的产品,尤其是在功能方面(稍后会详细介绍)。. 所以我决定放弃FMS,从头开始编写自己的Python RTMP解析器.

最后,我设法使我们的服务效率提高了大约20倍.

开始

这里涉及两个核心问题:首先, RTMP和其他Adobe协议和格式未打开(i.e.(可公开获取),这使得它们很难与之合作. 如何以您一无所知的格式反转或解析文件? 幸运的是, 在公共领域有一些逆转的努力(不是由Adobe制作的), 而是由一个叫做OS Flash的组织开发的, (现在已经不存在了)我们工作的基础.

注:Adobe后来发布了“规范,其中包含的信息并不比非adobe制作的反向维基和文档中已经披露的更多. 他们(Adobe)的规范质量低得离谱,却成功了 几乎不可能真正使用他们的库. 此外,协议本身有时似乎是有意误导. 例如:

  1. 他们使用29位整数.
  2. 它们包括无处不在的带有大端格式的协议头——除了一个特定的(尚未标记的)字段, 哪个是小端dian.
  3. 当传输9k视频帧时,他们以计算能力为代价将数据压缩到更小的空间中, 这几乎没有意义, 因为他们一次挣回的是比特或字节——对于这样的文件大小来说,这是微不足道的.

其次:RTMP是高度面向会话的, 这使得传入流实际上不可能多播. 在理想的情况下, 如果多个用户想观看同一个直播流, 我们可以将它们传递回指针,指向正在播放流的单个会话(这将是多播视频流)。. 但是对于RTMP, 我们必须为每个想要访问的用户创建一个全新的流实例. 这完全是浪费.

三个用户演示了多播视频流解决方案和FMS流问题之间的区别.

我的多播视频流解决方案

考虑到这一点,我决定将典型的响应流重新打包/解析为 FLV“标签” (其中“标签”只是一些视频,音频或元数据). 这些FLV标签可以在RTMP中传播,没有什么问题.

这种方法的好处:

  1. 我们只需要重新打包一个流一次(重新打包是一场噩梦,因为缺少上面提到的规范和协议怪癖).
  2. 只要给客户端提供一个FLV头,我们就可以在客户端之间重用任何流,而且问题很少, 而指向FLV标签的内部指针(以及某种偏移量来指示它们在流中的位置)允许访问内容.

我开始使用当时我最熟悉的语言:C进行开发. 随着时间的推移, this choice became cumbersome; so I started learning the basics of Python while porting over my C code. 开发过程加快了,但在几个演示之后,我很快就遇到了 资源枯竭问题. Python的套接字处理并不是为了处理这些类型的情况:特别是, 在Python中,我们发现每个动作需要进行多个系统调用和上下文切换, 增加了大量的开销.

提高视频流性能:混合Python、RTMP和C

在分析代码之后, 我选择将性能关键函数转移到完全用C编写的Python模块中. 这是相当低级的东西:具体来说,它利用了内核的 epoll 提供对数增长顺序的机制.

在异步套接字编程中,有一些工具可以为您提供有关给定套接字是否可读/可写/错误填充的信息. 在过去, 开发人员使用select()系统调用来获取这些信息, 规模很糟糕. Poll()是select的更好版本, 但它仍然不是那么好,因为你必须在每次调用时传递一堆套接字描述符. 

Epoll很神奇,因为你所要做的就是注册一个套接字,系统就会记住那个独特的套接字, 内部处理所有细节. 因此,每次调用都没有传递参数的开销. 它还具有更好的可伸缩性,并且只返回您关心的套接字, 比起运行一个包含100k套接字描述符的列表来查看它们是否具有带位掩码的事件(如果您使用其他解决方案,则需要这样做),哪一种方式更好.

而是为了提高性能, 我们付出了代价:这种方法遵循了与以前完全不同的设计模式. The site’s previous approach was (if I recall correctly) one monolithic process which blocked on receiving and sending; I was developing an event-driven solution, 所以我不得不重构剩下的代码来适应这个新模型.

具体地说, 在我们的新方法中, 我们有一个主循环, 其接收和发送处理如下:

Python视频流解决方案使用了RTMP的组合, FLV“标签”和多播视频流.

  1. 接收到的数据(作为消息)向上传递到RTMP层.
  2. 解剖RTMP,提取FLV标签.
  3. FLV数据被发送到缓冲和组播层, 是谁组织了流并填充了发送者的低级缓冲区.
  4. 发送方为每个客户端保留一个结构体, 带有最后发送的索引, 并尝试向客户发送尽可能多的数据.

这是一个滚动的数据窗口, 并且包含了当客户端接收太慢时丢弃帧的一些启发式方法. 一切都很顺利.

系统级、体系结构和硬件问题

但是我们遇到了另一个问题:内核的问题 上下文切换 我们变成了负担. 因此,我们选择每100毫秒写入一次,而不是立即写入一次. 这就聚集了较小的数据包,并防止了上下文切换的爆发.

也许更大的问题存在于服务器体系结构领域:我们需要一个负载平衡和故障转移功能的集群——由于服务器故障而丢失用户并不有趣. 起初, 我们采用了独立董事的方式, 在这种情况下,一个指定的“导演”会试图通过预测需求来创造和破坏广播节目. 但这次失败了. 事实上,我们所尝试的一切都失败了. 最后, 我们选择了一种相对蛮力的方法,在集群的节点之间随机共享广播器, 等于流量.

这个工作, 但有一个缺点:虽然一般情况下处理得很好, 当网站上的每个人(或不成比例的用户)都观看一个广播时,我们看到了糟糕的表现. 好消息是:这种情况绝不会发生在营销活动之外. 我们实现了一个单独的集群来处理这个场景, 但事实上,我们认为为了营销而破坏付费用户的体验是毫无意义的, 这并不是一个真正的场景(尽管处理所有可能的情况会很好)。.

结论

来自最终结果的一些统计数据:集群上的日流量在峰值时约为10万用户(负载为60%), 平均~50k. I managed two clusters (HUN and US); each of them handled about 40 machines to share the load. 集群的聚合带宽约为50 Gbps, 他们在峰值负载时使用了大约10gbps. 最后, I managed to push out 10 Gbps/machine easily; theoretically1, 这个数字可能会高达每台机器30 Gbps, 这意味着大约有30万用户同时从一台服务器上观看流媒体.

现有的FMS集群包含200多台机器, 这些可以被我的15个代替,只有10个能做实际工作. 这给了我们大约200/10 = 20倍的改进.

也许我从Python视频流项目中得到的最大收获是,我不应该让自己被必须学习新技能的前景所阻止. 特别是, Python, 代码转换, 以及面向对象编程, 在承担这个多播视频项目之前,我的所有概念都是非常专业的吗.

这一点,以及推出自己的解决方案可以带来巨大的回报.

1 晚些时候, 当我们将代码投入生产时, 我们遇到了硬件问题, 因为我们使用的是老式的sr2500英特尔服务器,由于其PCI带宽较低,无法处理10 Gbit以太网卡. 而不是, 我们在1-4x1 Gbit以太网绑定中使用它们(将几个网络接口卡的性能聚合到一个虚拟卡中). 最终, 我们有一些较新的sr2600 i7英特尔, 在没有任何性能问题的情况下通过光学传输10gbps. 所有预测的计算都涉及到这个硬件.

聘请Toptal这方面的专家.
现在雇佣
Gergely卡尔曼

Gergely卡尔曼

验证专家 在工程

西班牙马拉加

2016年4月4日成为会员

作者简介

Gergely曾担任Alexa 50强网站的首席开发人员,该网站每月有数百万独立访问者.

作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.

以前在

环球音乐集团

世界级的文章,每周发一次.

输入您的电子邮件,即表示您同意我们的 隐私政策.

世界级的文章,每周发一次.

输入您的电子邮件,即表示您同意我们的 隐私政策.

Toptal开发者

加入总冠军® 社区.