mirror of
https://github.com/cheetahlou/CategoryResourceRepost.git
synced 2025-11-19 07:33:47 +08:00
mod
This commit is contained in:
145
极客时间专栏/趣谈网络协议/第二模块 底层网络知识详解:陌生的数据中心/第18讲 | DNS协议:网络世界的地址簿.md
Normal file
145
极客时间专栏/趣谈网络协议/第二模块 底层网络知识详解:陌生的数据中心/第18讲 | DNS协议:网络世界的地址簿.md
Normal 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>
|
||||
|
||||
我们的专栏更新过半了,不知你掌握得如何?每节课后我留的思考题,你都有没有认真思考,并在留言区写下答案呢?我会从**已发布的文章中选出一批认真留言的同学**,赠送**学习奖励礼券**和我整理的**独家网络协议知识图谱**。
|
||||
|
||||
欢迎你留言和我讨论。趣谈网络协议,我们下期见!
|
||||
@@ -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
|
||||
{"dns":[{"host":"c.m.163.com","ips":["223.252.199.12"],"ttl":300,"http2":0}],"client":{"ip":"106.2.81.50","line":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>
|
||||
|
||||
我们的专栏更新过半了,不知你掌握得如何?每节课后我留的思考题,你都有没有认真思考,并在留言区写下答案呢?我会从已发布的文章中选出一批认真留言的同学,赠送学习奖励礼券和我整理的独家网络协议知识图谱。
|
||||
|
||||
欢迎你留言和我讨论。趣谈网络协议,我们下期见!
|
||||
123
极客时间专栏/趣谈网络协议/第二模块 底层网络知识详解:陌生的数据中心/第20讲 | CDN:你去小卖部取过快递么?.md
Normal file
123
极客时间专栏/趣谈网络协议/第二模块 底层网络知识详解:陌生的数据中心/第20讲 | CDN:你去小卖部取过快递么?.md
Normal 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讲,不知你掌握得如何?每节课后我留的思考题,你都有没有认真思考,并在留言区写下答案呢?我会从**已发布的文章中选出一批认真留言的同学**,赠送学习奖励礼券和我整理的独家网络协议知识图谱。
|
||||
|
||||
欢迎你留言和我讨论。趣谈网络协议,我们下期见!
|
||||
145
极客时间专栏/趣谈网络协议/第二模块 底层网络知识详解:陌生的数据中心/第21讲 | 数据中心:我是开发商,自己拿地盖别墅.md
Normal file
145
极客时间专栏/趣谈网络协议/第二模块 底层网络知识详解:陌生的数据中心/第21讲 | 数据中心:我是开发商,自己拿地盖别墅.md
Normal 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讲,不知你掌握得如何?每节课后我留的思考题,你都有没有认真思考,并在留言区写下答案呢?我会从**已发布的文章中选出一批认真留言的同学**,赠送学习奖励礼券和我整理的独家网络协议知识图谱。
|
||||
|
||||
欢迎你留言和我讨论。趣谈网络协议,我们下期见!
|
||||
262
极客时间专栏/趣谈网络协议/第二模块 底层网络知识详解:陌生的数据中心/第22讲 | VPN:朝中有人好做官.md
Normal file
262
极客时间专栏/趣谈网络协议/第二模块 底层网络知识详解:陌生的数据中心/第22讲 | VPN:朝中有人好做官.md
Normal 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一旦建立,需要传输大量数据,因而我们采取对称加密。但是同样,对称加密还是存在加密密钥如何传输的问题,这里需要用到因特网密钥交换(IKE,Internet 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的双方要对连接进行维护的**SA(Security Association)组件**。
|
||||
|
||||
## IPsec VPN的建立过程
|
||||
|
||||
下面来看IPsec VPN的建立过程,这个过程分两个阶段。
|
||||
|
||||
**第一个阶段,建立IKE自己的SA**。这个SA用来维护一个通过身份认证和安全保护的通道,为第二个阶段提供服务。在这个阶段,通过DH(Diffie-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>
|
||||
SPI(Security 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表示IP,0x8847表示MPLS Label。
|
||||
|
||||
在MPLS头里面,首先是标签值占20位,接着是3位实验位,再接下来是1位栈底标志位,表示当前标签是否位于栈底了。这样就允许多个标签被编码到同一个数据包中,形成标签栈。最后是8位TTL存活时间字段,如果标签数据包的出发TTL值为0,那么该数据包在网络中的生命期被认为已经过期了。
|
||||
|
||||
有了标签,还需要设备认这个标签,并且能够根据这个标签转发,这种能够转发标签的路由器称为**标签交换路由器**(LSR,Label 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>
|
||||
PE(Provider Edge):运营商网络与客户网络相连的边缘网络设备;
|
||||
</li>
|
||||
<li>
|
||||
CE(Customer Edge):客户网络与PE相连接的边缘设备;
|
||||
</li>
|
||||
<li>
|
||||
P(Provider):这里特指运营商网络中除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上,可以通过VRF(VPN Routing&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讲,不知你掌握得如何?每节课后我留的思考题,你都有没有认真思考,并在留言区写下答案呢?我会从**已发布的文章中选出一批认真留言的同学**,赠送学习奖励礼券和我整理的独家网络协议知识图谱。
|
||||
|
||||
欢迎你留言和我讨论。趣谈网络协议,我们下期见!
|
||||
@@ -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网络,而是电话网络,走模拟信号,专业名称为公共交换电话网(PSTN,Public Switched Telephone Network)。
|
||||
|
||||
那手机不连网线,也不连电话线,它是怎么上网的呢?
|
||||
|
||||
手机是通过收发无线信号来通信的,专业名称是Mobile Station,简称MS,需要嵌入SIM。手机是客户端,而无线信号的服务端,就是基站子系统(BSS,Base Station SubsystemBSS)。至于什么是基站,你可以回想一下,你在爬山的时候,是不是看到过信号塔?我们平时城市里面的基站比较隐蔽,不容易看到,所以只有在山里才会注意到。正是这个信号塔,通过无线信号,让你的手机可以进行通信。
|
||||
|
||||
但是你要知道一点,**无论无线通信如何无线,最终还是要连接到有线的网络里**。前面讲[数据中心](https://time.geekbang.org/column/article/10098)的时候我也讲过,电商的应用是放在数据中心的,数据中心的电脑都是插着网线的。
|
||||
|
||||
因而,基站子系统分两部分,一部分对外提供无线通信,叫作基站收发信台(BTS,Base Transceiver Station),另一部分对内连接有线网络,叫作基站控制器(BSC,Base Station Controller)。基站收发信台通过无线收到数据后,转发给基站控制器。
|
||||
|
||||
这部分属于无线的部分,统称为无线接入网(RAN,Radio Access Network)。
|
||||
|
||||
基站控制器通过有线网络,连接到提供手机业务的运营商的数据中心,这部分称为核心网(CN,Core Network)。核心网还没有真的进入互联网,这部分还是主要提供手机业务,是手机业务的有线部分。
|
||||
|
||||
首先接待基站来的数据的是移动业务交换中心(MSC,Mobile Service Switching Center),它是进入核心网的入口,但是它不会让你直接连接到互联网上。
|
||||
|
||||
因为在让你的手机真正进入互联网之前,提供手机业务的运营商,需要认证是不是合法的手机接入。你别自己造了一张手机卡,就连接上来。鉴权中心(AUC,Authentication Center)和设备识别寄存器(EIR,Equipment Identity Register)主要是负责安全性的。
|
||||
|
||||
另外,需要看你是本地的号,还是外地的号,这个牵扯到计费的问题,异地收费还是很贵的。访问位置寄存器(VLR,Visit Location Register)是看你目前在的地方,归属位置寄存器(HLR,Home Location Register)是看你的号码归属地。
|
||||
|
||||
当你的手机卡既合法又有钱的时候,才允许你上网,这个时候需要一个网关,连接核心网和真正的互联网。网关移动交换中心(GMSC ,Gateway Mobile Switching Center)就是干这个的,然后是真正的互连网。在2G时代,还是电话网络PSTN。
|
||||
|
||||
数据中心里面的这些模块统称为网络子系统(NSS,Network 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网络。
|
||||
|
||||
在上述网络的基础上,基站一面朝前接无线,一面朝后接核心网。在朝后的组件中,多了一个分组控制单元(PCU,Packet Control Unit),用以提供分组交换通道。
|
||||
|
||||
在核心网里面,有个朝前的接待员(SGSN,Service GPRS Supported Node)和朝后连接IP网络的网关型GPRS支持节点(GGSN,Gateway GPRS Supported Node)。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/0d/d8/0d2f378ace0fbfa2e4ece8e1e7893cd8.jpg" alt="">
|
||||
|
||||
### 3G网络
|
||||
|
||||
到了3G时代,主要是无线通信技术有了改进,大大增加了无线的带宽。
|
||||
|
||||
以W-CDMA为例,理论最高2M的下行速度,因而基站改变了,一面朝外的是Node B,一面朝内连接核心网的是无线网络控制器(RNC,Radio 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到PGW,SGW通过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="">
|
||||
|
||||
通过序列号,不用TCP,GTP-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讲,不知你掌握得如何?每节课后我留的思考题,你都有没有认真思考,并在留言区写下答案呢?我会从**已发布的文章中选出一批认真留言的同学**,赠送学习奖励礼券和我整理的独家网络协议知识图谱。
|
||||
|
||||
欢迎你留言和我讨论。趣谈网络协议,我们下期见!
|
||||
Reference in New Issue
Block a user