第二章 应用层(P2P、视频流和内容分发网)

目录

    • [2.5 P2P文件分发](#2.5 P2P文件分发)
    • [2.6 视频流和内容分发网](#2.6 视频流和内容分发网)
      • [2.6.1 因特网视频](#2.6.1 因特网视频)
      • [2.6.2 HTTP流和DASH](#2.6.2 HTTP流和DASH)
      • [2.6.3 内容分发网CDN](#2.6.3 内容分发网CDN)
      • [2.6.4 学习案例:Netflix、YouTube和"看看"](#2.6.4 学习案例:Netflix、YouTube和“看看”)

2.5 P2P文件分发

P2P 文件分发在讲啥?

前面学的 Web、邮件、DNS 都是 客户--服务器(C/S)结构

  • 客户端(浏览器、邮件客户端...)去找少数服务器要东西;
  • 所有数据都从服务器那几台机器"往外喷"。

缺点:

一旦很多人都来从同一台服务器下一个大文件(新系统 ISO、补丁、热门视频...),

服务器:我快被挤爆了......

因为:
所有人的数据都只能从这一个服务器出去,服务器的上行带宽就是瓶颈。

P2P 的思路是:

"让每个下载的人,也顺便帮忙上传给别人 ",

这样人越多,总的上传能力(带宽)越大,反而更轻松

这一节就是用一个数学小模型,比较:

  • 纯 C/S:只有服务器上传
  • 纯 P2P:服务器 + 所有对等方都可以上传

谁更快。

简单模型:一个文件发给 N 个人

书里先搭了一个统一模型(图 2-21):

  • 有一台服务器,要分发一个文件 F (单位:bit)给 N 个对等方(peer)
  • 每个对等方都要拿到完整一份这个文件。

对于每台机器,定义两个速率:

  • 服务器:
    • 上载速率(上传) = u s u_s us
  • 第 i 个对等方:
    • 下载速率 = d i d_i di
    • 上载速率 = u i u_i ui

目标:
分发时间(distribution time) = 所有 N 个对等方都拿到这个文件所需的总时间

记作 D D D。

为了好算:

  • 书里假设"核心网络"带宽足够,不是瓶颈;
  • 只有"接入链路"(服务器 / 对等方连入互联网的那根线)的上/下行速率起作用。

先看 C/S 结构的分发时间 D c s D_{cs} Dcs

在 C/S 结构里:

  • 只有服务器上传,所有对等方只下载不上传;
  • 所以整个系统真正的"输出能力"就只有服务器一条 u s u_s us。

1. 服务器端的限制

服务器要给 N 个人各发一份文件 F:

  • 总共要发出去的数据量 = N ⋅ F N \cdot F N⋅F bit
  • 它的上传速率 = u s u_s us bit/s

就算它不停地发、线路一直跑满,也至少要:
时间 ≥ N F u s \text{时间} \ge \frac{N F}{u_s} 时间≥usNF

所以这是一个 下界

不可能比 N F u s \frac{N F}{u_s} usNF 更快。

2. 最慢下载者的限制

每个对等方都要自己下载完 F 个 bit,

对于第 i 个对等方,至少要 F / d i F/d_i F/di 秒。

那对最慢那个人(下行速率最小的)来说:

  • 记 d min ⁡ = min ⁡ { d 1 , d 2 , ... , d N } d_{\min} = \min\{d_1, d_2, ..., d_N\} dmin=min{d1,d2,...,dN}
  • 它至少要 F / d min ⁡ F/d_{\min} F/dmin 秒才能收完文件。

无论服务器多快,只要有这么一个超级慢的人,
整体完成时间至少是 F / d min ⁡ F/d_{\min} F/dmin

3. 合在一起:公式 (2-1)

所以 C/S 的"最小分发时间下界"至少满足:
D c s ≥ max ⁡ { N F u s ,    F d min ⁡ } D_{cs} \ge \max\left\{ \frac{N F}{u_s},\; \frac{F}{d_{\min}} \right\} Dcs≥max{usNF,dminF}

书里为了方便后面画图,直接把这个"下界"当成近似的真实分发时间:
D c s ≈ max ⁡ { N F u s ,    F d min ⁡ } (2-1) D_{cs} \approx \max\left\{ \frac{N F}{u_s},\; \frac{F}{d_{\min}} \right\} \tag{2-1} Dcs≈max{usNF,dminF}(2-1)

直观理解:

  • N F u s \frac{N F}{u_s} usNF:服务器忙不过来的限制;
  • F d min ⁡ \frac{F}{d_{\min}} dminF:某个下载巨慢的人拖后腿的限制;
  • 两者哪个更慢,整体时间就由谁决定。

特别地,当 N 很大时,通常是服务器这项 N F u s \frac{NF}{u_s} usNF 占主导------
C/S 结构的时间会随着 N 线性增长。

再看 P2P 结构的分发时间 D p 2 p D_{p2p} Dp2p

P2P 的关键:
每个对等方既能下载,也能上传给别人。

所以系统的总上传能力不再是服务器一个人,而是:

  • 总上载速率 = u total = u s + u 1 + u 2 + ⋯ + u N u_{\text{total}} = u_s + u_1 + u_2 + \cdots + u_N utotal=us+u1+u2+⋯+uN

书里对 P2P 做了三个观察(对应图 2-21 下面那几 bullet):

1. 服务器至少要发一份完整文件出去

刚开始只有服务器手里有这份文件 F。

要让文件在"社群"里流动起来,服务器至少要先上传一份完整拷贝出去:

  • 它的速率是 u s u_s us,
  • 所以至少需要 F u s \frac{F}{u_s} usF 秒。

这是 P2P 分发时间的第一个下界:
D p 2 p ≥ F u s D_{p2p} \ge \frac{F}{u_s} Dp2p≥usF
2. 还是有最慢下载者的限制

和 C/S 一样,每个对等方必须自己下载完 F bit,

所以仍然有:
D p 2 p ≥ F d min ⁡ D_{p2p} \ge \frac{F}{d_{\min}} Dp2p≥dminF
3. 总上传能力的限制(最关键)

总共要发出的数据还是 N F N F NF bit(发给 N 个人)。

但是现在承载这些上传的"管道"有很多条:

  • 服务器的上载 = u s u_s us
  • 第 i 个对等方的上载 = u i u_i ui
  • 总共: u total = u s + ∑ i = 1 N u i u_{\text{total}} = u_s + \sum_{i=1}^{N} u_i utotal=us+∑i=1Nui

即使大家 7×24 不停地满速上传,把所有人的上载加起来,

系统要完成"交付 NF bit"也至少要:
D p 2 p ≥ N F u s + ∑ i = 1 N u i D_{p2p} \ge \frac{N F}{u_s + \sum_{i=1}^{N} u_i} Dp2p≥us+∑i=1NuiNF
4. 合成 P2P 的公式 (2-2) / (2-3)

把三个限制一起取 max:
D p 2 p ≥ max ⁡ { F u s ,    F d min ⁡ ,    N F u s + ∑ i = 1 N u i } (2-2) D_{p2p} \ge \max\left\{ \frac{F}{u_s},\; \frac{F}{d_{\min}},\; \frac{N F}{u_s + \sum_{i=1}^{N} u_i} \right\} \tag{2-2} Dp2p≥max{usF,dminF,us+∑i=1NuiNF}(2-2)

这就是 P2P 分发时间的下界

书里说,实际上真实的最小分发时间跟这个下界已经非常接近,

所以直接拿它当"估计值"用:
D p 2 p ≈ max ⁡ { F u s ,    F d min ⁡ ,    N F u s + ∑ i = 1 N u i } (2-3) D_{p2p} \approx \max\left\{ \frac{F}{u_s},\; \frac{F}{d_{\min}},\; \frac{N F}{u_s + \sum_{i=1}^{N} u_i} \right\} \tag{2-3} Dp2p≈max{usF,dminF,us+∑i=1NuiNF}(2-3)

记住直观含义就好:

  1. 服务器至少要发出一份完整文件 → F / u s F/u_s F/us
  2. 最慢下载者的速度上限 → F / d min ⁡ F/d_{\min} F/dmin
  3. 全系统上传总能力 → N F / ( u s + ∑ u i ) NF / (u_s + \sum u_i) NF/(us+∑ui)

P2P 的妙处

当 N 变大时,第三项的分母 u s + ∑ u i u_s + \sum u_i us+∑ui 也变大,因为多了很多对等方帮助上传,

所以分数不会像 C/S 那样线性暴涨

图 2-22:C/S vs P2P 分发时间随 N 的变化

书里选了一个具体配置(你大致知道意思就好):

  • 所有对等方的上传速率都相同: u i = u u_i = u ui=u
  • 服务器上传是对等方的 10 倍: u s = 10 u u_s = 10u us=10u
  • 文件大小和速率选得刚好满足: F / u = 1 小时 F/u = 1 \text{ 小时} F/u=1 小时
  • 为了简化,假设对等方下载速率足够大,不成为瓶颈(即 F / d min ⁡ F/d_{\min} F/dmin 这一项可以忽略)

这样:

1. C/S 情况

D c s ≈ N F u s = N F 10 u = N 10 小时 D_{cs} \approx \frac{N F}{u_s} = \frac{N F}{10 u} = \frac{N}{10} \text{ 小时} Dcs≈usNF=10uNF=10N 小时

也就是:

  • N=10 人:1 小时
  • N=20 人:2 小时
  • N=30 人:3 小时
    一条斜直线,线性增长。

2. P2P 情况

这时候:

  • F / u s = F / ( 10 u ) = 0.1 F/u_s = F/(10u) = 0.1 F/us=F/(10u)=0.1 小时;

  • ∑ u i = N u \sum u_i = N u ∑ui=Nu,所以:
    N F u s + ∑ u i = N F 10 u + N u = N 10 + N 小时 \frac{N F}{u_s + \sum u_i} = \frac{N F}{10u + N u} = \frac{N}{10+N} \text{ 小时} us+∑uiNF=10u+NuNF=10+NN 小时

当 N 很大时, N 10 + N → 1 \frac{N}{10+N} \to 1 10+NN→1 小时左右。

所以曲线一开始随 N 有点上升,最后慢慢趋于一个上界(约 1 小时)

这就是图上看到的:

  • C/S 曲线一路往上飙;
  • P2P 曲线慢慢变平,不再无限增大。

核心结论:

对 C/S 结构:人越多,服务器越累,时间线性增加。

对 P2P 结构:人越多,总上传能力越强,时间会趋近某个上限,不再爆炸。

这就是"P2P 体系结构的可扩展性"。

BitTorrent:真实世界中很流行的 P2P 协议

后面一大段开始讲 BitTorrent ,就是一个"落地实现版的 P2P 文件分发系统"。

1. 几个关键词

  • torrent / 洪流
    参与某个文件分发的所有对等方的集合,就叫一个"洪流"(swarm)。
  • chunk / 块
    文件不是一次性传完,而是被切成很多小块(典型大小 256KB)。
  • tracker / 追踪器
    一个基础设施节点,负责记录"当前有哪些对等方在这个洪流里"。

2. 加入洪流时发生什么?(图 2-23)

举一个对等方 Alice 的视角:

  1. Alice 想下载某个 BT 资源,加入洪流;
  2. 她先联系 追踪器 (tracker):
    • 在协议里"向洪流注册自己";
    • 追踪器定期更新:哪些对等方还在线。
  3. 追踪器随机挑出一小部分目前在线的对等方(比如 50 个),把这些对等方的 IP 列表返回给 Alice;
  4. Alice 根据这份列表,尝试跟里面的一些对等方建立 TCP 连接:
    • 这些连上的对等方就叫 Alice 的"邻居对等方";
    • 图 2-23 画了多个对等方之间的连接。

接下来就要靠这些对等方互相"拼块"。

块交换:rarest-first + tit-for-tat

1. 互相告诉对方"我有哪些块"

在任意时刻:

  • 每个对等方只拥有这个文件的一个子集(部分块);
  • 不同对等方拥有的块可能不一样。

Alice 会:

  1. 定期向每个邻居发送"自己拥有的块清单",
    邻居也会回给她各自的块清单;
  2. Alice 据此知道:
    哪个邻居有什么块,哪些块在整个邻居集合中比较稀有

2. Alice 决定"向谁要块、要哪一块"

Alice 有两个决定要做:

  1. 先向哪些邻居请求块?
  2. 从这些邻居那里要哪一块?

书里提到一个重要策略:最稀缺优先(rarest first)

  • 优先请求"在邻居中出现次数最少"的那些块;
  • 这样可以尽量避免某些块只有极少数人持有,一旦这些人下线就没源了。

3. Alice 决定"把块给谁":tit-for-tat(报还报)

上传更关键:要防止"只下载不上传的白嫖党"。

BitTorrent 使用一种"报还报(tit-for-tat)"式的交换算法,大致是:

  1. Alice 记录每个邻居最近向自己上传数据的速率;
  2. 每隔一小段时间(比如 10 秒):
    • 她把邻居里向自己上传最快的那 4 个选出来;
    • 把这 4 个邻居标记为 "不阻塞(unchoked)" ,即:
      • 对这 4 个邻居的下载请求,Alice 会积极响应、给他们上传块;
    • 其他邻居默认处于"阻塞(choked)"状态,从 Alice 这里什么也拿不到。
  3. 同时,每隔稍长一点时间(比如 30 秒),Alice 会从剩下的邻居中 随机选一个
    • 暂时把它也设为"unchoked",给它一个机会;
    • 这个随机选中的邻居被称为"乐观解除阻塞(optimistic unchoke)"。

直觉上:

  • 如果这个新邻居上传给 Alice 的速率很不错,那下次统计时它就可能挤进"前 4 名",成为长期合作对象;
  • 上传不给力的,就在下一轮被踢出前 4 名,只偶尔靠随机机会再被选中。

这样就形成一种自然激励:

谁对我好(给我传得快),我也优先对谁好;

谁什么也不给,我也不会给他。

这就是"你帮我,我也帮你"的报还报机制,本书认为是 BitTorrent 成功的关键之一。

最后的补充:DHT 一笔带过

这一节最后一句只是顺带提一下:

  • 还有另一类 P2P 应用叫 分布式散列表(DHT)
  • 它本质上是一个"分布在许多对等方上的数据库",
  • 像 BitTorrent 里有的版本,就用 DHT 来记录"哪个资源在哪些对等方"。

这部分本章就不展开了,只是告诉你:P2P 还能干更多事,不止文件分发。

2.6 视频流和内容分发网

2.6.1 因特网视频

  • 现在家庭宽带里的"流量大户"就是流式视频(Netflix、YouTube)。
  • 问题:
    • 怎么把视频做成"流式",让用户边下边看?
    • 怎么把视频内容分发到全世界,让大家都能流畅播放?

所以本节有两条主线:

  1. 视频怎么编码 + 通过 HTTP 流出来(DASH)
  2. 内容分发网(CDN)怎么把这些视频复制到全世界各地

1. "流式视频"场景是什么?

书里说的是**"存储式视频"应用**:

  • 视频都是预先录好的:电影、电视剧、录播课程、YouTube 上的 vlog 等。
  • 这些视频存放在服务器上。
  • 用户想看某个视频,就向服务器发请求,服务器把视频源源不断地发给用户------这就叫流式分发视频(streaming video)

例子:

你在 B 站点一个视频,其实就是向 B 站服务器说:

"请把这个视频从现在开始一点点地往我这儿推,我边下边播。"

2. 视频本质是什么?

视频 = 一帧一帧的图片序列

书里:

  • "视频是一系列的图像,通常以一种恒定的速率(每秒 24 或 30 帧图像)来展现。"

所以可以想象成:

把一堆照片快速翻页,你看到的就是动起来的"视频"。

每一帧图像又是由很多像素点组成,

  • 每个像素都要用一些比特来表示它的亮度、颜色。
  • 所以如果不压缩,原始视频数据量非常大。

3. 为什么要压缩?"特征码率"是什么?

要在网络上传视频,必须压缩,不然太大传不动。

书里说:

  • 压缩后的视频,仍然可以保持"视觉上足够好"的质量;压缩得越厉害,文件越小,但画质会变差。
  • 一个压缩后的视频,通常会有一个**"编码速率"/"比特率(bitrate)"**,比如:
    • 100 kbps(非常低质量)
    • 3 Mbps(蓝光级别比较清晰)
    • 10 Mbps(超清)

比特率 = 每秒钟需要多少 bit 来表示视频。

→ 就像"每秒钟要往你家水管里灌多少水"。

书里给了一个例子:

  • 2Mbps 的视频,
  • 播 67 分钟,大概要 1GB 的数据量。

所以比特率越高:

  • 画质更好(细节更清晰)
  • 同时也更吃:
    • 存储空间(硬盘)
    • 网络带宽(传输速度)

4. 一部视频会有多个"版本"

现实中,视频网站不会只存一个 3Mbps 的版本,因为:

  • 有人家里宽带很快,可以流畅看 3Mbps;
  • 有人只能用手机 4G,看 3Mbps 会一卡一卡的。

于是:

同一部视频通常会预先存 多种码率版本,例如:300kbps、1Mbps、3Mbps。

将来在播放时,用户/播放器会根据当前带宽情况来选择看哪个版本------这是后面 DASH 要解决的事。

2.6.2 HTTP流和DASH

视频怎么通过 HTTP 一段一段传过来,并且自动适应网络带宽变化

1. 传统 HTTP 流(最朴素的做法)

书里说:"在 HTTP 流中,视频只是存储在 HTTP 服务器上的一个普通文件"。

步骤:

  1. 服务器上有一个文件,例如 movie.mp4

  2. 客户端(你的浏览器或播放器)想看,就向服务器建立一个 TCP 连接,发送一个 HTTP GET 请求:

    GET /movie.mp4 HTTP/1.1

  3. 服务器就像发送普通文件那样,"尽快"把这个文件往外发。能发多快?

    • 取决于服务器出网带宽
    • 取决于网络链路中拥塞状况
  4. 客户端这边:

    • 一边接收数据,一边先放到本地的播放缓冲区(buffer)里。
    • 缓冲里攒够了(比如 5 秒的视频),播放器才开始播。
    • 播放的同时,客户端还会继续从服务器"抓取"后面的数据,填充 buffer。
    • 如果某一刻网络突然卡住、buffer 被播空了,就会出现你熟悉的"小圈圈转圈"------停下来缓冲。

你可以想象成:

  • 服务器是自来水厂,视频文件是一大桶水;
  • 你家是水龙头;
  • 打开龙头时,水厂就拼命往你这条管子里冲水;你家水箱先存一小部分再慢慢往外放;
  • 如果管子变细或被挤压了(网络拥塞),水箱很可能被放空 ------ 就卡了。

2. 纯 HTTP 流的问题

书里提到一个核心问题:

  • 不同用户的网络情况差别很大,有的人带宽高,有的人带宽低,而且会随时间变化;
  • 但在传统 HTTP 流中,你一开始就决定了"我要拉 3Mbps 的文件",中途网络变差也不改;
  • 结果是:
    • 带宽低的人会经常卡(缓冲区被播空);
    • 带宽高的人其实还能看更清晰的版本,但你只给他 1Mbps,就浪费了。

于是产生了一个需求:

能不能让客户端**"边播边根据网络情况调整清晰度"**?

这就是下面 DASH 要干的事。

3. DASH:动态自适应码率流(Dynamic Adaptive Streaming over HTTP)

DASH 的核心思想有三个:

  1. 把视频切成很多"小块"(chunk)
    • 例如每块 2 秒或 4 秒长。
    • 所有版本(300kbps / 1Mbps / 3Mbps)都切成相同时间的块:
      • 第 1 块:0--4 秒
      • 第 2 块:4--8 秒
      • ......
  2. 每个版本的所有块,都存在 HTTP 服务器上,每块有自己的 URL。
    • 例如:
      • .../v300/chunk1(300kbps)
      • .../v1000/chunk1(1Mbps)
      • .../v3000/chunk1(3Mbps)
    • 同理 chunk2, chunk3 ......
  3. 有一个"告示文件"(manifest file)
    • 里面列出:
      • 这部视频有哪些版本(300k, 1M, 3M ......)
      • 每个版本中每个块的 URL
    • 客户端第一步先请求这个 manifest 文件,拿到"菜单"。

接下来播放过程:

  1. 客户端先看 manifest,知道:
    • 有 300k / 1M / 3M 三个版本;
    • 每个版本的 chunk URL 是什么。
  2. 然后客户端自己做决策
    • 先测一测当前网络带宽(例如用最近几秒下载的速度粗略估算);
    • 例如测到当前只有 800kbps,那就先请求 300kbps 或 1Mbps 版本的前几个 chunk。
  3. 播放过程中,客户端每下载完一块,会重新估计带宽 + 看 buffer 里还剩多少 ,决定下一块选哪个版本:
    • 如果最近下载很快,buffer 又很满 → 说明带宽不错,可以试着要更高清的块(1M → 3M)。
    • 如果最近下载很慢,buffer 快见底 → 说明带宽吃紧,赶紧换到低码率版本(3M → 1M 或 300k)。

结果:

  • 带宽好时,你能看高清;
  • 带宽差时,画面可能糊一点,但至少不容易卡死。

这就是"动态自适应码率"的意思。

书里还说:

  • DASH 是一个标准,而不是某家公司私有的东西;
  • 很多流媒体系统(如 MPEG-DASH、HLS 类似思想)都遵循这样的做法。

2.6.3 内容分发网CDN

大量用户、全世界访问,怎么把视频内容高效地送到每个人手上?

1. 只用一个大数据中心,会有什么问题?

假设:

  • YouTube(或者 NetCinema)在某个城市有一个超大数据中心,里面存着所有视频。
  • 全世界用户看视频,都要跨海跨洲访问这个中心。

书里指出三大问题:

  1. 路径太长 + 经过太多 ISP
    • 美国用户从西海岸到东海岸,或者中国用户访问美国,都要经过很多运营商之间的链路;
    • 任何一个链路容量不足,就成"瓶颈",造成卡顿、延迟大。
  2. 带宽费用高 & 重复流量
    • 同一个热门视频,如果中国有一百万用户在看,每个人都从美国那一个数据中心拉一遍,
    • 中间跨国链路上就要重复传输同一个视频的一百万份,非常浪费。
    • 这些跨国链路通常非常贵(运营商之间结算)。
  3. 单点故障风险
    • 如果这个大数据中心出问题(断电、故障、被攻击),
    • 你就啥视频都播不了了。

所以不能只靠一个大机房。

2. CDN 的基本思想

CDN = Content Distribution Network,内容分发网。

做的事情:

  • 多个地理位置部署很多服务器集群;
  • 把视频(和其他静态内容,例如图片、CSS、JS 文件)复制到这些节点上;
  • 让用户访问离自己"更近"的某个节点,而不是远处的大数据中心。

CDN 可以分两种类型:

  1. 专用 CDN(private CDN)
    • 由内容提供商自己建的。
    • 例如:谷歌有自己的 CDN 来分发 YouTube 视频、谷歌搜索结果等。
  2. 第三方 CDN(third-party CDN)
    • 像专门做 CDN 服务的公司:Akamai、Limelight、Level-3 等。
    • 各种网站(比如 NetCinema)可以花钱"租用"这些公司的 CDN 节点来分发自己的视频。

书里用谷歌做了一个例子,让你感受大型内容提供商自己的 CDN 长什么样

谷歌的基础设施大致有三层:

  1. "百万级"大数据中心
    • 全球 14 个左右,其中 8 个在北美、4 个在欧洲、2 个在亚洲。
    • 每个数据中心有十万台以上服务器。
    • 存的是很多非个性化的内容:搜索索引、Gmail 邮件、YouTube 视频库等。
  2. IXP 上的中型集群
    • 在全球约 50 个 IXP(Internet 交换点)处部署集群。
    • 每个集群包含几十到几百台服务器。
    • 负责静态内容:例如 YouTube 视频、静态网页部分。
  3. "深入/enter-deep"集群:直接进入各大 ISP 内部
    • 每个集群通常位于某个运营商机房内,一机架几台到几十台服务器。
    • 这些服务器直接通过 TCP 分发静态内容给该 ISP 的用户。

工作方式举例(用户发起一次搜索):

  1. 用户在浏览器输入搜索内容,访问 google.com
  2. 请求首先会被 DNS 指向离用户最近的"enter-deep 集群"
  3. 这个集群从更大的数据中心("大数据中心")获取或缓存搜索结果。
  4. 返回给用户,用户感受是:响应很快。
  5. 对于 YouTube 视频,附近集群也可以直接缓存热门视频,并插入广告等。

要点:

用户看到的内容其实是由距离自己很近的服务器发出的,而不是远在某个国家的"主机房"。

CDN 部署原则:深入(deep) vs 邀请做客(bring home)

CDN 公司要决定把服务器放在哪儿。书里提到了两种典型设计:

1. 深入(deep,Akamai 的模式)

  • 把服务器集群部署在世界各地接入 ISP 的网络"边缘",尽量靠近终端用户。
  • Akamai 大约在 1700 个位置部署了这样的集群。

优点:

  • 路径短、经过的链路/路由器少 ⇒ 延迟和丢包更低,用户体验好。

缺点:

  • 点太多,很分散
  • 维护、管理难度大(运维成本高)

2. 邀请做客(bring home / 邀请做客策略)

  • Limelight 等 CDN 公司采用:
  • 不把服务器放到每个 ISP 里,而是放在较少数量的关键位置(例如 10 个左右的大型集群),这些位置通常是 Internet 交换点(IXP)。

优点:

  • 集中 ⇒ 易于维护和管理,成本低。

缺点:

  • 集群离某些用户比较远 ⇒ 时延和丢包可能略高。

实际使用中,两种方式可以混合。

一旦 CDN 的位置选好了,下一步就是:

决定哪些视频在每个集群里存一份副本,哪些只按需"拉取"。

这部分书也提到:不可能把所有视频的副本都放在每个集群,只能对热门内容多放副本,对冷门内容按需拉。

CDN 操作:NetCinema + KingCDN + DNS

这一块书里用一个例子讲CDN 是怎么用 DNS 把你"引导"到某个合适的 CDN 节点的

场景设定

  • 有一个视频网站:NetCinema
  • 它自己不建 CDN,而是雇了第三方 KingCDN 来帮忙分发视频。
  • NetCinema 网站上每个视频对应一个 URL,比如:
    • http://video.netcinema.com/6Y7B23V

重点:URL 里的主机名是 video.netcinema.com

关键点:CDN 如何"截获并重定向"这个请求?

CDN 利用了 DNS

  1. 用户点击链接 video.netcinema.com/6Y7B23V

    浏览器先要解析域名 video.netcinema.com,于是向**本地 DNS 服务器(LDNS)**发出 DNS 查询。

  2. 本地 DNS 服务器发现:

    • 这是 netcinema.com 这个域名下的 video 子域。
    • 为了把请求交给 KingCDN,NetCinema 事先把自己的权威 DNS 设置成:
      • video.netcinema.com 不直接给出 IP
      • 而是返回一个**"别名"(CNAME)**,指向 KingCDN 域名里的某个主机名,例如:
        • a1105.kingcdn.com

    所以:

    • LDNS 拿到的不是 IP,而是:

      "这个域名其实是 a1105.kingcdn.com。"

  3. 接下来,LDNS 又需要解析 a1105.kingcdn.com

    • 于是向 KingCDN 的权威 DNS 服务器发起新的 DNS 查询。
  4. KingCDN 的 DNS 系统在这里做两件事:

    • 根据发起查询的 LDNS 的 IP 地址,推断"这个用户大概在哪个地区";
    • 再根据自己的策略(后面讲"集群选择策略")选择一个合适的 CDN 集群里的一台服务器,返回其 IP 地址。
  5. LDNS 把这个 IP 地址返回给用户主机。

    此时,对浏览器来说,只知道:

    "video.netcinema.com 的 IP 是 X.X.X.X。"

  6. 浏览器跟这个 IP 建立 TCP 连接,并发送 HTTP GET 请求,

    • 请求里仍然写的是:GET /6Y7B23VHost: video.netcinema.com
    • 实际上,这台服务器是 KingCDN 集群中的某一个节点,它会根据 URL 找到相应的视频文件或者 DASH 的告示文件,然后开始一段一段往你这边发。

如果使用 DASH:

  • 服务器先返回 manifest 文件,列出不同版本、不同 chunk 的 URL;
  • 客户端再按 DASH 的逻辑选择版本、请求 chunk。

总结一下这个 DNS 技巧:

NetCinema 把 video.netcinema.com 的解析权"交给" KingCDN,

KingCDN 利用 DNS 查询中携带的 LDNS 信息,来决定把你指向哪一个 CDN 集群。

集群选择策略(cluster selection strategy)

最后一节讲:CDN 怎么决定把你派到哪个集群?

1. 利用 LDNS 的地理位置(最简单)

"地理上最为邻近"策略

  • CDN 维护一张"IP → 地理位置"的数据库(比如书里提到的 Quova、MaxMind 之类的服务公司);

  • 每个 LDNS 的 IP 都被映射到一个地理位置(大概的国家/城市);

  • 当某个 LDNS 用它的 IP 向 CDN DNS 发起查询时,CDN 就认为:

    "这个 LDNS 代表的用户大概在这个地区。"

  • 然后把这个用户派到地理上最近的某个 CDN 集群(例如直线距离最近)。

优点:

  • 简单、实现容易,对大多数用户而言效果还可以。

缺点:

  • LDNS 不一定就在用户身边,有时候 LDNS 可能在别的城市,甚至别的省;
  • 地理上最近 ≠ 网络路径最短(中间可能绕不少 AS 路由)。
  • 而且静态数据库不能及时反映网络状态变化(某条链路突然很拥塞)。

2. 实时测量(更聪明但更复杂)

更高级的办法:CDN 主动测量"某个集群到某个 LDNS 的网络时延/带宽",再用这个结果做决策。

方法:

  • CDN 定期让每个集群向世界各地的 LDNS 发送"探测包"(例如:ping、DNS 查询等),测出 RTT、可用带宽等指标;
  • 把这些指标存起来,当某个 LDNS 来解析时,就选对它"延迟最小、带宽最好"的那个集群。

优点:

  • 能更准确反映当前网络状况(比如某条路径临时很拥塞,就不会选那条路上的集群)。

缺点:

  • 实现复杂、开销大;
  • 需要很多测量流量;
  • 不是所有 LDNS 都适合被长期测量。

实际中,CDN 通常会综合使用

  • 先基于地理位置做一个粗选;
  • 再结合历史测量数据做微调。

2.6.4 学习案例:Netflix、YouTube和"看看"

  • 我们已经学完了"视频怎么压缩、怎么用 HTTP 流、怎么用 CDN 分发"等基础原理;
  • 现在看三个真实的大规模系统:
    Netflix、YouTube、看看(一个 P2P 视频系统)
  • 虽然实现方式差别很大,但都在用前面讲过的那些思想。

可以理解成:

"理论讲完了,下面看 3 个'现实中的大项目'到底怎么运用这些理论。"

1. Netflix:专用 CDN + 云 + DASH

1. Netflix 影响力有多大?

书里说:

2015 年,Netflix 产生了北美住宅 ISP 下载流量的 37%。

意思:

  • 所有北美家庭宽带下行流量里,超过三分之一都是在看 Netflix
  • 所以 Netflix 是美国第一大的"在线视频+电视节目提供商"。

这就是说:

"Netflix 已经大到会明显影响运营商的网络负载。"

2. Netflix 的两块关键基础设施

书里提到 Netflix 视频分发依赖两大部分:

  1. 亚马逊云(AWS)
    • Netflix 自己没建大数据中心,而是把后台逻辑放在亚马逊云上(用户登录、计费、推荐等)。
    • 你在网页上选电影,其实是在访问 Netflix 放在 AWS 上的 Web 服务。
  2. 自己的专用 CDN(Open Connect)
    • 一开始 Netflix 用第三方 CDN(比如 Akamai)分发视频。
    • 后来流量太大,自己搞了一个专用 CDN,视频就从自建 CDN 发出。
    • 但网页仍然可能用 Akamai 之类的 CDN。

可以理解成:

"脑子在亚马逊云里(控制逻辑),身体(视频数据)在自己建的 CDN 上。"

图 2-25 里灰色云状的是"亚马逊云里的服务器",右边一堆是"Netflix 自己的 CDN 服务器"。

3. 在亚马逊云里做的三件事

图 2-25 下面有三条小点,其实就是 Netflix 在 AWS 上干的事情:

  1. 内容摄取(Content ingestion)

    • Netflix 必须先拿到每一部电影/电视剧的母带(高质量原始视频),上传到亚马逊云里的服务器。
    • 来源:制片公司给的片源。
  2. 内容处理(Content processing)

    • 在云里的机器上,把母带视频转成多种格式、多种码率:
      • 适配电脑、手机、平板、游戏机等不同设备;
      • 每种格式又生成多个码率版本(300k、1M、3M...)。
    • 这一步其实就是我们前面讲的视频压缩 + 编码。
    • 最终得到:"许多版本 + 许多小块(DASH chunk)" 的文件集合。
  3. 向专用 CDN 上传版本

    • 当所有版本都生成好了,就从亚马逊云把这些文件推送到 Netflix 自己的 CDN 服务器

    • 相当于:

      "制作好了货,就运到各地仓库(CDN 节点)。"

4. Netflix 自建 CDN 的部署方式(Open Connect)

书里接着讲 Netflix 自建 CDN 是怎么铺的:

  • 刚开始(2007 年左右)
    • Netflix 做流式视频时,是雇 3 个第三方 CDN 公司来分发。
  • 后来
    • Netflix 建立了自己的专用 CDN(Open Connect),大部分视频都由自己的 CDN 发。

部署地点:

  1. 在 IXP 上放服务器机架
    • Netflix 在全球 50 多个 IXP 位置放机架(机架 = 一整排服务器)。
    • 每个机架里有多台服务器,存放 Netflix 的视频库(多版本、支持 DASH)。
  2. 在部分 ISP 内部放机架
    • 一些合作的 ISP 会在自己的网络机房里放 Netflix 的机架。
    • Netflix 给他们提供部署指南,甚至免费提供机架 ,因为对双方都是好事:
      • Netflix:离用户近,质量好;
      • ISP:流量走内部,不占对外出口,省钱。

机架规模(一个机架里):

  • 有几个 10Gbps 的网口;
  • 存储容量 > 100TB;
  • 能装多少服务器视情况而定。

机架里的内容策略:

  • IXP 上的机架:通常存放几台服务器就能装下一整个 Netflix 流式视频库
  • ISP 内部的机架:有的可能只存放最热门的视频子集

重要细节:

  • Netflix 不使用"拉高速缓存(HTTP 缓存)" ,而是直接把视频 事先推送 到 CDN 服务器上。
    • 即:不是等有人看才从中心拉,而是提前把热门内容推过去。
  • 对于存不下全部库的机架,只存热门内容;冷门视频则从其他 CDN 服务器送。

5. 播放时:Netflix 怎么帮你选"最合适的 CDN 服务器"?

这一段是核心:Netflix 如何把你引导到某个 CDN 节点上。

流程可以按类似步骤理解:

  1. 你在 Netflix 网站里浏览影片列表(Web 在 AWS 上)

    • 当你选择一部电影准备播放时,运行在亚马逊云里的 Netflix 软件要决定:

      "这部电影应该由哪个 CDN 服务器给你播?"

  2. Netflix 软件会根据:

    • 你所在的住宅 ISP;
    • 该 ISP 里是否部署了 Netflix 机架;
    • 或最近的 IXP 机架;
      等信息,选出一个"最合适的服务器"。

    简单理解为:

    • 如果你的 ISP 里有 Netflix 机架,就优先选本 ISP 的机架;
    • 没有的话,就选离你最近的 IXP 机架。
  3. 一旦选好某个 CDN 服务器,Netflix 会把:

    • 该服务器的 IP 地址
    • 该电影不同版本的 URL 和资源配置文件(类似 DASH 的 manifest)
      返回给你的客户端(浏览器 / App)。
  4. 客户端收到这些信息后,就按 2.6.2 里说的方式:

    • 用 HTTP GET 请求不同版本的 chunk;
    • 大约以 4 秒为一个小块;
    • 播放过程中,根据当前下载速度估算带宽,动态选择高/低码率块(DASH 自适应)。

这里的关键点:

Netflix 不再用 DNS 重定向来做"选 CDN 服务器"

而是在应用层(Netflix 的后台软件)里直接告诉你:

"你就找这台服务器,这些 URL 是属于它的。"

这样设计很"干净":

  • DNS 不需要搞复杂的重定向逻辑;
  • 应用层能更灵活地根据更多信息(用户账号、位置、历史测量)来选服务器。

6. Netflix 的几个设计"亮点"

最后一段总结:

  • 它用到了本章讲的许多技术:自适应流(DASH)+ CDN 分发
  • 但因为它只做视频,而网页用别的 CDN ,所以能简化自己的 CDN 设计:
    • 不需要给 Web 页做缓存,只针对视频做推送;
    • 不用 DNS 重定向,直接由 Netflix 软件告诉你去哪台服务器。
  • 它使用"推高密缓存"(提前把热门内容推到边缘),而不是传统"拉高速缓存"。

2. YouTube:自建 CDN + HTTP 渐进式下载(非 DASH)

1. YouTube 的规模

书里说:

  • 每分钟有 300 小时的视频上传,每天有几十亿次观看;
  • YouTube 是世界最大的视频共享网站;
  • 2006 年被谷歌收购。

2. YouTube 的 CDN 布局

跟 Netflix 类似,但也有不同:

  • 谷歌有自己的专用 CDN,用来分发 YouTube 视频;
  • 几百个 IXP 和 ISP 里部署了服务器集群;
  • 再加上我们前面学习案例里提到的那些大数据中心 + enter-deep 集群,一起服务于 YouTube。

换句话说:

YouTube 就是跑在谷歌那套庞大的自建 CDN 上。

3. 集群选择:用 DNS 重定向 + RTT 最小

不同于 Netflix 的"应用层选择",谷歌更偏向 DNS 方式:

  • 当你访问 YouTube 时,DNS 会把你指向某个集群;

  • 谷歌的策略通常是:

    让你被分配到 RTT 最小(往返时延最短)的集群。

不过书里也提到一个细节:

  • 为了平衡集群负载,有时会把一部分用户"送到稍远一点的集群";
  • 这样不会都挤在最近的集群,把它挤爆。

4. YouTube 的流式方式:HTTP 流 + 多个版本,但没有 DASH

这里和 Netflix 最大的区别来了:

  • YouTube 使用 HTTP 流,但通常不做自适应码率(至少书写作时是这样)。
  • 每个视频有多个不同比特率、不同质量的版本(480p、720p、1080p...),
  • 但需要你在客户端 手动选择一个版本(早期确实如此)。

为了避免浪费带宽,书里说 YouTube 会:

  • 使用 HTTP 请求中"字节范围(Range)"的方式,限制传输的数据速率
  • 不会一次性把视频全推满带宽,而是控制在一定"节奏"内传输,保证边看边下即可。

重点对比:

  • Netflix:DASH,自适应码率,客户端自动选版本。
  • YouTube:多版本,但不自适应,需要用户选;传输速率由服务器用 HTTP 字节范围控制。

5. 视频的上传和转码处理

书里还提了 YouTube 上传流程:

  • 每天几百万个视频被上传;
  • 上传时,视频先以 HTTP 形式上传到服务器;
  • 然后在谷歌数据中心里进行处理:
    • 转码成 YouTube 内部格式;
    • 生成多个不同码率的版本;
  • 这些加工工作全部在谷歌数据中心完成。

3. "看看":P2P + CDN 的混合方式

最后一个案例是**"看看"视频系统**(可以把它想象成类似早期的 PPLive / 迅雷看看那样的 P2P 视频)。

1. 为什么要搞 P2P?

前面 Netflix / YouTube 都是:

  • "服务器 + CDN 往用户那里下发视频"
  • 所有带宽和服务器成本都要由内容提供商承担。

这就有个问题:

  • 流量一旦非常大,CDN 部署和带宽费用会非常贵。

于是"看看"选择了另一种路子:

利用用户之间互相传视频(P2P)来分摊流量和成本

简单理解:

  • 每个正在看视频的人,既是"观众"(client),也是"供给者"(server)。
  • 你看的这部剧,如果你已经下载了一部分,就可以把这部分再传给别人。
  • 这样:
    • CDN 只需要提供一部分"种子流量";
    • 其余大量流量由用户之间互传完成,大大节省成本。

2. P2P 流媒体大致怎么干?

书里说它类似于 BitTorrent,但又不完全一样。

大致过程:

  1. 当你要看某个视频,客户端软件(看看播放器)会向系统发出请求。
  2. 系统会找到已经在看这个视频或刚看完的视频的其他用户(peers)
    • 并且记录每个用户手上"有哪些块"。
  3. 然后系统安排:
    • 哪些块从 CDN 节点下;
    • 哪些块从哪个 peer 下;
    • 目标是:
      • 确保马上要播的那一段块优先到达(减少卡顿);
      • 同时利用尽可能多的 peer,减轻 CDN 压力。

和 BitTorrent 不同的一点:

  • BitTorrent 不管你什么时候能播放,只要最终把文件下完就行;
  • P2P 流媒体必须保证播放连续,不中断,所以调度更讲究"块的顺序和时间"。

3. 看看是纯 P2P 还是混合 CDN-P2P?

书里后面说到:

  • 看看系统已经发展成一种混合 CDN-P2P 流式系统

含义:

  • 背后仍然部署了大量服务器和 CDN 节点,
  • 但不会所有流量都从 CDN 出来,而是把一部分负载交给 P2P 网络。

典型策略:

  • 当 P2P 网络中某个视频的流量足够大,节点足够多 时,
    • 大部分数据都在用户之间互传,CDN 只要少量补充。
  • 当 P2P 流量不足(在线用户不多或者某些块稀缺)时,
    • 客户端就会更多地向 CDN 请求,保证播放不会卡。

书里提到:

  • "如果 P2P 流量不足以支撑,客户端将重新启动 CDN 连接,把视频拉回来。"

你可以把它想象成:

  • 有很多人一起搬货(P2P),老板(CDN)只在大家搬不动时上手帮忙;
  • 这样既能保证货一定搬完(QoS),又能让老板少出力(降低成本)。
系统 主要流式方式 自适应吗 CDN 使用方式 选服务器/集群方式 特点
Netflix HTTP + DASH :客户端自动选择不同码率块 自建专用 CDN(Open Connect),提前把热门视频推到 IXP/ISP 机架 应用层软件(在 AWS 上)为每个用户选一个"最佳"服务器,把 IP + URL 列表发给客户端 设计干净,充分利用 DASH,自建 CDN,推送缓存
YouTube HTTP 渐进式流 一般不自适应(用户手动选清晰度) 跑在谷歌的专用 CDN 上,分布于大量 IXP/ISP 和数据中心 DNS 重定向为主:选 RTT 最小或负载合适的集群 规模极大,上传量很高,转码在谷歌数据中心完成
看看 P2P + CDN 混合流 实际上"自适应"取决于 P2P/服务器调度策略 有 CDN 服务器,但大量内容由用户之间 P2P 互传 系统调度:决定哪些块从 P2P peers 下、哪些从 CDN 下 用用户的上传带宽分摊成本,减少运营商和 CDN 带宽费用
相关推荐
序属秋秋秋1 小时前
《Linux系统编程之进程环境》【地址空间】
linux·运维·服务器·c语言·c++·系统编程·进程地址空间
2***65631 小时前
华为数据中心CE系列交换机级联M-LAG配置示例
服务器·华为·php
z***02601 小时前
服务器部署,用 nginx 部署后页面刷新 404 问题,宝塔面板修改(修改 nginx.conf 配置文件)
运维·服务器·nginx
shizhan_cloud1 小时前
SMB 服务器
linux·运维·服务器
可爱又迷人的反派角色“yang”1 小时前
Mysql数据库(一)
运维·服务器·前端·网络·数据库·mysql·nginx
abcefg_h1 小时前
HTTPS详解,及与HTTP的差异
网络协议·http·https
拾忆,想起1 小时前
Dubbo服务多版本管理全攻略:实现平滑升级与版本兼容
服务器·网络·微服务·架构·dubbo
zt1985q1 小时前
本地部署问答社区 Apache Anwser 并实现外部访问
运维·服务器·windows·网络协议
网安老伯1 小时前
劝退,劝退,关于自学/跳槽/转行做网络安全行业的一些建议
运维·python·网络协议·web安全·网络安全·跳槽·职场发展