This commit is contained in:
louzefeng
2024-07-11 05:50:32 +00:00
parent bf99793fd0
commit d3828a7aee
6071 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,145 @@
<audio id="audio" title="第18讲 | DNS协议网络世界的地址簿" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/c5/34/c56a67b3e6e791b6677d9d327b3fd834.mp3"></audio>
前面我们讲了平时常见的看新闻、支付、直播、下载等场景现在网站的数目非常多常用的网站就有二三十个如果全部用IP地址进行访问恐怕很难记住。于是就需要一个地址簿根据名称就可以查看具体的地址。
例如,我要去西湖边的“外婆家”,这就是名称,然后通过地址簿,查看到底是哪条路多少号。
## DNS服务器
在网络世界也是这样的。你肯定记得住网站的名称但是很难记住网站的IP地址因而也需要一个地址簿就是**DNS服务器**。
由此可见DNS在日常生活中多么重要。每个人上网都需要访问它但是同时这对它来讲也是非常大的挑战。一旦它出了故障整个互联网都将瘫痪。另外上网的人分布在全世界各地如果大家都去同一个地方访问某一台服务器时延将会非常大。因而**DNS服务器一定要设置成高可用、高并发和分布式的**。
于是,就有了这样**树状的层次结构**。
<img src="https://static001.geekbang.org/resource/image/89/4d/890ff98fde625c6a60fb71yy22d8184d.jpg" alt="">- 根DNS服务器 返回顶级域DNS服务器的IP地址
<li>
顶级域DNS服务器返回权威DNS服务器的IP地址
</li>
<li>
权威DNS服务器 返回相应主机的IP地址
</li>
## DNS解析流程
为了提高DNS的解析性能很多网络都会就近部署DNS缓存服务器。于是就有了以下的DNS解析流程。
<li>
电脑客户端会发出一个DNS请求问www.163.com的IP是啥啊并发给本地域名服务器 (本地DNS)。那本地域名服务器 (本地DNS) 是什么呢如果是通过DHCP配置本地DNS由你的网络服务商ISP如电信、移动等自动分配它通常就在你网络服务商的某个机房。
</li>
<li>
本地DNS收到来自客户端的请求。你可以想象这台服务器上缓存了一张域名与之对应IP地址的大表格。如果能找到 www.163.com它就直接返回IP地址。如果没有本地DNS会去问它的根域名服务器“老大能告诉我www.163.com的IP地址吗”根域名服务器是最高层次的全球共有13套。它不直接用于域名解析但能指明一条道路。
</li>
<li>
根DNS收到来自本地DNS的请求发现后缀是 .com“哦www.163.com啊这个域名是由.com区域管理我给你它的顶级域名服务器的地址你去问问它吧。”
</li>
<li>
本地DNS转向问顶级域名服务器“老二你能告诉我www.163.com的IP地址吗”顶级域名服务器就是大名鼎鼎的比如 .com、.net、 .org这些一级域名它负责管理二级域名比如 163.com所以它能提供一条更清晰的方向。
</li>
<li>
顶级域名服务器说:“我给你负责 www.163.com 区域的权威DNS服务器的地址你去问它应该能问到。”
</li>
<li>
本地DNS转向问权威DNS服务器“您好www.163.com 对应的IP是啥呀”163.com的权威DNS服务器它是域名解析结果的原出处。为啥叫权威呢就是我的域名我做主。
</li>
<li>
权威DNS服务器查询后将对应的IP地址X.X.X.X告诉本地DNS。
</li>
<li>
本地DNS再将IP地址返回客户端客户端和目标建立连接。
</li>
至此我们完成了DNS的解析过程。现在总结一下整个过程我画成了一个图。
<img src="https://static001.geekbang.org/resource/image/71/e8/718e3a1a1a7927302b6a0f836409e8e8.jpg" alt="">
## 负载均衡
站在客户端角度,这是一次**DNS递归查询过程。<strong>因为本地DNS全权为它效劳它只要坐等结果即可。在这个过程中DNS除了可以通过名称映射为IP地址它还可以做另外一件事就是**负载均衡</strong>
还是以访问“外婆家”为例,还是我们开头的“外婆家”,但是,它可能有很多地址,因为它在杭州可以有很多家。所以,如果一个人想去吃“外婆家”,他可以就近找一家店,而不用大家都去同一家,这就是负载均衡。
DNS首先可以做**内部负载均衡**。
例如一个应用要访问数据库在这个应用里面应该配置这个数据库的IP地址还是应该配置这个数据库的域名呢显然应该配置域名因为一旦这个数据库因为某种原因换到了另外一台机器上而如果有多个应用都配置了这台数据库的话一换IP地址就需要将这些应用全部修改一遍。但是如果配置了域名则只要在DNS服务器里将域名映射为新的IP地址这个工作就完成了大大简化了运维。
在这个基础上我们可以再进一步。例如某个应用要访问另外一个应用如果配置另外一个应用的IP地址那么这个访问就是一对一的。但是当被访问的应用撑不住的时候我们其实可以部署多个。但是访问它的应用如何在多个之间进行负载均衡只要配置成为域名就可以了。在域名解析的时候我们只要配置策略这次返回第一个IP下次返回第二个IP就可以实现负载均衡了。
另外一个更加重要的是DNS还可以做**全局负载均衡**。
为了保证我们的应用高可用往往会部署在多个机房每个地方都会有自己的IP地址。当用户访问某个域名的时候这个IP地址可以轮询访问多个数据中心。如果一个数据中心因为某种原因挂了只要在DNS服务器里面将这个数据中心对应的IP地址删除就可以实现一定的高可用。
另外,我们肯定希望北京的用户访问北京的数据中心,上海的用户访问上海的数据中心,这样,客户体验就会非常好,访问速度就会超快。这就是全局负载均衡的概念。
## 示例DNS访问数据中心中对象存储上的静态资源
我们通过DNS访问数据中心中对象存储上的静态资源为例看一看整个过程。
假设全国有多个数据中心托管在多个运营商每个数据中心三个可用区Available Zone。对象存储通过跨可用区部署实现高可用性。在每个数据中心中都至少部署两个内部负载均衡器内部负载均衡器后面对接多个对象存储的前置服务器Proxy-server
<img src="https://static001.geekbang.org/resource/image/0b/b6/0b241afef775a1c942c5728364b302b6.jpg" alt="">
<li>
当一个客户端要访问object.yourcompany.com的时候需要将域名转换为IP地址进行访问所以它要请求本地DNS解析器。
</li>
<li>
本地DNS解析器先查看看本地的缓存是否有这个记录。如果有则直接使用因为上面的过程太复杂了如果每次都要递归解析就太麻烦了。
</li>
<li>
如果本地无缓存则需要请求本地的DNS服务器。
</li>
<li>
本地的DNS服务器一般部署在你的数据中心或者你所在的运营商的网络中本地DNS服务器也需要看本地是否有缓存如果有则返回因为它也不想把上面的递归过程再走一遍。
</li>
<li>
至 7. 如果本地没有本地DNS才需要递归地从根DNS服务器查到.com的顶级域名服务器最终查到 yourcompany.com 的权威DNS服务器给本地DNS服务器权威DNS服务器按说会返回真实要访问的IP地址。
</li>
对于不需要做全局负载均衡的简单应用来讲yourcompany.com的权威DNS服务器可以直接将 object.yourcompany.com这个域名解析为一个或者多个IP地址然后客户端可以通过多个IP地址进行简单的轮询实现简单的负载均衡。
但是对于复杂的应用,尤其是跨地域跨运营商的大型应用,则需要更加复杂的全局负载均衡机制,因而需要专门的设备或者服务器来做这件事情,这就是**全局负载均衡器****GSLB****Global Server Load Balance**)。
在yourcompany.com的DNS服务器中一般是通过配置CNAME的方式给 object.yourcompany.com起一个别名例如 object.vip.yourcomany.com然后告诉本地DNS服务器让它请求GSLB解析这个域名GSLB就可以在解析这个域名的过程中通过自己的策略实现负载均衡。
图中画了两层的GSLB是因为分运营商和地域。我们希望不同运营商的客户可以访问相同运营商机房中的资源这样不跨运营商访问有利于提高吞吐量减少时延。
<li>
第一层GSLB通过查看请求它的本地DNS服务器所在的运营商就知道用户所在的运营商。假设是移动通过CNAME的方式通过另一个别名 object.yd.yourcompany.com告诉本地DNS服务器去请求第二层的GSLB。
</li>
<li>
第二层GSLB通过查看请求它的本地DNS服务器所在的地址就知道用户所在的地理位置然后将距离用户位置比较近的Region里面六个**内部负载均衡****SLB**S**erver Load Balancer**的地址返回给本地DNS服务器。
</li>
<li>
本地DNS服务器将结果返回给本地DNS解析器。
</li>
<li>
本地DNS解析器将结果缓存后返回给客户端。
</li>
<li>
客户端开始访问属于相同运营商的距离较近的Region 1中的对象存储当然客户端得到了六个IP地址它可以通过负载均衡的方式随机或者轮询选择一个可用区进行访问。对象存储一般会有三个备份从而可以实现对存储读写的负载均衡。
</li>
## 小结
好了,这节内容就到这里了,我们来总结一下:
<li>
DNS是网络世界的地址簿可以通过域名查地址因为域名服务器是按照树状结构组织的因而域名查找是使用递归的方法并通过缓存的方式增强性能
</li>
<li>
在域名和IP的映射过程中给了应用基于域名做负载均衡的机会可以是简单的负载均衡也可以根据地址和运营商做全局的负载均衡。
</li>
最后,给你留两个思考题:
<li>
全局负载均衡为什么要分地址和运营商呢?
</li>
<li>
全局负载均衡使用过程中,常常遇到失灵的情况,你知道具体有哪些情况吗?对应应该怎么来解决呢?
</li>
我们的专栏更新过半了,不知你掌握得如何?每节课后我留的思考题,你都有没有认真思考,并在留言区写下答案呢?我会从**已发布的文章中选出一批认真留言的同学**,赠送**学习奖励礼券**和我整理的**独家网络协议知识图谱**。
欢迎你留言和我讨论。趣谈网络协议,我们下期见!

View File

@@ -0,0 +1,166 @@
<audio id="audio" title="第19讲 | HttpDNS网络世界的地址簿也会指错路" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/c5/8e/c5878b08f79096cdad80d9f9e656818e.mp3"></audio>
上一节我们知道了DNS的两项功能第一是根据名称查到具体的地址另外一个是可以针对多个地址做负载均衡而且可以在多个地址中选择一个距离你近的地方访问。
然而有时候这个地址簿也经常给你指错路明明距离你500米就有个吃饭的地方非要把你推荐到5公里外。为什么会出现这样的情况呢
还记得吗当我们发出请求解析DNS的时候首先会先连接到运营商本地的DNS服务器由这个服务器帮我们去整棵DNS树上进行解析然后将解析的结果返回给客户端。但是本地的DNS服务器作为一个本地导游往往有自己的“小心思”。
## 传统DNS存在哪些问题
### 1.域名缓存问题
它可以在本地做一个缓存也就是说不是每一个请求它都会去访问权威DNS服务器而是访问过一次就把结果缓存到自己本地当其他人来问的时候直接就返回这个缓存数据。
这就相当于导游去过一个饭店,自己脑子记住了地址,当有一个游客问的时候,他就凭记忆回答了,不用再去查地址簿。这样经常存在的一个问题是,人家那个饭店明明都已经搬了,结果作为导游,他并没有刷新这个缓存,结果你辛辛苦苦到了这个地点,发现饭店已经变成了服装店,你是不是会非常失望?
另外,有的运营商会把一些静态页面,缓存到本运营商的服务器内,这样用户请求的时候,就不用跨运营商进行访问,这样既加快了速度,也减少了运营商之间流量计算的成本。在域名解析的时候,不会将用户导向真正的网站,而是指向这个缓存的服务器。
很多情况下是看不出问题的,但是当页面更新,用户会访问到老的页面,问题就出来了。例如,你听说一个餐馆推出了一个新菜,你想去尝一下。结果导游告诉你,在这里吃也是一样的。有的游客会觉得没问题,但是对于想尝试新菜的人来说,如果导游说带你去,但其实并没有吃到新菜,你是不是也会非常失望呢?
再就是本地的缓存,往往使得全局负载均衡失败,因为上次进行缓存的时候,缓存中的地址不一定是这次访问离客户最近的地方,如果把这个地址返回给客户,那肯定就会绕远路。
就像上一次客户要吃西湖醋鱼的事,导游知道西湖边有一家,因为当时游客就在西湖边,可是,下一次客户在灵隐寺,想吃西湖醋鱼的时候,导游还指向西湖边的那一家,那这就绕得太远了。
<img src="https://static001.geekbang.org/resource/image/8b/eb/8b5e670e22c459e859293db1bed643eb.jpg" alt="">
### 2.域名转发问题
缓存问题还是说本地域名解析服务还是会去权威DNS服务器中查找只不过不是每次都要查找。可以说这还是大导游、大中介。还有一些小导游、小中介有了请求之后直接转发给其他运营商去做解析自己只是外包了出去。
这样的问题是如果是A运营商的客户访问自己运营商的DNS服务器如果A运营商去权威DNS服务器查询的话权威DNS服务器知道你是A运营商的就返回给一个部署在A运营商的网站地址这样针对相同运营商的访问速度就会快很多。
但是A运营商偷懒将解析的请求转发给B运营商B运营商去权威DNS服务器查询的话权威服务器会误认为你是B运营商的那就返回给你一个在B运营商的网站地址吧结果客户的每次访问都要跨运营商速度就会很慢。
<img src="https://static001.geekbang.org/resource/image/cf/f1/cfde4b3bc5c0aabaaa81f3a26cd99cf1.jpg" alt="">
### 3.出口NAT问题
前面讲述网关的时候,我们知道,出口的时候,很多机房都会配置**NAT**,也即**网络地址转换**使得从这个网关出去的包都换成新的IP地址当然请求返回的时候在这个网关再将IP地址转换回去所以对于访问来说是没有任何问题。
但是一旦做了网络地址的转换权威的DNS服务器就没办法通过这个地址来判断客户到底是来自哪个运营商而且极有可能因为转换过后的地址误判运营商导致跨运营商的访问。
### 4.域名更新问题
本地DNS服务器是由不同地区、不同运营商独立部署的。对域名解析缓存的处理上实现策略也有区别有的会偷懒忽略域名解析结果的TTL时间限制在权威DNS服务器解析变更的时候解析结果在全网生效的周期非常漫长。但是有的时候在DNS的切换中场景对生效时间要求比较高。
例如双机房部署的时候跨机房的负载均衡和容灾多使用DNS来做。当一个机房出问题之后需要修改权威DNS将域名指向新的IP地址但是如果更新太慢那很多用户都会出现访问异常。
这就像有的导游比较勤快、敬业时时刻刻关注酒店、餐馆、交通的变化问他的时候往往会得到最新情况。有的导游懒一些8年前背的导游词就没换过问他的时候指的路往往就是错的。
### 5.解析延迟问题
从上一节的DNS查询过程来看DNS的查询过程需要递归遍历多个DNS服务器才能获得最终的解析结果这会带来一定的时延甚至会解析超时。
## HttpDNS的工作模式
既然DNS解析中有这么多问题那怎么办呢难不成退回到直接用IP地址这样显然不合适所以就有了** HttpDNS**。
HttpDNS其实就是不走传统的DNS解析而是自己搭建基于HTTP协议的DNS服务器集群分布在多个地点和多个运营商。当客户端需要DNS解析的时候直接通过HTTP协议进行请求这个服务器集群得到就近的地址。
这就相当于每家基于HTTP协议自己实现自己的域名解析自己做一个自己的地址簿而不使用统一的地址簿。但是默认的域名解析都是走DNS的因而使用HttpDNS需要绕过默认的DNS路径就不能使用默认的客户端。使用HttpDNS的往往是手机应用需要在手机端嵌入支持HttpDNS的客户端SDK。
通过自己的HttpDNS服务器和自己的SDK实现了从依赖本地导游到自己上网查询做旅游攻略进行自由行爱怎么玩怎么玩。这样就能够避免依赖导游而导游又不专业你还不能把他怎么样的尴尬。
下面我来解析一下** HttpDNS的工作模式**。
在客户端的SDK里动态请求服务端获取HttpDNS服务器的IP列表缓存到本地。随着不断地解析域名SDK也会在本地缓存DNS域名解析的结果。
当手机应用要访问一个地址的时候首先看是否有本地的缓存如果有就直接返回。这个缓存和本地DNS的缓存不一样的是这个是手机应用自己做的而非整个运营商统一做的。如何更新、何时更新手机应用的客户端可以和服务器协调来做这件事情。
如果本地没有就需要请求HttpDNS的服务器在本地HttpDNS服务器的IP列表中选择一个发出HTTP的请求会返回一个要访问的网站的IP列表。
请求的方式是这样的。
```
curl http://106.2.xxx.xxx/d?dn=c.m.163.com
{&quot;dns&quot;:[{&quot;host&quot;:&quot;c.m.163.com&quot;,&quot;ips&quot;:[&quot;223.252.199.12&quot;],&quot;ttl&quot;:300,&quot;http2&quot;:0}],&quot;client&quot;:{&quot;ip&quot;:&quot;106.2.81.50&quot;,&quot;line&quot;:269692944}}
```
手机客户端自然知道手机在哪个运营商、哪个地址。由于是直接的HTTP通信HttpDNS服务器能够准确知道这些信息因而可以做精准的全局负载均衡。
<img src="https://static001.geekbang.org/resource/image/aa/75/aa45cf8a07b563ccea376f712b2e8975.jpg" alt="">
当然当所有这些都不工作的时候可以切换到传统的LocalDNS来解析慢也比访问不到好。那HttpDNS是如何解决上面的问题的呢
其实归结起来就是两大问题。一是解析速度和更新速度的平衡问题二是智能调度的问题对应的解决方案是HttpDNS的缓存设计和调度设计。
### HttpDNS的缓存设计
解析DNS过程复杂通信次数多对解析速度造成很大影响。为了加快解析因而有了缓存但是这又会产生缓存更新速度不及时的问题。最要命的是这两个方面都掌握在别人手中也即本地DNS服务器手中它不会为你定制你作为客户端干着急没办法。
而HttpDNS就是将解析速度和更新速度全部掌控在自己手中。一方面解析的过程不需要本地DNS服务递归的调用一大圈一个HTTP的请求直接搞定要实时更新的时候马上就能起作用另一方面为了提高解析速度本地也有缓存缓存是在客户端SDK维护的过期时间、更新时间都可以自己控制。
HttpDNS的缓存设计策略也是咱们做应用架构中常用的缓存设计模式也即分为客户端、缓存、数据源三层。
<li>
对于应用架构来讲就是应用、缓存、数据库。常见的是Tomcat、Redis、MySQL。
</li>
<li>
对于HttpDNS来讲就是手机客户端、DNS缓存、HttpDNS服务器。
</li>
<img src="https://static001.geekbang.org/resource/image/9e/56/9e0141a2939e7c194689e990859ed456.jpg" alt="">
只要是缓存模式,就存在缓存的过期、更新、不一致的问题,解决思路也是很像的。
例如DNS缓存在内存中也可以持久化到存储上从而APP重启之后能够尽快从存储中加载上次累积的经常访问的网站的解析结果就不需要每次都全部解析一遍再变成缓存。这有点像Redis是基于内存的缓存但是同样提供持久化的能力使得重启或者主备切换的时候数据不会完全丢失。
SDK中的缓存会严格按照缓存过期时间如果缓存没有命中或者已经过期而且客户端不允许使用过期的记录则会发起一次解析保障记录是更新的。
解析可以**同步进行**也就是直接调用HttpDNS的接口返回最新的记录更新缓存也可以**异步进行**添加一个解析任务到后台由后台任务调用HttpDNS的接口。
**同步更新**的**优点**是实时性好缺点是如果有多个请求都发现过期的时候同时会请求HttpDNS多次其实是一种浪费。
同步更新的方式对应到应用架构中缓存的**Cache-Aside机制**,也即先读缓存,不命中读数据库,同时将结果写入缓存。
**异步更新**的**优点**是可以将多个请求都发现过期的情况合并为一个对于HttpDNS的请求任务只执行一次减少HttpDNS的压力。同时可以在即将过期的时候就创建一个任务进行预加载防止过期之后再刷新称为**预加载**
它的**缺点**是当前请求拿到过期数据的时候,如果客户端允许使用过期数据,需要冒一次风险。如果过期的数据还能请求,就没问题;如果不能请求,则失败一次,等下次缓存更新后,再请求方能成功。
<img src="https://static001.geekbang.org/resource/image/df/98/df65059e9b66c32bbbca6febf6ecb298.jpg" alt="">
异步更新的机制对应到应用架构中缓存的**Refresh-Ahead机制**即业务仅仅访问缓存当过期的时候定期刷新。在著名的应用缓存Guava Cache中有个RefreshAfterWrite机制对于并发情况下多个缓存访问不命中从而引发并发回源的情况可以采取只有一个请求回源的模式。在应用架构的缓存中也常常用**数据预热**或者**预加载**的机制。
<img src="https://static001.geekbang.org/resource/image/16/28/161a14f41b3547739982ec551aa26928.jpg" alt="">
### HttpDNS的调度设计
由于客户端嵌入了SDK因而就不会因为本地DNS的各种缓存、转发、NAT让权威DNS服务器误会客户端所在的位置和运营商而可以拿到第一手资料。
在**客户端**可以知道手机是哪个国家、哪个运营商、哪个省甚至哪个市HttpDNS服务端可以根据这些信息选择最佳的服务节点访问。
如果有多个节点,还会考虑错误率、请求时间、服务器压力、网络状况等,进行综合选择,而非仅仅考虑地理位置。当有一个节点宕机或者性能下降的时候,可以尽快进行切换。
要做到这一点需要客户端使用HttpDNS返回的IP访问业务应用。客户端的SDK会收集网络请求数据如错误率、请求时间等网络请求质量数据并发送到统计后台进行分析、聚合以此查看不同的IP的服务质量。
在**服务端**应用可以通过调用HttpDNS的管理接口配置不同服务质量的优先级、权重。HttpDNS会根据这些策略综合地理位置和线路状况算出一个排序优先访问当前那些优质的、时延低的IP地址。
HttpDNS通过智能调度之后返回的结果也会缓存在客户端。为了不让缓存使得调度失真客户端可以根据不同的移动网络运营商WIFI的SSID来分维度缓存。不同的运营商或者WIFI解析出来的结果会不同。
<img src="https://static001.geekbang.org/resource/image/3b/ae/3b368yy7a4f2319bd6491bc4e66e55ae.jpg" alt="">
## 小结
好了,这节就到这里了,我们来总结一下,你需要记住这两个重点:
<li>
传统的DNS有很多问题例如解析慢、更新不及时。因为缓存、转发、NAT问题导致客户端误会自己所在的位置和运营商从而影响流量的调度。
</li>
<li>
HttpDNS通过客户端SDK和服务端通过HTTP直接调用解析DNS的方式绕过了传统DNS的这些缺点实现了智能的调度。
</li>
最后,给你留两个思考题。
<li>
使用HttpDNS需要向HttpDNS服务器请求解析域名可是客户端怎么知道HttpDNS服务器的地址或者域名呢
</li>
<li>
HttpDNS的智能调度主要是让客户端选择最近的服务器而有另一种机制使得资源分发到离客户端更近的位置从而加快客户端的访问你知道是什么技术吗
</li>
我们的专栏更新过半了,不知你掌握得如何?每节课后我留的思考题,你都有没有认真思考,并在留言区写下答案呢?我会从已发布的文章中选出一批认真留言的同学,赠送学习奖励礼券和我整理的独家网络协议知识图谱。
欢迎你留言和我讨论。趣谈网络协议,我们下期见!

View File

@@ -0,0 +1,123 @@
<audio id="audio" title="第20讲 | CDN你去小卖部取过快递么" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/8d/a0/8dafced847a138ec2914b8c5f45b5ea0.mp3"></audio>
上一节,我们看到了网站的一般访问模式。
当一个用户想访问一个网站的时候指定这个网站的域名DNS就会将这个域名解析为地址然后用户请求这个地址返回一个网页。就像你要买个东西首先要查找商店的位置然后去商店里面找到自己想要的东西最后拿着东西回家。
**那这里面还有没有可以优化的地方呢?**
例如你去电商网站下单买个东西,这个东西一定要从电商总部的中心仓库送过来吗?原来基本是这样的,每一单都是单独配送,所以你可能要很久才能收到你的宝贝。但是后来电商网站的物流系统学聪明了,他们在全国各地建立了很多仓库,而不是只有总部的中心仓库才可以发货。
电商网站根据统计大概知道,北京、上海、广州、深圳、杭州等地,每天能够卖出去多少书籍、卫生纸、包、电器等存放期比较长的物品。这些物品用不着从中心仓库发出,所以平时就可以将它们分布在各地仓库里,客户一下单,就近的仓库发出,第二天就可以收到了。
这样,用户体验大大提高。当然,这里面也有个难点就是,生鲜这类东西保质期太短,如果提前都备好货,但是没有人下单,那肯定就坏了。这个问题,我后文再说。
**我们先说,我们的网站访问可以借鉴“就近配送”这个思路。**
全球有这么多的数据中心,无论在哪里上网,临近不远的地方基本上都有数据中心。是不是可以在这些数据中心里部署几台机器,形成一个缓存的集群来缓存部分数据,那么用户访问数据的时候,就可以就近访问了呢?
当然是可以的。这些分布在各个地方的各个数据中心的节点,就称为**边缘节点**。
由于边缘节点数目比较多,但是每个集群规模比较小,不可能缓存下来所有东西,因而可能无法命中,这样就会在边缘节点之上。有区域节点,规模就要更大,缓存的数据会更多,命中的概率也就更大。在区域节点之上是中心节点,规模更大,缓存数据更多。如果还不命中,就只好回源网站访问了。
<img src="https://static001.geekbang.org/resource/image/5f/25/5fbe602d9b85966d9a1748d2e6aa6425.jpeg" alt="">
这就是**CDN分发系统的架构**。CDN系统的缓存也是一层一层的能不访问后端真正的源就不打扰它。这也是电商网站物流系统的思路北京局找不到找华北局华北局找不到再找北方局。
有了这个分发系统之后,接下来,**客户端如何找到相应的边缘节点进行访问呢?**
还记得我们讲过的基于DNS的全局负载均衡吗这个负载均衡主要用来选择一个就近的同样运营商的服务器进行访问。你会发现CDN分发网络也是一个分布在多个区域、多个运营商的分布式系统也可以用相同的思路选择最合适的边缘节点。
<img src="https://static001.geekbang.org/resource/image/c4/24/c4d826188e664605d6f8dfb82e348824.jpeg" alt="">
**在没有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服务器。
当本地DNS服务器拿到这个新的域名时需要继续解析这个新的域名。这个时候再访问的就不是web.com的权威DNS服务器了而是web.cdn.com的权威DNS服务器这是CDN自己的权威DNS服务器。在这个服务器上还是会设置一个CNAME指向另外一个域名也即CDN网络的全局负载均衡器。
接下来本地DNS服务器去请求CDN的全局负载均衡器解析域名全局负载均衡器会为用户选择一台合适的缓存服务器提供服务选择的依据包括
<li>
根据用户IP地址判断哪一台服务器距用户最近
</li>
<li>
用户所处的运营商;
</li>
<li>
根据用户所请求的URL中携带的内容名称判断哪一台服务器上有用户所需的内容
</li>
<li>
查询各个服务器当前的负载情况,判断哪一台服务器尚有服务能力。
</li>
基于以上这些条件进行综合分析之后全局负载均衡器会返回一台缓存服务器的IP地址。
本地DNS服务器缓存这个IP地址然后将IP返回给客户端客户端去访问这个边缘节点下载资源。缓存服务器响应用户请求将用户所需内容传送到用户终端。如果这台缓存服务器上并没有用户想要的内容那么这台服务器就要向它的上一级缓存服务器请求内容直至追溯到网站的源服务器将内容拉到本地。
**CDN可以进行缓存的内容有很多种。**
保质期长的日用品比较容易缓存,因为不容易过期,对应到就像电商仓库系统里,就是静态页面、图片等,因为这些东西也不怎么变,所以适合缓存。
<img src="https://static001.geekbang.org/resource/image/ca/1d/caec3ba1086557cbf694c621e7e01e1d.jpeg" alt="">
还记得这个**接入层缓存的架构**吗在进入数据中心的时候我们希望通过最外层接入层的缓存将大部分静态资源的访问拦在边缘。而CDN则更进一步将这些静态资源缓存到离用户更近的数据中心。越接近客户访问性能越好时延越低。
但是静态内容中有一种特殊的内容也大量使用了CDN这个就是前面讲过的[流媒体](https://time.geekbang.org/column/article/9688)。
CDN支持**流媒体协议**例如前面讲过的RTMP协议。在很多情况下这相当于一个代理从上一级缓存读取内容转发给用户。由于流媒体往往是连续的因而可以进行预先缓存的策略也可以预先推送到用户的客户端。
对于静态页面来讲,内容的分发往往采取**拉取**的方式,也即当发现未命中的时候,再去上一级进行拉取。但是,流媒体数据量大,如果出现**回源**,压力会比较大,所以往往采取主动**推送**的模式,将热点数据主动推送到边缘节点。
对于流媒体来讲很多CDN还提供**预处理服务**,也即文件在分发之前,经过一定的处理。例如将视频转换为不同的码流,以适应不同的网络带宽的用户需求;再如对视频进行分片,降低存储压力,也使得客户端可以选择使用不同的码率加载不同的分片。这就是我们常见的,“我要看超清、标清、流畅等”。
对于流媒体CDN来讲有个关键的问题是**防盗链**问题。因为视频是要花大价钱买版权的,为了挣点钱,收点广告费,如果流媒体被其他的网站盗走,在人家的网站播放,那损失可就大了。
最常用也最简单的方法就是**HTTP头的referer字段** 当浏览器发送请求的时候一般会带上referer告诉服务器是从哪个页面链接过来的服务器基于此可以获得一些信息用于处理。如果refer信息不是来自本站就阻止访问或者跳到其它链接。
**referer的机制相对比较容易破解所以还需要配合其他的机制。**
一种常用的机制是**时间戳防盗链**。使用CDN的管理员可以在配置界面上和CDN厂商约定一个加密字符串。
客户端取出当前的时间戳要访问的资源及其路径连同加密字符串进行签名算法得到一个字符串然后生成一个下载链接带上这个签名字符串和截止时间戳去访问CDN。
在CDN服务端根据取出过期时间和当前 CDN 节点时间进行比较确认请求是否过期。然后CDN服务端有了资源及路径时间戳以及约定的加密字符串根据相同的签名算法计算签名如果匹配则一致访问合法才会将资源返回给客户。
然而比如在电商仓库中,我在前面提过,有关生鲜的缓存就是非常麻烦的事情,这对应着就是动态的数据,比较难以缓存。怎么办呢?现在也有**动态CDN主要有两种模式**。
<li>
一种为**生鲜超市模式**,也即**边缘计算的模式**。既然数据是动态生成的,所以数据的逻辑计算和存储,也相应的放在边缘的节点。其中定时从源数据那里同步存储的数据,然后在边缘进行计算得到结果。就像对生鲜的烹饪是动态的,没办法事先做好缓存,因而将生鲜超市放在你家旁边,既能够送货上门,也能够现场烹饪,也是边缘计算的一种体现。
</li>
<li>
另一种是**冷链运输模式**,也即**路径优化的模式**。数据不是在边缘计算生成的而是在源站生成的但是数据的下发则可以通过CDN的网络对路径进行优化。因为CDN节点较多能够找到离源站很近的边缘节点也能找到离用户很近的边缘节点。中间的链路完全由CDN来规划选择一个更加可靠的路径使用类似专线的方式进行访问。
</li>
对于常用的TCP连接在公网上传输的时候经常会丢数据导致TCP的窗口始终很小发送速度上不去。根据前面的TCP流量控制和拥塞控制的原理在CDN加速网络中可以调整TCP的参数使得TCP可以更加激进地传输数据。
可以通过多个请求复用一个连接,保证每次动态请求到达时。连接都已经建立了,不必临时三次握手或者建立过多的连接,增加服务器的压力。另外,可以通过对传输数据进行压缩,增加传输效率。
所有这些手段就像冷链运输,整个物流优化了,全程冷冻高速运输。不管生鲜是从你旁边的超市送到你家的,还是从产地送的,保证到你家是新鲜的。
## 小结
好了,这节就到这里了。咱们来总结一下,你记住这两个重点就好。
<li>
CDN和电商系统的分布式仓储系统一样分为中心节点、区域节点、边缘节点而数据缓存在离用户最近的位置。
</li>
<li>
CDN最擅长的是缓存静态数据除此之外还可以缓存流媒体数据这时候要注意使用防盗链。它也支持动态数据的缓存一种是边缘计算的生鲜超市模式另一种是链路优化的冷链运输模式。
</li>
最后,给你留两个思考题:
<li>
这一节讲了CDN使用DNS进行全局负载均衡的例子CDN如何使用HttpDNS呢
</li>
<li>
客户端对DNS、HttpDNS、CDN访问了半天还没进数据中心你知道数据中心里面什么样吗
</li>
我们的专栏更新到第20讲不知你掌握得如何每节课后我留的思考题你都有没有认真思考并在留言区写下答案呢我会从**已发布的文章中选出一批认真留言的同学**,赠送学习奖励礼券和我整理的独家网络协议知识图谱。
欢迎你留言和我讨论。趣谈网络协议,我们下期见!

View File

@@ -0,0 +1,145 @@
<audio id="audio" title="第21讲 | 数据中心:我是开发商,自己拿地盖别墅" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/66/f4/66330fd4f7fb45367b333fee9775faf4.mp3"></audio>
无论你是看新闻、下订单、看视频、下载文件,最终访问的目的地都在数据中心里面。我们前面学了这么多的网络协议和网络相关的知识,你是不是很好奇,数据中心究竟长啥样呢?
数据中心是一个大杂烩,几乎要用到前面学过的所有知识。
前面讲办公室网络的时候,我们知道办公室里面有很多台电脑。如果要访问外网,需要经过一个叫**网关**的东西,而网关往往是一个路由器。
数据中心里面也有一大堆的电脑,但是它和咱们办公室里面的笔记本或者台式机不一样。数据中心里面是服务器。服务器被放在一个个叫作**机架****Rack**)的架子上面。
数据中心的入口和出口也是路由器,由于在数据中心的边界,就像在一个国家的边境,称为**边界路由器****Border Router**)。为了高可用,边界路由器会有多个。
一般家里只会连接一个运营商的网络,而为了高可用,为了当一个运营商出问题的时候,还可以通过另外一个运营商来提供服务,所以数据中心的边界路由器会连接多个运营商网络。
既然是路由器就需要跑路由协议数据中心往往就是路由协议中的自治区域AS。数据中心里面的机器要想访问外面的网站数据中心里面也是有对外提供服务的机器都可以通过BGP协议获取内外互通的路由信息。这就是我们常听到的**多线BGP**的概念。
如果数据中心非常简单,没几台机器,那就像家里或者宿舍一样,所有的服务器都直接连到路由器上就可以了。但是数据中心里面往往有非常多的机器,当塞满一机架的时候,需要有交换机将这些服务器连接起来,可以互相通信。
这些交换机往往是放在机架顶端的,所以经常称为**TOR****Top Of** **Rack****交换机**。这一层的交换机常常称为**接入层****Access Layer**)。注意这个接入层和原来讲过的应用的接入层不是一个概念。
<img src="https://static001.geekbang.org/resource/image/8f/f8/8fdfb8d4e1cd5a9a086f99b98a7555f8.jpg" alt="">
当一个机架放不下的时候,就需要多个机架,还需要有交换机将多个机架连接在一起。这些交换机对性能的要求更高,带宽也更大。这些交换机称为**汇聚层交换机****Aggregation Layer**)。
数据中心里面的每一个连接都是需要考虑高可用的。这里首先要考虑的是如果一台机器只有一个网卡上面连着一个网线接入到TOR交换机上。如果网卡坏了或者不小心网线掉了机器就上不去了。所以需要至少两个网卡、两个网线插到TOR交换机上但是两个网卡要工作得像一张网卡一样这就是常说的**网卡绑定****bond**)。
这就需要服务器和交换机都支持一种协议**LACP****Link Aggregation Control Protocol**)。它们互相通信,将多个网卡聚合称为一个网卡,多个网线聚合成一个网线,在网线之间可以进行负载均衡,也可以为了高可用作准备。
<img src="https://static001.geekbang.org/resource/image/84/94/84196dedd044cc135bfc28ede4687d94.jpg" alt="">
网卡有了高可用保证但交换机还有问题。如果一个机架只有一个交换机它挂了那整个机架都不能上网了。因而TOR交换机也需要高可用同理接入层和汇聚层的连接也需要高可用性也不能单线连着。
最传统的方法是部署两个接入交换机、两个汇聚交换机。服务器和两个接入交换机都连接接入交换机和两个汇聚都连接当然这样会形成环所以需要启用STP协议去除环但是这样两个汇聚就只能一主一备了。STP协议里我们学过只有一条路会起作用。
<img src="https://static001.geekbang.org/resource/image/11/50/116a168c0eb55fabd7786fca728bd850.jpg" alt="">
交换机有一种技术叫作**堆叠**,所以另一种方法是,将多个交换机形成一个逻辑的交换机,服务器通过多根线分配连到多个接入层交换机上,而接入层交换机多根线分别连接到多个交换机上,并且通过堆叠的私有协议,形成**双活**的连接方式。
<img src="https://static001.geekbang.org/resource/image/10/3a/10aa7eac3fd38dfc2a09d6475ff4d93a.jpg" alt="">
由于对带宽要求更大,而且挂了影响也更大,所以两个堆叠可能就不够了,可以就会有更多的,比如四个堆叠为一个逻辑的交换机。
汇聚层将大量的计算节点相互连接在一起,形成一个集群。在这个集群里面,服务器之间通过二层互通,这个区域常称为一个**POD****Point Of Delivery**),有时候也称为一个**可用区****Available Zon**e
当节点数目再多的时候,一个可用区放不下,需要将多个可用区连在一起,连接多个可用区的交换机称为**核心交换机**。
<img src="https://static001.geekbang.org/resource/image/08/13/080ce3bbe673de38e196b5b741a86313.jpg" alt="">
核心交换机吞吐量更大,高可用要求更高,肯定需要堆叠,但是往往仅仅堆叠,不足以满足吞吐量,因而还是需要部署多组核心交换机。核心和汇聚交换机之间为了高可用,也是全互连模式的。
这个时候还存在一个问题,出现环路怎么办?
一种方式是,不同的可用区在不同的二层网络,需要分配不同的网段。汇聚和核心之间通过三层网络互通的,二层都不在一个广播域里面,不会存在二层环路的问题。三层有环是没有问题的,只要通过路由协议选择最佳的路径就可以了。那为啥二层不能有环路,而三层可以呢?你可以回忆一下二层环路的情况。
<img src="https://static001.geekbang.org/resource/image/be/yy/be86f9a94002cf8d849a229ce5993cyy.jpeg" alt="">
如图核心层和汇聚层之间通过内部的路由协议OSPF找到最佳的路径进行访问而且还可以通过ECMP等价路由在多个路径之间进行负载均衡和高可用。
但是随着数据中心里面的机器越来越多,尤其是有了云计算、大数据,集群规模非常大,而且都要求在一个二层网络里面。这就需要二层互连从**汇聚层**上升为**核心层**,也即在核心以下,全部是二层互连,全部在一个广播域里面,这就是常说的**大二层**。
<img src="https://static001.geekbang.org/resource/image/2a/2c/2aa3787c31c52defc7614c53f0a71d2c.jpg" alt="">
如果大二层横向流量不大,核心交换机数目不多,可以做堆叠,但是如果横向流量很大,仅仅堆叠满足不了,就需要部署多组核心交换机,而且要和汇聚层进行全互连。由于堆叠只解决一个核心交换机组内的无环问题,而组之间全互连,还需要其他机制进行解决。
如果是STP那部署多组核心无法扩大横向流量的能力因为还是只有一组起作用。
于是大二层就引入了**TRILL****Transparent Interconnection of Lots of Link**),即**多链接透明互联协议**。它的基本思想是,二层环有问题,三层环没有问题,那就把三层的路由能力模拟在二层实现。
运行TRILL协议的交换机称为**RBridge**,是**具有路由转发特性的网桥设备**只不过这个路由是根据MAC地址来的不是根据IP来的。
Rbridage之间通过**链路状态协议**运作。记得这个路由协议吗通过它可以学习整个大二层的拓扑知道访问哪个MAC应该从哪个网桥走还可以计算最短的路径也可以通过等价的路由进行负载均衡和高可用性。
<img src="https://static001.geekbang.org/resource/image/b6/af/b6487347ebc5ec8f019e7ac82dd5d4af.jpeg" alt="">
TRILL协议在原来的MAC头外面加上自己的头以及外层的MAC头。TRILL头里面的Ingress RBridge有点像IP头里面的源IP地址Egress RBridge是目标IP地址这两个地址是端到端的在中间路由的时候不会发生改变。而外层的MAC可以有下一跳的Bridge就像路由的下一跳也是通过MAC地址来呈现的一样。
如图中所示的过程有一个包要从主机A发送到主机B中间要经过RBridge 1、RBridge 2、RBridge X等等直到RBridge 3。在RBridge 2收到的包里面分内外两层内层就是传统的主机A和主机B的MAC地址以及内层的VLAN。
在外层首先加上一个TRILL头里面描述这个包从RBridge 1进来的要从RBridge 3出去并且像三层的IP地址一样有跳数。然后再外面目的MAC是RBridge 2源MAC是RBridge 1以及外层的VLAN。
当RBridge 2收到这个包之后首先看MAC是否是自己的MAC如果是要看自己是不是Egress RBridge也即是不是最后一跳如果不是查看跳数是不是大于0然后通过类似路由查找的方式找到下一跳RBridge X然后将包发出去。
RBridge 2发出去的包内层的信息是不变的外层的TRILL头里面。同样描述这个包从RBridge 1进来的要从RBridge 3出去但是跳数要减1。外层的目标MAC变成RBridge X源MAC变成RBridge 2。
如此一直转发直到RBridge 3将外层解出来发送内层的包给主机B。
这个过程是不是和IP路由很像
对于大二层的广播包也需要通过分发树的技术来实现。我们知道STP是将一个有环的图通过去掉边形成一棵树而分发树是一个有环的图形成多棵树不同的树有不同的VLAN有的广播包从VLAN A广播有的从VLAN B广播实现负载均衡和高可用。
<img src="https://static001.geekbang.org/resource/image/bf/f2/bfdd48216f55bdf674fd8638e61d4ff2.jpeg" alt="">
核心交换机之外,就是边界路由器了。至此从服务器到数据中心边界的层次情况已经清楚了。
在核心交换上面往往会挂一些安全设备例如入侵检测、DDoS防护等等。这是整个数据中心的屏障防止来自外来的攻击。核心交换机上往往还有负载均衡器原理前面的章节已经说过了。
在有的数据中心里面对于存储设备还会有一个存储网络用来连接SAN和NAS。但是对于新的云计算来讲往往不使用传统的SAN和NAS而使用部署在x86机器上的软件定义存储这样存储也是服务器了而且可以和计算节点融合在一个机架上从而更加有效率也就没有了单独的存储网络了。
于是整个数据中心的网络如下图所示。
<img src="https://static001.geekbang.org/resource/image/dd/b3/dd39a95064b2132d78e3a2efb0723bb3.jpg" alt="">
这是一个典型的三层网络结构。这里的三层不是指IP层而是指接入层、汇聚层、核心层三层。这种模式非常有利于外部流量请求到内部应用。这个类型的流量是从外到内或者从内到外对应到上面那张图里就是从上到下从下到上上北下南所以称为**南北流量**。
但是随着云计算和大数据的发展,节点之间的交互越来越多,例如大数据计算经常要在不同的节点将数据拷贝来拷贝去,这样需要经过交换机,使得数据从左到右,从右到左,左西右东,所以称为**东西流量**。
为了解决东西流量的问题,演进出了**叶脊网络****Spine/Leaf**)。
<li>
**叶子交换机****leaf**直接连接物理服务器。L2/L3网络的分界点在叶子交换机上叶子交换机之上是三层网络。
</li>
<li>
**脊交换机****spine switch**相当于核心交换机。叶脊之间通过ECMP动态选择多条路径。脊交换机现在只是为叶子交换机提供一个弹性的L3路由网络。南北流量可以不用直接从脊交换机发出而是通过与leaf交换机并行的交换机再接到边界路由器出去。
</li>
<img src="https://static001.geekbang.org/resource/image/99/92/99f86d113a629d81bb52786d80ca5c92.jpg" alt="">
传统的三层网络架构是垂直的结构,而叶脊网络架构是扁平的结构,更易于水平扩展。
## 小结
好了,复杂的数据中心就讲到这里了。我们来总结一下,你需要记住这三个重点。
<li>
数据中心分为三层。服务器连接到接入层,然后是汇聚层,再然后是核心层,最外面是边界路由器和安全设备。
</li>
<li>
数据中心的所有链路都需要高可用性。服务器需要绑定网卡交换机需要堆叠三层设备可以通过等价路由二层设备可以通过TRILL协议。
</li>
<li>
随着云和大数据的发展,东西流量相对于南北流量越来越重要,因而演化为叶脊网络结构。
</li>
最后,给你留两个思考题:
<li>
对于数据中心来讲,高可用是非常重要的,每个设备都要考虑高可用,那跨机房的高可用,你知道应该怎么做吗?
</li>
<li>
前面说的浏览新闻、购物、下载、看视频等行为都是普通用户通过公网访问数据中心里面的资源。那IT管理员应该通过什么样的方式访问数据中心呢
</li>
我们的专栏更新到第21讲不知你掌握得如何每节课后我留的思考题你都有没有认真思考并在留言区写下答案呢我会从**已发布的文章中选出一批认真留言的同学**,赠送学习奖励礼券和我整理的独家网络协议知识图谱。
欢迎你留言和我讨论。趣谈网络协议,我们下期见!

View File

@@ -0,0 +1,262 @@
<audio id="audio" title="第22讲 | VPN朝中有人好做官" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/0b/c8/0b3436bfb8557d895cf50828f73fb5c8.mp3"></audio>
前面我们讲到了数据中心,里面很复杂,但是有的公司有多个数据中心,需要将多个数据中心连接起来,或者需要办公室和数据中心连接起来。这该怎么办呢?
<li>
第一种方式是走公网,但是公网太不安全,你的隐私可能会被别人偷窥。
</li>
<li>
第二种方式是租用专线的方式把它们连起来,这是土豪的做法,需要花很多钱。
</li>
<li>
第三种方式是用VPN来连接这种方法比较折中安全又不贵。
</li>
<img src="https://static001.geekbang.org/resource/image/9f/68/9f797934cb5cf40543b716d97e214868.jpg" alt="">
**VPN**,全名**Virtual Private Network****虚拟专用网**,就是利用开放的公众网络,建立专用数据传输通道,将远程的分支机构、移动办公人员等连接起来。
## VPN是如何工作的
VPN通过隧道技术在公众网络上仿真一条点到点的专线是通过利用一种协议来传输另外一种协议的技术这里面涉及三种协议**乘客协议**、**隧道协议**和**承载协议**。
我们以IPsec协议为例来说明。
<img src="https://static001.geekbang.org/resource/image/52/7f/52c72a2a29c6b8526a243125e101f77f.jpeg" alt="">
你知道如何通过自驾进行海南游吗?这其中,你的车怎么通过琼州海峡呢?这里用到轮渡,其实这就用到**隧道协议**。
在广州这边开车是有“协议”的,例如靠右行驶、红灯停、绿灯行,这个就相当于“被封装”的**乘客协议**。当然在海南那面,开车也是同样的协议。这就相当于需要连接在一起的一个公司的两个分部。
但是在海上坐船航行,也有它的协议,例如要看灯塔、要按航道航行等。这就是外层的**承载协议**。
那我的车如何从广州到海南呢?这就需要你遵循开车的协议,将车开上轮渡,所有通过轮渡的车都关在船舱里面,按照既定的规则排列好,这就是**隧道协议**。
在大海上,你的车是关在船舱里面的,就像在隧道里面一样,这个时候内部的乘客协议,也即驾驶协议没啥用处,只需要船遵从外层的承载协议,到达海南就可以了。
到达之后,外部承载协议的任务就结束了,打开船舱,将车开出来,就相当于取下承载协议和隧道协议的头。接下来,在海南该怎么开车,就怎么开车,还是内部的乘客协议起作用。
在最前面的时候说了直接使用公网太不安全所以接下来我们来看一种十分安全的VPN**IPsec VPN**。这是基于IP协议的**安全隧道协议**,为了保证在公网上面信息的安全,因而采取了一定的机制保证安全性。
<li>
<p>机制一:**私密性**,防止信息泄露给未经授权的个人,通过加密把数据从明文变成无法读懂的密文,从而确保数据的私密性。<br>
前面讲HTTPS的时候说过加密可以分为对称加密和非对称加密。对称加密速度快一些。而VPN一旦建立需要传输大量数据因而我们采取对称加密。但是同样对称加密还是存在加密密钥如何传输的问题这里需要用到因特网密钥交换IKEInternet Key Exchange协议。</p>
</li>
<li>
机制二:**完整性**数据没有被非法篡改通过对数据进行hash运算产生类似于指纹的数据摘要以保证数据的完整性。
</li>
<li>
机制三:**真实性**,数据确实是由特定的对端发出,通过身份认证可以保证数据的真实性。
</li>
那如何保证对方就是真正的那个人呢?
<li>
第一种方法就是**预共享密钥**,也就是双方事先商量好一个暗号,比如“天王盖地虎,宝塔镇河妖”,对上了,就说明是对的。
</li>
<li>
另外一种方法就是**用数字签名来验证**。咋签名呢?当然是使用私钥进行签名,私钥只有我自己有,所以如果对方能用我的数字证书里面的公钥解开,就说明我是我。
</li>
基于以上三个特性,组成了**IPsec VPN的协议簇**。这个协议簇内容比较丰富。
<img src="https://static001.geekbang.org/resource/image/e4/c2/e43f13e5c68c9a5455b3793fb530a4c2.jpeg" alt="">
在这个协议簇里面,有两种协议,这两种协议的区别在于封装网络包的格式不一样。
<li>
一种协议称为**AH****Authentication Header**),只能进行数据摘要 ,不能实现数据加密。
</li>
<li>
还有一种**ESP****Encapsulating Security Payload**),能够进行数据加密和数据摘要。
</li>
在这个协议簇里面,还有两类算法,分别是**加密算法**和**摘要算法**。
这个协议簇还包含两大组件一个用于VPN的双方要进行对称密钥的交换的**IKE组件**另一个是VPN的双方要对连接进行维护的**SASecurity Association组件**。
## IPsec VPN的建立过程
下面来看IPsec VPN的建立过程这个过程分两个阶段。
**第一个阶段建立IKE自己的SA**。这个SA用来维护一个通过身份认证和安全保护的通道为第二个阶段提供服务。在这个阶段通过DHDiffie-Hellman算法计算出一个对称密钥K。
DH算法是一个比较巧妙的算法。客户端和服务端约定两个公开的质数p和q然后客户端随机产生一个数a作为自己的私钥服务端随机产生一个b作为自己的私钥客户端可以根据p、q和a计算出公钥A服务端根据p、q和b计算出公钥B然后双方交换公钥A和B。
到此客户端和服务端可以根据已有的信息各自独立算出相同的结果K就是**对称密钥**。但是这个过程,对称密钥从来没有在通道上传输过,只传输了生成密钥的材料,通过这些材料,截获的人是无法算出的。
<img src="https://static001.geekbang.org/resource/image/24/ea/24c89b7703ffcb7ce966f9d259b06eea.jpeg" alt="">
有了这个对称密钥K接下来是**第二个阶段建立IPsec SA**。在这个SA里面双方会生成一个随机的对称密钥M由K加密传给对方然后使用M进行双方接下来通信的数据。对称密钥M是有过期时间的会过一段时间重新生成一次从而防止被破解。
IPsec SA里面有以下内容
<li>
SPISecurity Parameter Index用于标识不同的连接
</li>
<li>
双方商量好的加密算法、哈希算法和封装模式;
</li>
<li>
生存周期超过这个周期就需要重新生成一个IPsec SA重新生成对称密钥。
</li>
<img src="https://static001.geekbang.org/resource/image/4d/75/4dd02eaa9a0242252371248a1b455275.jpeg" alt="">
当IPsec建立好接下来就可以开始打包封装传输了。
<img src="https://static001.geekbang.org/resource/image/15/65/158af554e14dd93237b136a99d07d165.jpg" alt="">
左面是原始的IP包在IP头里面会指定上一层的协议为TCP。ESP要对IP包进行封装因而IP头里面的上一层协议为ESP。在ESP的正文里面ESP的头部有双方商讨好的SPI以及这次传输的序列号。
接下来全部是加密的内容。可以通过对称密钥进行解密解密后在正文的最后指明了里面的协议是什么。如果是IP则需要先解析IP头然后解析TCP头这是从隧道出来后解封装的过程。
有了IPsec VPN之后客户端发送的明文的IP包都会被加上ESP头和IP头在公网上传输由于加密可以保证不被窃取到了对端后去掉ESP的头进行解密。
<img src="https://static001.geekbang.org/resource/image/48/d2/487d8dde5ec7758b4c169509fba59cd2.jpeg" alt="">
这种点对点的基于IP的VPN能满足互通的要求但是速度往往比较慢这是由底层IP协议的特性决定的。IP不是面向连接的是尽力而为的协议每个IP包自由选择路径到每一个路由器都自己去找下一跳丢了就丢了是靠上一层TCP的重发来保证可靠性。
<img src="https://static001.geekbang.org/resource/image/29/8e/29f4dff1f40a252dda2ac6f9d1d4088e.jpg" alt="">
因为IP网络从设计的时候就认为是不可靠的所以即使同一个连接也可能选择不同的道路这样的好处是一条道路崩溃的时候总有其他的路可以走。当然带来的代价就是不断的路由查找效率比较差。
和IP对应的另一种技术称为ATM。这种协议和IP协议的不同在于它是面向连接的。你可以说TCP也是面向连接的啊。这两个不同ATM和IP是一个层次的和TCP不是一个层次的。
另外TCP所谓的面向连接是不停地重试来保证成功其实下层的IP还是不面向连接的丢了就丢了。ATM是传输之前先建立一个连接形成一个虚拟的通路一旦连接建立了所有的包都按照相同的路径走不会分头行事。
<img src="https://static001.geekbang.org/resource/image/af/48/afea2a2cecb8bfe6c1c40585000f1c48.jpg" alt="">
好处是不需要每次都查路由表的虚拟路径已经建立打上了标签后续的包傻傻的跟着走就是了不用像IP包一样每个包都思考下一步怎么走都按相同的路径走这样效率会高很多。
但是一旦虚拟路径上的某个路由器坏了,则这个连接就断了,什么也发不过去了,因为其他的包还会按照原来的路径走,都掉坑里了,它们不会选择其他的路径走。
ATM技术虽然没有成功但其屏弃了繁琐的路由查找改为简单快速的标签交换将具有全局意义的路由表改为只有本地意义的标签表这些都可以大大提高一台路由器的转发功力。
有没有一种方式将两者的优点结合起来呢?这就是**多协议标签交换****MPLS****Multi-Protocol Label Switching**。MPLS的格式如图所示在原始的IP头之外多了MPLS的头里面可以打标签。
<img src="https://static001.geekbang.org/resource/image/c4/96/c45a0a2f11678f15e126449e64644596.jpeg" alt="">
在二层头里面有类型字段0x0800表示IP0x8847表示MPLS Label。
在MPLS头里面首先是标签值占20位接着是3位实验位再接下来是1位栈底标志位表示当前标签是否位于栈底了。这样就允许多个标签被编码到同一个数据包中形成标签栈。最后是8位TTL存活时间字段如果标签数据包的出发TTL值为0那么该数据包在网络中的生命期被认为已经过期了。
有了标签,还需要设备认这个标签,并且能够根据这个标签转发,这种能够转发标签的路由器称为**标签交换路由器**LSRLabel Switching Router
这种路由器会有两个表格一个就是传统的FIB也即路由表另一个就是LFIB标签转发表。有了这两个表既可以进行普通的路由转发也可以进行基于标签的转发。
<img src="https://static001.geekbang.org/resource/image/66/97/66df10af27dbyycee673dc47667dbb97.jpeg" alt="">
有了标签转发表,转发的过程如图所示,就不用每次都进行普通路由的查找了。
这里我们区分MPLS区域和非MPLS区域。在MPLS区域中间使用标签进行转发非MPLS区域使用普通路由转发在边缘节点上需要有能力将对于普通路由的转发变成对于标签的转发。
例如图中要访问114.1.1.1在边界上查找普通路由发现马上要进入MPLS区域了进去了对应标签1于是在IP头外面加一个标签1在区域里面标签1要变成标签3标签3到达出口边缘将标签去掉按照路由发出。
这样一个通过标签转换而建立的路径称为LSP标签交换路径。在一条LSP上沿数据包传送的方向相邻的LSR分别叫**上游LSR****upstream LSR**)和**下游LSR****downstream LSR**)。
有了标签转发是很简单的事但是如何生成标签却是MPLS中最难修炼的部分。在MPLS秘笈中这部分被称为**LDP****Label Distribution Protocol**),是一个动态的生成标签的协议。
其实LDP与IP帮派中的路由协议十分相像通过LSR的交互互相告知去哪里应该打哪个标签称为标签分发往往是从下游开始的。
<img src="https://static001.geekbang.org/resource/image/91/67/91cd0038877da8933365494625280b67.jpeg" alt="">
如果有一个边缘节点发现自己的路由表中出现了新的目的地址,它就要给别人说,我能到达一条新的路径了。
如果此边缘节点存在上游LSR并且尚有可供分配的标签则该节点为新的路径分配标签并向上游发出标签映射消息其中包含分配的标签等信息。
收到标签映射消息的LSR记录相应的标签映射信息在其标签转发表中增加相应的条目。此LSR为它的上游LSR分配标签并继续向上游LSR发送标签映射消息。
当入口LSR收到标签映射消息时在标签转发表中增加相应的条目。这时就完成了LSP的建立。有了标签转发轻松多了但是这个和VPN什么关系呢
可以想象如果我们VPN通道里面包的转发都是通过标签的方式进行效率就会高很多。所以要想个办法把MPLS应用于VPN。
<img src="https://static001.geekbang.org/resource/image/eb/ae/eb01c7d748b99bc94017f667eb74caae.jpeg" alt="">
在MPLS VPN中网络中的路由器分成以下几类
<li>
PEProvider Edge运营商网络与客户网络相连的边缘网络设备
</li>
<li>
CECustomer Edge客户网络与PE相连接的边缘设备
</li>
<li>
PProvider这里特指运营商网络中除PE之外的其他运营商网络设备。
</li>
为什么要这样分呢因为我们发现在运营商网络里面也即P Router之间使用标签是没有问题的因为都在运营商的管控之下对于网段路由都可以自己控制。但是一旦客户要接入这个网络就复杂得多。
首先是客户地址重复的问题。客户所使用的大多数都是私网的地址(192.168.X.X;10.X.X.X;172.X.X.X),而且很多情况下都会与其它的客户重复。
比如机构A和机构B都使用了192.168.101.0/24网段的地址这就发生了地址空间重叠Overlapping Address Spaces
首先困惑的是BGP协议既然VPN将两个数据中心连起来应该看起来像一个数据中心一样那么如何到达另一端需要通过BGP将路由广播过去传统BGP无法正确处理地址空间重叠的VPN的路由。
假设机构A和机构B都使用了192.168.101.0/24网段的地址并各自发布了一条去往此网段的路由BGP将只会选择其中一条路由从而导致去往另一个VPN的路由丢失。
所以PE路由器之间使用特殊的MP-BGP来发布VPN路由在相互沟通的消息中在一般32位IPv4的地址之前加上一个客户标示的区分符用于客户地址的区分这种称为VPN-IPv4地址族这样PE路由器会收到如下的消息机构A的192.168.101.0/24应该往这面走机构B的192.168.101.0/24则应该去另外一个方向。
另外困惑的是**路由表**当两个客户的IP包到达PE的时候PE就困惑了因为网段是重复的。
如何区分哪些路由是属于哪些客户VPN内的如何保证VPN业务路由与普通路由不相互干扰
在PE上可以通过VRFVPN Routing&amp;Forwarding Instance建立每个客户一个路由表与其它VPN客户路由和普通路由相互区分。可以理解为专属于客户的小路由器。
远端PE通过MP-BGP协议把业务路由放到近端PE近端PE根据不同的客户选择出相关客户的业务路由放到相应的VRF路由表中。
VPN报文转发采用两层标签方式
<li>
第一层外层标签在骨干网内部进行交换指示从PE到对端PE的一条LSP。VPN报文利用这层标签可以沿LSP到达对端PE
</li>
<li>
第二层内层标签在从对端PE到达CE时使用在PE上通过查找VRF表项指示报文应被送到哪个VPN用户或者更具体一些到达哪一个CE。这样对端PE根据内层标签可以找到转发报文的接口。
</li>
<img src="https://static001.geekbang.org/resource/image/43/1f/43e9ee00e3db2b0cd8315058d38d701f.jpeg" alt="">
我们来举一个例子看MPLS VPN的包发送过程。
<li>
机构A和机构B都发出一个目的地址为192.168.101.0/24的IP报文分别由各自的CE将报文发送至PE。
</li>
<li>
PE会根据报文到达的接口及目的地址查找VPN实例表项VRF匹配后将报文转发出去同时打上内层和外层两个标签。假设通过MP-BGP配置的路由两个报文在骨干网走相同的路径。
</li>
<li>
MPLS网络利用报文的外层标签将报文传送到出口PE报文在到达出口PE 2前一跳时已经被剥离外层标签仅含内层标签。
</li>
<li>
出口PE根据内层标签和目的地址查找VPN实例表项VRF确定报文的出接口将报文转发至各自的CE。
</li>
<li>
CE根据正常的IP转发过程将报文传送到目的地。
</li>
## 小结
好了,这一节就到这里了,我们来总结一下:
<li>
VPN可以将一个机构的多个数据中心通过隧道的方式连接起来让机构感觉在一个数据中心里面就像自驾游通过琼州海峡一样
</li>
<li>
完全基于软件的IPsec VPN可以保证私密性、完整性、真实性、简单便宜但是性能稍微差一些
</li>
<li>
MPLS-VPN综合和IP转发模式和ATM的标签转发模式的优势性能较好但是需要从运营商购买。
</li>
接下来,给你留两个思考题:
<li>
当前业务的高可用性和弹性伸缩很重要,所以很多机构都会在自建私有云之外,采购公有云,你知道私有云和公有云应该如何打通吗?
</li>
<li>
前面所有的上网行为,都是基于电脑的,但是移动互联网越来越成为核心,你知道手机上网都需要哪些协议吗?
</li>
我们的专栏更新到第22讲不知你掌握得如何每节课后我留的思考题你都有没有认真思考并在留言区写下答案呢我会从**已发布的文章中选出一批认真留言的同学**,赠送学习奖励礼券和我整理的独家网络协议知识图谱。
欢迎你留言和我讨论。趣谈网络协议,我们下期见!

View File

@@ -0,0 +1,217 @@
<audio id="audio" title="第23讲 | 移动网络:去巴塞罗那,手机也上不了脸书" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/1b/b7/1bf7c2014dcac41bd61657729dea4bb7.mp3"></audio>
前面讲的都是电脑上网的场景,那使用手机上网有什么不同呢?
## 移动网络的发展历程
你一定知道手机上网有2G、3G、4G的说法究竟这都是什么意思呢有一个通俗的说法就是用2G看txt用3G看jpg用4G看avi。
### 2G网络
手机本来是用来打电话的不是用来上网的所以原来在2G时代上网使用的不是IP网络而是电话网络走模拟信号专业名称为公共交换电话网PSTNPublic Switched Telephone Network
那手机不连网线,也不连电话线,它是怎么上网的呢?
手机是通过收发无线信号来通信的专业名称是Mobile Station简称MS需要嵌入SIM。手机是客户端而无线信号的服务端就是基站子系统BSSBase Station SubsystemBSS。至于什么是基站你可以回想一下你在爬山的时候是不是看到过信号塔我们平时城市里面的基站比较隐蔽不容易看到所以只有在山里才会注意到。正是这个信号塔通过无线信号让你的手机可以进行通信。
但是你要知道一点,**无论无线通信如何无线,最终还是要连接到有线的网络里**。前面讲[数据中心](https://time.geekbang.org/column/article/10098)的时候我也讲过,电商的应用是放在数据中心的,数据中心的电脑都是插着网线的。
因而基站子系统分两部分一部分对外提供无线通信叫作基站收发信台BTSBase Transceiver Station另一部分对内连接有线网络叫作基站控制器BSCBase Station Controller。基站收发信台通过无线收到数据后转发给基站控制器。
这部分属于无线的部分统称为无线接入网RANRadio Access Network
基站控制器通过有线网络连接到提供手机业务的运营商的数据中心这部分称为核心网CNCore Network。核心网还没有真的进入互联网这部分还是主要提供手机业务是手机业务的有线部分。
首先接待基站来的数据的是移动业务交换中心MSCMobile Service Switching Center它是进入核心网的入口但是它不会让你直接连接到互联网上。
因为在让你的手机真正进入互联网之前提供手机业务的运营商需要认证是不是合法的手机接入。你别自己造了一张手机卡就连接上来。鉴权中心AUCAuthentication Center和设备识别寄存器EIREquipment Identity Register主要是负责安全性的。
另外需要看你是本地的号还是外地的号这个牵扯到计费的问题异地收费还是很贵的。访问位置寄存器VLRVisit Location Register是看你目前在的地方归属位置寄存器HLRHome Location Register是看你的号码归属地。
当你的手机卡既合法又有钱的时候才允许你上网这个时候需要一个网关连接核心网和真正的互联网。网关移动交换中心GMSC Gateway Mobile Switching Center就是干这个的然后是真正的互连网。在2G时代还是电话网络PSTN。
数据中心里面的这些模块统称为网络子系统NSSNetwork and Switching Subsystem
<img src="https://static001.geekbang.org/resource/image/2e/72/2e29d99cd977eaa41231a2abd1017c72.jpg" alt="">
因而2G时代的上网如图所示我们总结一下有这几个核心点
<li>
**手机通过无线信号连接基站;**
</li>
<li>
**基站一面朝前接无线,一面朝后接核心网;**
</li>
<li>
**核心网一面朝前接到基站请求,一是判断你是否合法,二是判断你是不是本地号,还有没有钱,一面通过网关连接电话网络。**
</li>
### 2.5G网络
后来从2G到了2.5G也即在原来电路交换的基础上加入了分组交换业务支持Packet的转发从而支持IP网络。
在上述网络的基础上基站一面朝前接无线一面朝后接核心网。在朝后的组件中多了一个分组控制单元PCUPacket Control Unit用以提供分组交换通道。
在核心网里面有个朝前的接待员SGSNService GPRS Supported Node和朝后连接IP网络的网关型GPRS支持节点GGSNGateway GPRS Supported Node
<img src="https://static001.geekbang.org/resource/image/0d/d8/0d2f378ace0fbfa2e4ece8e1e7893cd8.jpg" alt="">
### 3G网络
到了3G时代主要是无线通信技术有了改进大大增加了无线的带宽。
以W-CDMA为例理论最高2M的下行速度因而基站改变了一面朝外的是Node B一面朝内连接核心网的是无线网络控制器RNCRadio Network Controller。核心网以及连接的IP网络没有什么变化。
<img src="https://static001.geekbang.org/resource/image/60/57/60e2b3701de683f1424ec6a77816c957.jpg" alt="">
### 4G网络
然后就到了今天的4G网络基站为eNodeB包含了原来Node B和RNC的功能下行速度向百兆级别迈进。另外核心网实现了控制面和数据面的分离这个怎么理解呢
在前面的核心网里面有接待员MSC或者SGSN你会发现检查是否合法是它负责转发数据也是它负责也即控制面和数据面是合二为一的这样灵活性比较差因为控制面主要是指令多是小包往往需要高的及时性数据面主要是流量多是大包往往需要吞吐量。
于是有了下面这个架构。
<img src="https://static001.geekbang.org/resource/image/a6/61/a645919dfb484542350af84d76076d61.jpg" alt="">
HSS用于存储用户签约信息的数据库其实就是你这个号码归属地是哪里的以及一些认证信息。
MME是核心控制网元是控制面的核心当手机通过eNodeB连上的时候MME会根据HSS的信息判断你是否合法。如果允许连上来MME不负责具体的数据的流量而是MME会选择数据面的SGW和PGW然后告诉eNodeB我允许你连上来了你连接它们吧。
于是手机直接通过eNodeB连接SGW连上核心网SGW相当于数据面的接待员并通过PGW连到IP网络。PGW就是出口网关。在出口网关有一个组件PCRF称为策略和计费控制单元用来控制上网策略和流量的计费。
## 4G网络协议解析
我们来仔细看一下4G网络的协议真的非常复杂。我们将几个关键组件放大来看。
<img src="https://static001.geekbang.org/resource/image/e4/50/e40f7cb5754e01ed82ae120d8d571f50.jpg" alt="">
### 控制面协议
其中虚线部分是控制面的协议。当一个手机想上网的时候先要连接eNodeB并通过S1-MME接口请求MME对这个手机进行认证和鉴权。S1-MME协议栈如下图所示。
<img src="https://static001.geekbang.org/resource/image/3b/92/3b40f3c06f95de2e261609b82163f392.jpg" alt="">
UE就是你的手机eNodeB还是两面派朝前对接无线网络朝后对接核心网络在控制面对接的是MME。
eNodeB和MME之间的连接就是很正常的IP网络但是这里面在IP层之上却既不是TCP也不是UDP而是SCTP。这也是传输层的协议也是面向连接的但是更加适合移动网络。 它继承了TCP较为完善的拥塞控制并改进TCP的一些不足之处。
SCTP的第一个特点是**多宿主**。一台机器可以有多个网卡而对于TCP连接来讲虽然服务端可以监听0.0.0.0,也就是从哪个网卡来的连接都能接受,但是一旦建立了连接,就建立了四元组,也就选定了某个网卡。
SCTP引入了联合association的概念将多个接口、多条路径放到一个联合中来。当检测到一条路径失效时协议就会通过另外一条路径来发送通信数据。应用程序甚至都不必知道发生了故障、恢复从而提供更高的可用性和可靠性。
SCTP的第二个特点是**将一个联合分成多个流**。一个联合中的所有流都是独立的但均与该联合相关。每个流都给定了一个流编号它被编码到SCTP报文中通过联合在网络上传送。在TCP的机制中由于强制顺序导致前一个不到达后一个就得等待SCTP的多个流不会相互阻塞。
SCTP的第三个特点是**四次握手防止SYN攻击**。在TCP中是三次握手当服务端收到客户的SYN之后返回一个SYN-ACK之前就建立数据结构并记录下状态等待客户端发送ACK的ACK。当恶意客户端使用虚假的源地址来伪造大量SYN报文时服务端需要分配大量的资源最终耗尽资源无法处理新的请求。
SCTP可以通过四次握手引入Cookie的概念来有效地防止这种攻击的产生。在SCTP中客户机使用一个INIT报文发起一个连接。服务器使用一个INIT-ACK报文进行响应其中就包括了Cookie。然后客户端就使用一个COOKIE-ECHO报文进行响应其中包含了服务器所发送的Cookie。这个时候服务器为这个连接分配资源并通过向客户机发送一个COOKIE-ACK报文对其进行响应。
SCTP的第四个特点是**将消息分帧**。TCP是面向流的也即发送的数据没头没尾没有明显的界限。这对于发送数据没有问题但是对于发送一个个消息类型的数据就不太方便。有可能客户端写入10个字节然后再写入20个字节。服务端不是读出10个字节的一个消息再读出20个字节的一个消息而有可能读入25个字节再读入5个字节需要业务层去组合成消息。
SCTP借鉴了UDP的机制在数据传输中提供了消息分帧功能。当一端对一个套接字执行写操作时可确保对等端读出的数据大小与此相同。
SCTP的第五个特点是**断开连接是三次挥手**。在TCP里面断开连接是四次挥手允许另一端处于半关闭的状态。SCTP选择放弃这种状态当一端关闭自己的套接字时对等的两端全部需要关闭将来任何一端都不允许再进行数据的移动了。
当MME通过认证鉴权同意这个手机上网的时候需要建立一个数据面的数据通路。建立通路的过程还是控制面的事情因而使用的是控制面的协议GTP-C。
建设的数据通路分两段路其实是两个隧道。一段是从eNodeB到SGW这个数据通路由MME通过S1-MME协议告诉eNodeB它是隧道的一端通过S11告诉SGW它是隧道的另一端。第二端是从SGW到PGWSGW通过S11协议知道自己是其中一端并主动通过S5协议告诉PGW它是隧道的另一端。
GTP-C协议是基于UDP的这是[UDP的“城会玩”](https://time.geekbang.org/column/article/8924)中的一个例子。如果看GTP头我们可以看到这里面有隧道的ID还有序列号。
<img src="https://static001.geekbang.org/resource/image/77/cd/77eb34d092948fbf8773ef9041305fcd.jpg" alt="">
通过序列号不用TCPGTP-C自己就可以实现可靠性为每个输出信令消息分配一个依次递增的序列号以确保信令消息的按序传递并便于检测重复包。对于每个输出信令消息启动定时器在定时器超时前未接收到响应消息则进行重发。
### 数据面协议
当两个隧道都打通接在一起的时候PGW会给手机分配一个IP地址这个IP地址是隧道内部的IP地址可以类比为IPsec协议里面的IP地址。这个IP地址是归手机运营商管理的。然后手机可以使用这个IP地址连接eNodeB从eNodeB经过S1-U协议通过第一段隧道到达SGW再从SGW经过S8协议通过第二段隧道到达PGW然后通过PGW连接到互联网。
数据面的协议都是通过GTP-U如图所示。
<img src="https://static001.geekbang.org/resource/image/03/29/0397a72d0c5d76d4e3591cbe61eef729.jpg" alt="">
手机每发出的一个包都由GTP-U隧道协议封装起来格式如下。
<img src="https://static001.geekbang.org/resource/image/15/11/15c48f78ed74d62cdeda7cf2d3c66711.jpg" alt="">
和IPsec协议很类似分为乘客协议、隧道协议、承载协议。其中乘客协议是手机发出来的包IP是手机的IP隧道协议里面有隧道ID不同的手机上线会建立不同的隧道因而需要隧道ID来标识。承载协议的IP地址是SGW和PGW的IP地址。
### 手机上网流程
接下来,我们来看一个手机开机之后上网的流程,这个过程称为**Attach**。可以看出来移动网络还是很复杂的。因为这个过程要建立很多的隧道分配很多的隧道ID所以我画了一个图来详细说明这个过程。
<img src="https://static001.geekbang.org/resource/image/4d/d2/4d3e9282b00410a28e77f91f9375f4d2.jpg" alt="">
<li>
手机开机以后在附近寻找基站eNodeB找到后给eNodeB发送Attach Request说“我来啦我要上网”。
</li>
<li>
eNodeB将请求发给MME说“有个手机要上网”。
</li>
<li>
MME去请求手机一是认证二是鉴权还会请求HSS看看有没有钱看看是在哪里上网。
</li>
<li>
当MME通过了手机的认证之后开始分配隧道先告诉SGW说要创建一个会话Create Session。在这里面会给SGW分配一个隧道ID t1并且请求SGW给自己也分配一个隧道ID。
</li>
<li>
SGW转头向PGW请求建立一个会话为PGW的控制面分配一个隧道ID t2也给PGW的数据面分配一个隧道ID t3并且请求PGW给自己的控制面和数据面分配隧道ID。
</li>
<li>
PGW回复SGW说“创建会话成功”使用自己的控制面隧道ID t2回复里面携带着给SGW控制面分配的隧道ID t4和控制面的隧道ID t5至此SGW和PGW直接的隧道建设完成。双方请求对方都要带着对方给自己分配的隧道ID从而标志是这个手机的请求。
</li>
<li>
接下来SGW回复MME说“创建会话成功”使用自己的隧道ID t1访问MME回复里面有给MME分配隧道ID t6也有SGW给eNodeB分配的隧道ID t7。
</li>
<li>
当MME发现后面的隧道都建设成功之后就告诉eNodeB“后面的隧道已经建设完毕SGW给你分配的隧道ID是t7你可以开始连上来了但是你也要给SGW分配一个隧道ID”。
</li>
<li>
eNodeB告诉MME自己给SGW分配一个隧道ID为t8。
</li>
<li>
MME将eNodeB给SGW分配的隧道ID t8告知SGW从而前面的隧道也建设完毕。
</li>
这样,手机就可以通过建立的隧道成功上网了。
## 异地上网问题
接下来我们考虑异地上网的事情。
为什么要分SGW和PGW呢一个GW不可以吗SGW是你本地的运营商的设备而PGW是你所属的运营商的设备。
如果你在巴塞罗那一下飞机手机开机周围搜寻到的肯定是巴塞罗那的eNodeB。通过MME去查询国内运营商的HSS看你是否合法是否还有钱。如果允许上网你的手机和巴塞罗那的SGW会建立一个隧道然后巴塞罗那的SGW和国内运营商的PGW建立一个隧道然后通过国内运营商的PGW上网。
<img src="https://static001.geekbang.org/resource/image/06/38/0628bd6923ca91dc63ba36ca7ab74e38.jpg" alt="">
因此判断你是否能上网的是国内运营商的HSS控制你上网策略的是国内运营商的PCRF给手机分配的IP地址也是国内运营商的PGW负责的给手机分配的IP地址也是国内运营商里统计的。运营商由于是在PGW里面统计的这样你的上网流量全部通过国内运营商即可只不过巴塞罗那运营商也要和国内运营商进行流量结算。
由于你的上网策略是由国内运营商在PCRF中控制的因而你还是上不了脸书。
## 小结
好了,这一节就到这里了,我们来总结一下:
<li>
移动网络的发展历程从2G到3G再到4G逐渐从打电话的功能为主向上网的功能为主转变
</li>
<li>
请记住4G网络的结构有eNodeB、MME、SGW、PGW等分控制面协议和数据面协议你可以对照着结构试着说出手机上网的流程
</li>
<li>
即便你在国外的运营商下上网,也是要通过国内运营商控制的,因而也上不了脸书。
</li>
最后,给你留两个思考题:
<li>
咱们上网都有套餐,有交钱多的,有交钱少的,你知道移动网络是如何控制不同优先级的用户的上网流量的吗?
</li>
<li>
前面讲过的所有的网络都是基于物理机的,随着云计算兴起,无论是电商,还是移动网络都要部署在云中了,你知道云中网络的设计有哪些要点吗?
</li>
我们的专栏更新到第23讲不知你掌握得如何每节课后我留的思考题你都有没有认真思考并在留言区写下答案呢我会从**已发布的文章中选出一批认真留言的同学**,赠送学习奖励礼券和我整理的独家网络协议知识图谱。
欢迎你留言和我讨论。趣谈网络协议,我们下期见!