Shou.TV 背后基于 Node.js 和 WebSocket 的技术架构

jopen 10年前

我们使用一个定制的基于WebSocket的协议SLSP来实现广播和直播。所有组件均由Nginx代理,部署于Ubuntu server上。组件间通过HTTP和JSON通讯。

Shou.TV 背后基于 Node.js 和 WebSocket 的技术架构Shou.TV 背后基于 Node.js 和 WebSocket 的技术架构

技术 

在Shou.TV,我们有如下几条“军规”。我们尽最大努力,在日常开发中坚守这些规定。

  • 在造轮子之前先选用已有解决方案中最好的那一个。工程师们都热爱自行造轮子。但是为了交付产品,我们需要快速地构建,并确保产品的稳定性。

  • 掌握核心技术。如果在我们的核心架构中引入第三方解决方案,我们应当尽最大的努力去理解各个方面。如果我们能力不足以理解该解决方案,或者该解决方案并不值得我们花时间去搞懂,那么就构建我们自己的解决方案。

  • 不要将核心技术绑定在一家供应商上。我们应当确保解决方案可以被移植到任何服务器上。

  • 尽可能快地完成非核心技术。使用任何一个可用的软件或解决方案。以后有时间的时候在去理解它。

根据这些规定,我们在Shou.TV使用下列技术。

  1. 从不同的供应商处租用VPS,例如EC2、GCE、Linode、Rackspace、DigitalOcean等等。

  2. 使用Ubuntu 14.04 LTS。它拥有最新的软件,并不像CentOS那样保守。

  3. 对网站、API、聊天室和广播服务器的所有请求,都经由Nginx,并开启SSL。

  4. 使用MongoDB作为主数据库。

  5. 使用Ruby on Rails开发网站和API服务器。

  6. 使用Socket.IO和Redis开发聊天室。

  7. 使用Node.js和FFmpeg开发了基于WebSocket的自定义广播协议——SLSP。

  8. 使用HLS支撑视频直播和视频回放。使用Video.js作为web播放器和Android视频播放器。

  9. 使用Google云存储来存档视频片段。

  10. 使用Amazon S3存储小资源,例如用户头像。

  11. 使用Git管理代码。使用Capistrano部署。 

网站和API

我们使用最新的Ruby on Rails和Unicorn来开发网站和客户端API。所有请求都经由Nginx和SSL代理。我们使用越来越多的memcached来应对持续增长的用户。数据库是一个MongoDB的集群。

我们还没有遇到大量的访问。所以在用户大量涌入时,我们无法确保可用性。但是我们已经设计了基于AWS Route 53和Elastic Load Balancing或者GCE Network Load Balancing的整套负载均衡架构。   

聊天室

聊天室是一个平衡负载后简单的Socket.IO服务器集群,它使用redis集群分发邮件和聊天室,使用相同的cookie和会话进行用户认证的主要网站。

网络聊天界面是使用Socket.IO的客户端库,iScroll.js和简单的jsrender模板库。

我们使用AndroidAsync图书馆建立Android的聊天室,有几个问题,我们已经做了一些补丁。

广播服务器

我们定义了一个基于WebSocket的自定义直播流媒体协议:SLSP,并只用了大约1000行Node.js和C语言代码实现。

原因是,RTMP非常旧,而且难于理解及使用大型、可用的HTTP解决方案,相比WebSocket或SLSP而言,它只是个“稳定”的骗局。我在多媒体开发领域有几年经验,但在Wowza或任何当前可用的RTMP服务器上,修复这类问题或实现自定义特性仍然感觉困难。

网络正快速革新,对所有人来讲,HTTP是一个更成熟、更容易理解的协议。我们有很多高性能的开源HTTP服务器,比如:nginx,具有非常高的性能且保持高稳定性。

WebSocket是一个长连接协议,适用于视频流。所有现代浏览器都支持WebSocket。WebSocket内置SSL,故而客户端和服务器端都不需要任何附加代码。WebSocket使用和HTTPS一样的443端口,因为可以穿越绝大多数防火墙。

SLSP,简而言之,如同一个WebSocket聊天室。只需要将服务器部署在Nginx代理之后,一旦WebSocket客户端向服务器发送持续的视频流,SLSP就会将视频流分段成数个HLS TS段,故而任何一个可用的HLS播放器都可以播放视频流了! 

WebSocket可以使用大量可用的高性能HTTP解决方案。SLSP是基于WebSocket的,理所当然我们也可以构建非常健壮的智能负载均 衡方案。如上图所示,无论何时我们启动一台新的SLSP服务器,它都会向负载均衡器注册自身。每一个SLSP服务器都会持续地向均衡器发送自身的状态,例 如服务器当前负载。 

当一个SLSP客户端想要去广播, 它首先要向负载均衡器请求一个SLSP服务器的地址,均衡器会基于潜在的服务器负载,选择一个最合适的SLSP服务器,然后客户端会直接发布视频流到SLSP服务器。

无论什么时候负载均衡器遇到高负载,它都会在几分钟内自动建立一个新的SLSP服务器, 并且我们还会进一步改进它。均衡器会移除空闲的SLSP服务器以节省开销。

广播结束之后,为了将来可以回放,服务器将会上传完整的流到Google云。

去更新吧

Shou.TV 仍然是一个很新的项目,它的用户不多,因此我们还没有验证在高负载下的情形。我们将会持续改进和发布更多细节。