网络协议(七)-流媒体协议(网络直播当中的视频压缩与传播问题)

1. 视频压缩

网络直播,视频压缩是一个很关键的技术,因为假设每一张图片大小为1024 * 768,每个像素由RGB组成,其中每个占8位,共24位。那么每秒钟的视频大小为:

30帧 x 1024 x 768 x 24 = 70,778,880 Bytes
如果一分钟的视频,就已经是4个G了。

解决的方式是编码,通过对图片的压缩,使播放的时候画面看起来仍然足够精美。

1.1 视频和图片压缩过程特征

1.1.1 空间冗余

图像的相邻像素之间有较强的相关性,一张图片相邻像素往往是渐变的,不是突变的,没必要每个像素都完整地保存,可以隔几个保存一个,中间的用算法计算出来。

1.1.2 时间冗余

视频序列的相邻图像之间内容相似。一个视频中连续出现的图片也不是突变的,可以根据已有的图片进行预测和推断。

1.1.3 视觉冗余

人的视觉系统对某些细节不敏感,因此不会每一个细节都注意到,可以允许丢失一些数据。

1.1.4 编码冗余

不同像素值出现的概率不同,概率高的用的字节少,概率低的用的字节多

整个压缩过程如下图所示:

fig1.jpg

1.2 视频编码的两大种类/ 流派

1.2.1 ITU International Telecommunications Union

VCEG(Video Conding Experts Group),视频编码,侧重于传输

1.2.2 ISO International Standards Organization

MPEG(Moving Picture Experts Group),视频存储

1.2 网络直播

网络协议将编码好的视频流,从主播端推送到服务器,在服务器上有个运行了同样协议的服务端来接收这些网络包,从而得到里面的视频流。

服务端接到视频流以后,对视频流进行转码,保证用各种客户端都能看到直播。

如果有非常多的观众,同时看一个视频直播,都从一个服务器上拉流,压力太大了,因而需要一个视频的分发网络,将视频预先加载到就近的边缘节点,来降低服务器的压力。

fig2.jpg

1.3 视频图片压缩过程详解

1.3.1 编码

会将视频序列分为三种帧,来分别进行压缩行为:

  • I 帧

也称关键帧。里面是完整的图片,只需要本帧数据,就可以完成解码。

  • P 帧

前向预测编码帧。P 帧表示的是这一帧跟之前的一个关键帧(或 P 帧)的差别,解码时需要用之前缓存的画面,叠加上和本帧定义的差别,生成最终画面。

  • B 帧

双向预测内插编码帧。B 帧记录的是本帧与前后帧的差别。要解码 B 帧,不仅要取得之前的缓存画面,还要解码之后的画面,通过前后画面的数据与本帧数据的叠加,取得最终的画面。

可以看出,I 帧最完整,B 帧压缩率最高,而压缩后帧的序列,应该是在 IBBP 的间隔出现的。这就是通过时序进行编码

fig3.jpg

在一帧中,分成多个片,每个片中分成多个宏块,每个宏块分成多个子块,这样将一张大的图分解成一个个小块,可以方便进行空间上的编码。

帧 -> 片 -> 宏块 -> 子块

编码后的整个序列是要压缩为一个二进制流在网络上传播的,因此需要分割成一个个网络提取单元(NALU, network abstraction layer unit).

fig4.jpg

每一个 NALU 首先是一个起始标识符,用于标识 NALU 之间的间隔;然后是 NALU 的头,里面主要配置了 NALU 的类型;最终 Payload 里面是 NALU 承载的数据。

在 NALU 头里面,主要的内容是类型NAL Type.

  • 0x07 表示 SPS,是序列参数集, 包括一个图像序列的所有信息,如图像尺寸、视频格式等。
  • 0x08 表示 PPS,是图像参数集,包括一个图像的所有分片的所有相关信息,包括图像类型、序列号等。
  • 在传输视频流之前,必须要传输这两类参数,不然无法解码。为了保证容错性,每一个 I 帧前面,都会传一遍这两个参数集合。

如果 NALU Header 里面的表示类型是 SPS 或者 PPS,则 Payload 中就是真正的参数集的内容。

如果类型是帧,则 Payload 中才是正的视频数据,当然也是一帧一帧存放的,前面说了,一帧的内容还是挺多的,因而每一个 NALU 里面保存的是一片。对于每一片,到底是 I 帧,还是 P 帧,还是 B 帧,在片结构里面也有个 Header,这里面有个类型,然后是片的内容。

一个视频,可以拆分成一系列的帧,每一帧拆分成一系列的片,每一片都放在一个 NALU 里面,NALU 之间都是通过特殊的起始标识符分隔,在每一个 I 帧的第一片前面,要插入单独保存 SPS 和 PPS 的 NALU,最终形成一个长长的 NALU 序列

1.3.2 推流

需要将这个二进制流打包成网络包进行发送,一般使用RTMP协议。

RTMP协议是基于TCP的,因此肯定需要双方建立一个TCP的连接。在有TCP的连接的基础上,还需要建立一个RTMP的连接,即在程序当中,需要调用RTMP类库的Connect函数显示创建一个连接。

RTMP需要单独一个连接的原因在于:双方需要互相知道版本号,时间戳(看时间戳的差值)

未来沟通这些事情,需要发送六条消息:客户端发送 C0、C1、 C2,服务器发送 S0、 S1、 S2。首先,客户端发送 C0 表示自己的版本号,不必等对方的回复,然后发送 C1 表示自己的时间戳。服务器只有在收到 C0 的时候,才能返回 S0,表明自己的版本号,如果版本不匹配,可以断开连接。
服务器发送完 S0 后,也不用等什么,就直接发送自己的时间戳 S1。客户端收到 S1 的时候,发一个知道了对方时间戳的 ACK C2。同理服务器收到 C1 的时候,发一个知道了对方时间戳的 ACK S2。
握手完成。

fig5.jpg

握手之后,双方需要互相传递一些控制信息,比如Chunk块的大小,窗口大小等。真正传输数据的时候,还是需要创建一个流Stream,然后通过这个Stream来推流publish。

推流的过程,就是将NALU放在message里面发送,称为RTMP Packet包。格式如下图所示:

fig6.jpg

发送的时候,去掉 NALU 的起始标识符。因为这部分对于 RTMP 协议来讲没有用。接下来,将 SPS 和 PPS 参数集封装成一个 RTMP 包发送,然后发送一个个片的 NALU。

RTMP 在收发数据的时候并不是以 Message 为单位的,而是把 Message 拆分成 Chunk 发送,而且必须在一个 Chunk 发送完成之后,才能开始发送下一个 Chunk。每个 Chunk 中都带有 Message ID,表示属于哪个 Message,接收端也会按照这个 ID 将 Chunk 组装成 Message。

前面连接的时候,设置的 Chunk 块大小就是指这个 Chunk。将大的消息变为小的块再发送,可以在低带宽的情况下,减少网络拥塞。

举一个分块的例子:

假设一个视频的消息长度为 307,但是 Chunk 大小约定为 128,于是会拆分为三个 Chunk。

第一个 Chunk 的 Type=0,表示 Chunk 头是完整的;头里面 Timestamp 为 1000,总长度 Length 为 307,类型为 9,是个视频,Stream ID 为 12346,正文部分承担 128 个字节的 Data。

第二个 Chunk 也要发送 128 个字节,Chunk 头由于和第一个 Chunk 一样,因此采用 Chunk Type=3,表示头一样就不再发送了。

第三个 Chunk 要发送的 Data 的长度为 307-128-128=51 个字节,还是采用 Type=3。

fig7.jpg

这样数据就能源源不断到达流媒体服务器

fig8.jpg

这个时候,大量观看直播的观众就可以通过 RTMP 协议从流媒体服务器上拉取,但是这么多的用户量,都去同一个地方拉取,服务器压力会很大,而且用户分布在全国甚至全球,如果都去统一的一个地方下载,也会时延比较长,需要有分发网络。

分发网络分为中心和边缘两层。边缘层服务器部署在全国各地及横跨各大运营商里,和用户距离很近。中心层是流媒体服务集群,负责内容的转发。智能负载均衡系统,根据用户的地理位置信息,就近选择边缘服务器,为用户提供推 / 拉流服务。中心层也负责转码服务,例如,把 RTMP 协议的码流转换为 HLS 码流。

fig9.jpg

1.3.3 拉流

观众的客户端通过RTMP拉流的过程:

fig10.jpg

2. P2P

2.1 传输大文件的现有方式

2.1.1 HTTP方式

最简单的是通过HTTP进行下载,但是通过浏览器下载速度非常慢。

2.1.2 FTP方式

还可以通过FTP,即文件传输协议,FTP通过两个TCP连接来传输一个文件。

  • 控制连接

服务器以被动的方式,打开用于FTP的端口21,客户端则主动发起连接。该连接将命令从客户端传给服务器,并传回服务器的应答。

  • 数据连接

每当一个文件在客户端与服务器之间传输时,就创建一个数据连接

FTP有两种工作模式

  • 主动模式 PORT

客户端随机打开一个大于1024的端口N,向服务器的命令端口21发起连接,同时开放N+1端口监听,并向服务器发出 prot N+1的命令,由服务器从自己的数据端口20主动连接到客户端指定的数据端口N+1

  • 被动模式 PASV

当开启一个FTP连接时,客户端打开两个任意的本地端口N(仍然需要大于1024)和N+1.第一个端口连接服务器的21端口,提交PASV命令。然后,服务器会开启一个任意的端口P(大于1024),返回”227 entering passive mode”信息,其中有FTP服务器开放的用来进行数据传输的端口。客户端收到信息获取端口号以后,会通过N+1号端口连接服务器的端口P,然后在两个端口之间进行数据传输。

2.2 P2P概念

首先无论是HTTP的方式还是FTP的方式,都难以解决单一服务器的带宽压力的问题,因为它们使用的都是传统的客户端服务器方式。P2P是指peer-to-peer。资源开始并不集中地存储在某些设备上,而是分散地存储在多台设备上。

想要下载一个文件的时候,需要得到那些已经存在了文件的peer,并和这些peer之间建立点对点的连接,而不需要到中心服务器上,就可以就近下载文件。同时在做下载和上传。

2.3 种子(.torrent) 文件

需要知道哪些peer有这些文件,因此需要用到种子,就是我们熟悉的.torrent文件。由两部分组成:分别是announce(tracker URL) 和文件信息

2.3.1 文件信息

  • info区

指定该中西有几个文件、文件有多长、目录结构,以及目录和文件的名字。

  • name字段

指定顶层目录的名字

  • 每个段的大小

BitTorrent协议把一个文件分成很多小段,然后分段下载。

  • 段哈希值

将整个种子种,每个段的SHA-1哈希值拼在一起。

2.3.2 下载过程

下载时,BT 客户端首先解析.torrent 文件,得到 tracker 地址,然后连接 tracker 服务器。tracker 服务器回应下载者的请求,将其他下载者(包括发布者)的 IP 提供给下载者。下载者再连接其他下载者,根据.torrent 文件,两者分别对方告知自己已经有的块,然后交换对方没有的数据。此时不需要其他服务器参与,并分散了单个线路上的数据流量,因此减轻了服务器的负担。

下载者每得到一个块,需要算出下载块的 Hash 验证码,并与.torrent 文件中的对比。如果一样,则说明块正确,不一样则需要重新下载这个块。这种规定是为了解决下载内容的准确性问题。

从这个过程也可以看出,这种方式特别依赖 tracker。tracker 需要收集下载者信息的服务器,并将此信息提供给其他下载者,使下载者们相互连接起来,传输数据。虽然下载的过程是非中心化的,但是加入这个 P2P 网络的时候,都需要借助 tracker 中心服务器,这个服务器是用来登记有哪些用户在请求哪些资源。

所以,这种工作方式有一个弊端,一旦 tracker 服务器出现故障或者线路遭到屏蔽,BT 工具就无法正常工作了。

2.4 去中心化网络(Distributed Hash Table)

每个加入这个DHT网络的人都要负责存储这个网络里的资源信息和其它成员的联系信息,相当于所有人一起构成了一个庞大的分布式存储数据库。

2.4.1 Kademlia 协议

任何一个BitTorrent启动之后,都有两个角色:一个是peer,监听一个TCP端口,用来上传和下载文件;另一个角色DHT node,监听一个UDP端口,通过这个角色,这个节点就可以加入到一个DHT网络当中。

fig11.jpg

在 DHT 网络里面,每一个 DHT node 都有一个 ID。这个 ID 是一个很长的串。每个 DHT node 都有责任掌握一些知识,也就是文件索引,即它应该知道某些文件时保存在哪些节点上的,这些信息就足够了,而它自己本身不一定就是保存这个文件的节点。

2.4.2 哈希值

每个文件可以计算出一个哈希值,而DHT node的ID是和哈希值相同长度的串。

DHT 算法是这样规定的:如果一个文件计算出一个哈希值,则和这个哈希值一样的那个 DHT node,就有责任知道从哪里下载这个文件,即便它自己没保存这个文件。

当然不一定这么巧,总能找到和哈希值一模一样的,有可能一模一样的 DHT node 也下线了,所以 DHT 算法还规定:除了一模一样的那个 DHT node 应该知道,ID 和这个哈希值非常接近的 N 个 DHT node 也应该知道。

什么叫和哈希值接近呢?例如只修改了最后一位,就很接近;修改了倒数 2 位,也不远;修改了倒数 3 位,也可以接受。总之,凑齐了规定的 N 这个数就行。

在这种模式下,种子.torrent 文件里面就不再是 tracker 的地址了,而是一个 list 的 node 的地址,而所有这些 node 都是已经在 DHT 网络里面的。当然随着时间的推移,很可能有退出的,有下线的,但是我们假设,不会所有的都联系不上,总有一个能联系上。

node new 只要在种子里面找到一个 DHT node,就加入了网络。

node new 会计算文件 1 的哈希值,并根据这个哈希值了解到,和这个哈希值匹配,或者很接近的 node 上知道如何下载这个文件,例如计算出来的哈希值就是 node C。

但是 node new 不知道怎么联系上 node C,因为种子里面的 node 列表里面很可能没有 node C,但是它可以问,DHT 网络特别像一个社交网络,node new 只有去它能联系上的 node 问,你们知道不知道 node C 的联系方式呀?

在 DHT 网络中,每个 node 都保存了一定的联系方式,但是肯定没有 node 的所有联系方式。DHT 网络中,节点之间通过互相通信,也会交流联系方式,也会删除联系方式。

在 node C 上,告诉 node new,下载文件 1,要去 B、D、 F,于是 node new 选择和 node B 进行 peer 连接,开始下载,它一旦开始下载,自己本地也有文件 1 了,于是 node new 告诉 node C 以及和 node C 的 ID 很像的那些节点,我也有文件 1 了,可以加入那个文件拥有者列表了。

但是你会发现 node new 上没有文件索引,但是根据哈希算法,一定会有某些文件的哈希值是和 node new 的 ID 匹配上的。在 DHT 网络中,会有节点告诉它,你既然加入了咱们这个网络,你也有责任知道某些文件的下载地址。

3. DNS

3.1 DNS服务器

DNS服务器很重要,根据名称来查找对应的IP地址的协议。DNS服务器,一定要设置成高可用、高并发和分布式的。

fig12.jpg

  • 根DNS服务器:返回顶级域DNS服务器的IP地址
  • 顶级域DNS服务器:返回权威DNS服务器的IP地址
  • 权威DNS服务器:返回相应主机的IP地址

3.2 DNS解析流程

fig13.jpg

  1. 电脑客户端会发出一个 DNS 请求,问 www.163.com 的 IP 是啥啊,并发给本地域名服务器 (本地 DNS)。那本地域名服务器 (本地 DNS) 是什么呢?如果是通过 DHCP 配置,本地 DNS 由你的网络服务商(ISP),如电信、移动等自动分配,它通常就在你网络服务商的某个机房。
  2. 本地 DNS 收到来自客户端的请求。你可以想象这台服务器上缓存了一张域名与之对应 IP 地址的大表格。如果能找到 www.163.com,它直接就返回 IP 地址。如果没有,本地 DNS 会去问它的根域名服务器:“老大,能告诉我 www.163.com 的 IP 地址吗?”根域名服务器是最高层次的,全球共有 13 套。它不直接用于域名解析,但能指明一条道路。
  3. 根 DNS 收到来自本地 DNS 的请求,发现后缀是 .com,说:“哦,www.163.com 啊,这个域名是由.com 区域管理,我给你它的顶级域名服务器的地址,你去问问它吧。”
  4. 本地 DNS 转向问顶级域名服务器:“老二,你能告诉我 www.163.com 的 IP 地址吗?”顶级域名服务器就是大名鼎鼎的比如 .com、.net、 .org 这些一级域名,它负责管理二级域名,比如 163.com,所以它能提供一条更清晰的方向。
  5. 顶级域名服务器说:“我给你负责 www.163.com 区域的权威 DNS 服务器的地址,你去问它应该能问到。”
  6. 本地 DNS 转向问权威 DNS 服务器:“您好,www.163.com 对应的 IP 是啥呀?”163.com 的权威 DNS 服务器,它是域名解析结果的原出处。为啥叫权威呢?就是我的域名我做主。
  7. 权限 DNS 服务器查询后将对应的 IP 地址 X.X.X.X 告诉本地 DNS。
  8. 本地 DNS 再将 IP 地址返回客户端,客户端和目标建立连接。

3.3 DNS 负载均衡

DNS通过名称映射为IP地址的时候,并不会都映射到同一个IP地址,会根据距离选择最近的。

3.3.1 DNS内部负载均衡

例如,一个应用要访问数据库,在这个应用里面应该配置这个数据库的 IP 地址,还是应该配置这个数据库的域名呢?显然应该配置域名,因为一旦这个数据库,因为某种原因,换到了另外一台机器上,而如果有多个应用都配置了这台数据库的话,一换 IP 地址,就需要将这些应用全部修改一遍。但是如果配置了域名,则只要在 DNS 服务器里,将域名映射为新的 IP 地址,这个工作就完成了,大大简化了运维。

都尽量用域名进行配置,然后就可以在DNS层面上对其进行限制,比如轮询不同的IP地址,达到负载均衡的目的。

3.3.2 全局负载均衡

为了保证我们的应用高可用,往往会部署在多个机房,每个地方都会有自己的 IP 地址。当用户访问某个域名的时候,这个 IP 地址可以轮询访问多个数据中心。如果一个数据中心因为某种原因挂了,只要在 DNS 服务器里面,将这个数据中心对应的 IP 地址删除,就可以实现一定的高可用。

3.3.3 DNS访问数据中心中对象存储上的静态资源

我们通过 DNS 访问数据中心中对象存储上的静态资源为例,看一看整个过程。

假设全国有多个数据中心,托管在多个运营商,每个数据中心三个可用区(Available Zone)。对象存储通过跨可用区部署,实现高可用性。在每个数据中心中,都至少部署两个内部负载均衡器,内部负载均衡器后面对接多个对象存储的前置服务器(Proxy-server)。

fig14.jpg

  1. 当一个客户端要访问 object.yourcompany.com 的时候,需要将域名转换为 IP 地址进行访问,所以它要请求本地 DNS 解析器。
  2. 本地 DNS 解析器先查看看本地的缓存是否有这个记录。如果有则直接使用,因为上面的过程太复杂了,如果每次都要递归解析,就太麻烦了。
  3. 如果本地无缓存,则需要请求本地的 DNS 服务器。
  4. 本地的 DNS 服务器一般部署在你的数据中心或者你所在的运营商的网络中,本地 DNS 服务器也需要看本地是否有缓存,如果有则返回,因为它也不想把上面的递归过程再走一遍。
  5. 至 7. 如果本地没有,本地 DNS 才需要递归地从根 DNS 服务器,查到.com 的顶级域名服务器,最终查到 yourcompany.com 的权威 DNS 服务器,给本地 DNS 服务器,权威 DNS 服务器按说会返回真实要访问的 IP 地址。

对于不需要进行全局负载均衡的简单应用来讲,权威DNS服务器就可以直接将域名解析为一个或者多个IP地址,然后客户端可以通过多个IP地址进行简单的轮询,实现简单的负载均衡。

但是对于复杂的应用,尤其是跨地域运营商的大型应用,需要专门的设备或者服务器来做这件事情,这就是全局负载均衡器。(GSLB, Global Server Load Balance)

在 yourcompany.com 的 DNS 服务器中,一般是通过配置 CNAME 的方式,给 object.yourcompany.com 起一个别名,例如 object.vip.yourcomany.com,然后告诉本地 DNS 服务器,让它请求 GSLB 解析这个域名,GSLB 就可以在解析这个域名的过程中,通过自己的策略实现负载均衡。

  1. 第一层 GSLB,通过查看请求它的本地 DNS 服务器所在的运营商,就知道用户所在的运营商。假设是移动,通过 CNAME 的方式,通过另一个别名 object.yd.yourcompany.com,告诉本地 DNS 服务器去请求第二层的 GSLB。
  2. 第二层 GSLB,通过查看请求它的本地 DNS 服务器所在的地址,就知道用户所在的地理位置,然后将距离用户位置比较近的 Region 里面,六个内部负载均衡的地址返回给本地DNS服务器
  3. 本地DNS服务器将结果返回给本地DNS解析器
  4. 本地DNS解析器将结果缓存后,返回给客户端
  5. 客户端开始访问属于相同运营商的距离较近的 Region 1 中的对象存储,当然客户端得到了六个 IP 地址,它可以通过负载均衡的方式,随机或者轮询选择一个可用区进行访问。对象存储一般会有三个备份,从而可以实现对存储读写的负载均衡。

3.4 DNS功能

  1. 根据名称找具体地址
  2. 针对多个地址做负载均衡

在多个地址中选择一个距离你近的地方访问。

3.5 传统DNS的问题

3.5.1 域名缓存问题

DNS会对域名做缓存,在访问过一次以后会把结果缓存到本地,当其他人来问的时候,直接就返回这个缓存数据。某些运营商会将静态页面缓存到本运营商的服务器内,这样用户请求的时候,就不用跨运营商进行访问了。既加快了速度,也减少了运营商之间流量计算的成本。 在做域名解析的时候,不会将用户导向真正的网址,而是指向这个缓存的服务器。

还有就是本地的缓存往往会使全局负载失败,因为上次进行缓存的时候,缓存中的地址不一定是这次访问离客户最近的地方。

3.5.2 域名转发问题

运营商可能不是直接和DNS服务器交流的,可能用转发给了其他的做解析,自己只是外包了出去。

3.5.3 出口NAT问题

网络地址转换,使得从网关出去的包都换成了新的IP地址,当请求返回的时候,在这个网关,再将IP地址转换回去。但一旦做了网络地址转换,权威DNS服务器就没法通过这个地址来判断客户到底来自哪个运营商,极有可能误判运营商,导致跨运营商的访问

3.5.4 域名更新问题

本地 DNS 服务器是由不同地区、不同运营商独立部署的。对域名解析缓存的处理上,实现策略也有区别,有的会偷懒,忽略域名解析结果的 TTL 时间限制,在权威 DNS 服务器解析变更的时候,解析结果在全网生效的周期非常漫长。但是有的时候,在 DNS 的切换中,场景对生效时间要求比较高。

例如双机房部署的时候,跨机房的负载均衡和容灾多使用 DNS 来做。当一个机房出问题之后,需要修改权威 DNS,将域名指向新的 IP 地址,但是如果更新太慢,那很多用户都会出现访问异常。

3.6 HTTPDNS

HTTPDNS就是不走传统的DNS解析,而是自己搭建基于HTTP协议的DNS服务器集群,分布在多个地点和多个运营商。当客户端需要DNS解析的时候,直接通过HTTP协议进行请求这个服务器集群,得到就近的地址。大部分应用在手机中,在手机端嵌入支持HTTPDNS的客户端SDK来进行使用。

4. CDN

当一个用户想访问一个网址的时候,指定这个网站的域名,DNS就会将这个域名解析为地址,然后用户请求这个地址,返回一个网页。

但是还有很多可以优化的地方:

借鉴快递的就近配送的原则/思路,在数据中心里部署几台机器,形成一个缓存的集群来缓存部分数据。

这些分布在各个地方的各个数据中心的节点,称为边缘节点。

由于边缘节点数目比较多,但是每个集群规模比较小,不可能缓存下来所有东西,因而可能无法命中,这样就会在边缘节点之上。有区域节点,规模就要更大,缓存的数据会更多,命中的概率也就更大。在区域节点之上是中心节点,规模更大,缓存数据更多。如果还不命中,就只好回源网站访问了。

fig15.jpg

在没有CDN的情况下,用户向浏览器输入 www.web.com 这个域名,客户端访问本地 DNS 服务器的时候,如果本地 DNS 服务器有缓存,则返回网站的地址;如果没有,递归查询到网站的权威 DNS 服务器,这个权威 DNS 服务器是负责 web.com 的,它会返回网站的 IP 地址。本地 DNS 服务器缓存下 IP 地址,将 IP 地址返回,然后客户端直接访问这个 IP 地址,就访问到了这个网站。

当CDN存在的时候,在web.com这个权威DNS服务器上,会设置一个CNAME别名,指向另一个域名 www.web.cdn.com,并返回给本地DNS服务器。

fig16.jpg

当本地 DNS 服务器拿到这个新的域名时,需要继续解析这个新的域名。这个时候,再访问的就不是 web.com 的权威 DNS 服务器了,而是 web.cdn.com 的权威 DNS 服务器,这是 CDN 自己的权威 DNS 服务器。在这个服务器上,还是会设置一个 CNAME,指向另外一个域名,也即 CDN 网络的全局负载均衡器。接下来,本地 DNS 服务器去请求 CDN 的全局负载均衡器解析域名,全局负载均衡器会为用户选择一台合适的缓存服务器提供服务,选择的依据包括:

  1. 根据用户 IP 地址,判断哪一台服务器距用户最近;
  2. 用户所处的运营商;
  3. 根据用户所请求的 URL 中携带的内容名称,判断哪一台服务器上有用户所需的内容;
  4. 查询各个服务器当前的负载情况,判断哪一台服务器尚有服务能力。

基于以上这些条件,进行综合分析之后,全局负载均衡器会返回一台缓存服务器的 IP 地址。

本地 DNS 服务器缓存这个 IP 地址,然后将 IP 返回给客户端,客户端去访问这个边缘节点,下载资源。缓存服务器响应用户请求,将用户所需内容传送到用户终端。如果这台缓存服务器上并没有用户想要的内容,那么这台服务器就要向它的上一级缓存服务器请求内容,直至追溯到网站的源服务器将内容拉到本地。

4.1 CDN缓存的内容

fig17.jpg

会保存静态页面,图片等,因为这些东西变化的可能性不高。

在进入数据中心的时候,我们希望通过最外层接入层的缓存,将大部分静态资源的访问拦在边缘。而CDN则更进一步,将这些静态资源缓存到离用户更近的数据中心外。越接近客户,访问性能越好,时延越低。

静态资源中,流媒体也大量使用了CDN技术。CDN支持流媒体协议,例如前面讲过的 RTMP 协议。在很多情况下,这相当于一个代理,从上一级缓存读取内容,转发给用户。由于流媒体往往是连续的,因而可以进行预先缓存的策略,也可以预先推送到用户的客户端。

对于静态页面来讲,内容的分发往往采取拉取的方式,即未命中的时候,向上一级进行拉取,但流媒体数据量很大,如果出现回源,压力会比较大,因此往往采取主动推送的模式,将热点数据主动推送到边缘节点。

对于流媒体来讲,很多CDN还提供预处理服务,即在文件分发之前,经过一定的处理。例如将视频转换为不同的码流,以适应不同的网络带宽的用户需求;再比如对视频进行分片,降低存储压力,也使得客户端可以选择使用不同的码率加载不同的分片。

4.2 防盗链问题

对于流媒体来说,防盗链很重要,即视频都有版权的,只能在自己的网站里播才可以的。

4.2.1 refer机制

HTTP头的refer字段,告诉服务器这个请求从哪里来的,服务器基于此可以获得一些信息用于处理。如果referer的信息不是来自本站,就阻止访问或者调到其它链接当中。

4.2.2 时间戳防盗链

使用 CDN 的管理员可以在配置界面上,和 CDN 厂商约定一个加密字符串。客户端取出当前的时间戳,要访问的资源及其路径,连同加密字符串进行签名算法得到一个字符串,然后生成一个下载链接,带上这个签名字符串和截止时间戳去访问 CDN。在 CDN 服务端,根据取出过期时间,和当前 CDN 节点时间进行比较,确认请求是否过期。然后 CDN 服务端有了资源及路径,时间戳,以及约定的加密字符串,根据相同的签名算法计算签名,如果匹配则一致,访问合法,才会将资源返回给客户。

4.3 动态CDN

4.3.1 边缘计算模式

既然数据时动态生成的,那数据的逻辑计算和存储也应当相应的放在边缘节点。其中定时从源数据哪里同步存储的数据,然后再边缘进行计算得到结果。

4.3.2 路径优化模式

数据不是在边缘计算生成的,而是在源站生成的,数据的下发则可以通过CDN网络,对路径进行优化。因为CDN节点较多,能够找到离源站很近的边缘节点,也能找到离用户很近的边缘节点。中间的链路完全由CDN规划,选择一个更加可靠的路径,使用类似专线的方式进行访问。


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 stone2paul@gmail.com

文章标题:网络协议(七)-流媒体协议(网络直播当中的视频压缩与传播问题)

文章字数:8.8k

本文作者:Leilei Chen

发布时间:2020-02-01, 19:38:44

最后更新:2020-02-01, 22:06:58

原始链接:https://www.llchen60.com/%E7%BD%91%E7%BB%9C%E5%8D%8F%E8%AE%AE-%E4%B8%83-%E6%B5%81%E5%AA%92%E4%BD%93%E5%8D%8F%E8%AE%AE-%E7%BD%91%E7%BB%9C%E7%9B%B4%E6%92%AD%E5%BD%93%E4%B8%AD%E7%9A%84%E8%A7%86%E9%A2%91%E5%8E%8B%E7%BC%A9%E4%B8%8E%E4%BC%A0%E6%92%AD%E9%97%AE%E9%A2%98/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录
×

喜欢就点赞,疼爱就打赏