预计阅读本页时间:-
第 5 章 服务器端的局域网中有什么玄机
热身问答
在开始探索之旅之前,我们准备了一些和本章内容有关的小题目,请大家先试试看。
广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元
这些题目是否答得出来并不影响接下来的探索之旅,因此请大家放轻松。
问题
下列说法是正确的(√)还是错误的(×)?
1. 当使用浏览器访问 Web 服务器时,浏览器的通信对象不仅限于 Web 服务器。
2. 没有防火墙就不能连接到互联网。
3. 也有防火墙无法抵御的攻击。
答案
1. √。浏览器有时候是和 Web 服务器通信,有时候是和缓存服务器以及负载均衡器等进行通信。
2. ×。防火墙并不是必需的,但是没有防火墙会增加风险。
3. √。防火墙不会检查通信数据的具体内容,因此无法抵御隐藏在通信数据内容中的攻击。
前情提要
上一章,我们探索了网络包在进入互联网之后,通过通信线路和运营商网络到达服务器 POP 端的过程。接下来,网络包将继续朝服务器前进,并通过服务器前面的防火墙、缓存服务器、负载均衡器等。本章我们将对这一部分进行探索。
探索之旅的看点
(1)Web 服务器的部署地点
客户端计算机一般都放在家庭、公司网络上,但服务器的部署不仅限于家庭和公司中。那么服务器到底放在哪里呢?这是我们的第一个看点。
(2)防火墙的结构和原理
一般在 Web 服务器前面都会部署防火墙,那么防火墙是通过怎样的机制保护服务器的呢?这是我们的第二个看点。
(3)通过将请求平均分配给多台服务器来平衡负载
随着访问量的增加,Web 服务器的处理能力会不够用,对于访问量很大的大型网站来说,必须要考虑到这一点。如何应对这个问题,也是我们的看点之一。有很多方案可以应对这个问题,我们先介绍其中一种方法,即通过多台 Web 服务器来分担负载。
(4)利用缓存服务器分担负载
另一种减轻 Web 服务器负担的方法是将访问过的数据保存在缓存服务器中,当再次访问时直接使用缓存的数据。除了在服务器端部署缓存服务器之外,在客户端也可以部署缓存服务器,缓存服务器有各种用法,这也是我们的看点之一。
(5)内容分发服务
内容分发服务是从缓存服务器发展而来的,它在互联网中部署很多缓存服务器,并将用户的访问引导到最近的缓存服务器上。那么如何才能找到离用户最近的缓存服务器呢?如何将用户的访问引导到这台服务器上呢?内容分发服务的结构还是非常耐人寻味的。
5.1 Web 服务器的部署地点
5.1.1 在公司里部署 Web 服务器
网络包从互联网到达服务器的过程,根据服务器部署地点的不同而不同。最简单的是图 5.1(a)中的这种情况,服务器直接部署在公司网络上,并且可以从互联网直接访问。这种情况下,网络包通过最近的 POP 中的路由器、接入网以及服务器端路由器之后,就直接到达了服务器。其中,路由器的包转发操作,以及接入网和局域网中包的传输过程都和我们之前讲过的内容没有区别 1 。
1 路由器的包转发参见第 3 章,接入网参见第 4 章,局域网参见第 3 章。
图 5.1 服务器的所在地
以前这样的服务器部署方式很常见,但现在已经不是主流方式了。这里有几个原因。第一个原因是 IP 地址不足。这样的方式需要为公司网络中的所有设备,包括服务器和客户端计算机,都分配各自的公有地址。然而现在公有地址已经不够用了,因此采用这种方式已经不现实了。
另一个原因是安全问题。这种方式中,从互联网传来的网络包会无节制地进入服务器,这意味着服务器在攻击者看来处于“裸奔”状态。当然,我们可以强化服务器本身的防御来抵挡攻击,这样可以一定程度上降低风险。但是,任何设置失误都会产生安全漏洞,而裸奔状态的服务器,其安全漏洞也都会暴露出来。人工方式总会出错,安全漏洞很难完全消除,因此让服务器裸奔并不是一个稳妥的办法。
因此,现在我们一般采用图 5.1(b)中的方式,即部署防火墙 2 。防火墙的作用类似于海关,它只允许发往指定服务器的指定应用程序的网络包通过,从而屏蔽其他不允许通过的包。这样一来,即便应用程序存在安全漏洞,也可以降低相应的风险。因为防火墙屏蔽了不允许从外部访问的应用程序,所以即便这些程序存在安全漏洞,用于攻击的网络包也进不来 3 。当然,即便如此风险也不会降到零,因为如果允许外部访问的应用程序中有安全漏洞,还是有可能遭到攻击的 4 ,但怎么说也远比完全暴露安全漏洞的风险要低得多。这就是防火墙的作用。
2 防火墙:一种抵御外部网络攻击的机制,也是最早出现的一种防御机制。现在已经出现了很多可以绕过防火墙的攻击方法,因此防火墙一般需要和反病毒、非法入侵检测、访问隔离等机制并用。我们将在 5.2 节详细介绍。
3 在设计防火墙机制的那个年代,还没有特别恶劣的攻击方式,因此只要服务器管理员正确配置应用程序,就可以防止出现漏洞。当时的设计思路就是对于允许外部访问的应用程序进行正确配置,防止出现漏洞,而对于其他应用程序则用防火墙来进行屏蔽保护。
4 因此管理员必须注意两点:1. 更新应用程序修补安全漏洞;2. 正确配置应用程序避免出现漏洞。
5.1.2 将 Web 服务器部署在数据中心
图 5.1(a)和图 5.1(b)都是将 Web 服务器部署在公司里,但 Web 服务器不仅可以部署在公司里,也可以像图 5.1(c)这样把服务器放在网络运营商等管理的数据中心里,或者直接租用运营商提供的服务器。
数据中心是与运营商核心部分 NOC 直接连接的,或者是与运营商之间的枢纽 IX 直接连接的。换句话说,数据中心通过高速线路直接连接到互联网的核心部分,因此将服务器部署在这里可以获得很高的访问速度 5 ,当服务器访问量很大时这是非常有效的。此外,数据中心一般位于具有抗震结构的大楼内,还具有自主发电设备,并实行 24 小时门禁管理,可以说比放在公司里具有更高的安全性。此外,数据中心不但提供安放服务器的场地,还提供各种附加服务,如服务器工作状态监控、防火墙的配置和运营、非法入侵监控等,从这一点来看,其安全性也更高。
5 将服务器部署在公司里时,只要提高接入网的带宽,就可以让访问速度变得更快。
如果 Web 服务器部署在数据中心里,那么网络包会从互联网核心部分直接进入数据中心,然后到达服务器。如果数据中心有防火墙,则网络包会先接受防火墙的检查,放行之后再到达服务器。无论如何,网络包通过路由器的层层转发,最终到达服务器的这个过程都是相同的。
5.2 防火墙的结构和原理
5.2.1 主流的包过滤方式
无论服务器部署在哪里,现在一般都会在前面部署一个防火墙,如果包无法通过防火墙,就无法到达服务器。因此,让我们先来探索一下包是如何通过防火墙的。
防火墙的基本思路刚才已经介绍过了,即只允许发往特定服务器中的特定应用程序的包通过,然后屏蔽其他的包。不过,特定服务器上的特定应用程序这个规则看起来不复杂,但网络中流动着很多各种各样的包,如何才能从这些包中分辨出哪些可以通过,哪些不能通过呢?为此,人们设计了多种方式 6 ,其中任何一种方式都可以实现防火墙的目的,但出于性能、价格、易用性等因素,现在最为普及的是包过滤方式。因此,我们的探险之旅就集中介绍一下包过滤方式的防火墙是怎样工作的。
6 防火墙可分为包过滤、应用层网关、电路层网关等几种方式。
5.2.2 如何设置包过滤的规则
网络包的头部包含了用于控制通信操作的控制信息,只要检查这些信息,就可以获得很多有用的内容。这些头部信息中,经常用于设置包过滤规则的字段如表 5.1 所示。不过,光看这张表还是难以理解过滤规则是如何设置的,所以我们来看一个具体的例子 7 。
7 要理解包过滤的设置需要深入理解包是如何在网络中传输的,这些内容在第 2 章有详细的讲解,请大家复习一下。
表 5.1 地址转换和包过滤中用于设置规则的字段
头部类型 | 规则判断条件 | 含义 | |
---|---|---|---|
MAC 头部 | 发送方 MAC 地址 | 路由器在对包进行转发时会改写 MAC 地址,将转发目标路由器的 MAC 地址设为接收方 MAC 地址,将自己的 MAC 地址设为发送方 MAC 地址。通过发送方 MAC 地址,可以知道上一个转发路由器的 MAC 地址 | |
IP 头部 | 发送方 IP 地址 | 发送该包的原始设备的 IP 地址。如果要以发送设备来设置规则,需要使用这个字段 | |
接收方 IP 地址 | 包的目的地 IP 地址,如果要以包的目的地来设置规则,需要使用这个字段 | ||
协议号 | TCP/IP 协议为每个协议分配了一个编号,如果要以协议类型来设置规则,需要使用这个编号。主要的协议号包括 IP∶0;ICMP∶1;TCP∶6;UDP∶17;OSPF∶89 | ||
TCP 头部或 UDP 头部 | 发送方端口号 | 发送该包的程序对应的端口号。服务器程序对应的端口号是固定的,因此根据服务器返回的包的端口号可以分辨是哪个程序发送的。不过,客户端程序的端口号大多是随机分配的,难以判断其来源,因此很少使用客户端发送的包的端口号来设置过滤规则 | |
接收方端口号 | 包的目的地程序对应的端口号。和发送方端口号一样,一般使用服务器的端口号来设置规则,很少使用客户端的端口号 | ||
TCP 控制位 | TCP 协议的控制信息,主要用来控制连接操作 | ||
ACK | 表示接收数据序号字段有效,一般用于通知发送方数据已经正确接收 | ||
PSH | 表示发送方应用程序希望不等待发送缓冲区填充完毕,立即发送这个包 | ||
RST | 强制断开连接,用于异常中断 | ||
SYN | 开始通信时连接操作中发送的第一个包中,SYN 为 1,ACK 为 0。如果能够过滤这样的包,则后面的操作都无法继续,可以屏蔽整个访问 | ||
FIN | 表示断开连接 | ||
分片 | 通过 IP 协议的分片功能拆分后的包,从第二个分片开始会设置该字段 | ||
ICMP 消息(非头部)的内容 | ICMP 消息类型 | ICMP 消息用于通知包传输过程中产生的错误,或者用来确认通信对象的工作状态。ICMP 消息主要包括以下类型,这些类型可以用来设置过滤规则 | |
0 | 针对 ping 命令发送的 ICMP echo 消息的响应。将这种类型的消息和下面的类型 8 消息屏蔽后,ping 命令就没有响应了。一般在发动攻击之前会通过 ping 命令查询网络中有哪些设备,如果屏蔽 0 和 8,就不会响应 ping 命令,攻击者也就无法获取网络中的信息了。不过,ping 命令也可以用来查询设备是否在正常工作,如果屏蔽了 0 和 8 的消息,可能别人会误以为设备没有在工作 | ||
8 | 这个类型的消息叫作 ICMP echo,当执行 ping 命令时,就会发送 ICMP echo 消息 | ||
其他 | ICMP 消息除了 0 和 8 以外还有其他一些类型,但其中有些消息被屏蔽后会导致网络故障,因此如果要屏蔽 0 和 8 以外的消息必须十分谨慎 |
假设我们的网络如图 5.2 所示,将开放给外网的服务器和公司内网分开部署,Web 服务器所在的网络可以从外网直接访问。现在我们希望允许从互联网访问 Web 服务器(图 5.2 ①),但禁止 Web 服务器访问互联网(图 5.2 ②)。以前很少禁止 Web 服务器访问互联网,但现在出现了一些寄生在服务器中感染其他服务器的恶意软件,如果阻止 Web 服务器访问互联网,就可以防止其他服务器被感染。要实现这样的要求,应该如何设置包过滤的规则呢?我们就用这个例子来看一看包过滤的具体思路。
在设置包过滤规则时,首先要观察包是如何流动的。通过接收方 IP 地址和发送方 IP 地址,我们可以判断出包的起点和终点。在图 5.2 ①的例子中,包从互联网流向 Web 服务器,从互联网发送过来的包其起点是不确定的,但终点是确定的,即 Web 服务器。因此,我们可以按此来设定规则,允许符合规则的包通过。也就是说,允许起点(发送方 IP 地址)为任意,终点(接收方 IP 地址)为 Web 服务器 IP 地址的包通过(图 5.2 中表的第 1 行)。如果可以确定发送方 IP 地址,也可以将其加入规则,但这个例子中起点是不确定的,因此可以不将发送方 IP 地址设为判断条件。
图 5.2 包过滤的典型示例
这样一来,从互联网发往 Web 服务器的包就可以通过防火墙了,但光这样还无法完成访问。因为收到包之后,Web 服务器需要通过确认应答机制 8 通知发送方数据已经正常收到,这需要 Web 服务器向互联网发送包。在 Web 服务器发往互联网的包中,我们可以将起点(发送方 IP 地址)为 Web 服务器地址的包设置为允许通过(图 5.2 中表的第 3 行)。像这样,我们可以先根据接收方和发送方地址判断包的流向,并设置是允许还是阻止。
8 详见第 2 章的内容。
5.2.3 通过端口号限定应用程序
不过,按照前面的设置,相当于允许了互联网和 Web 服务器之间所有的包通过,这个状态很危险。假如服务器上还有一个文件服务器程序在工作,那么这些文件就可能会被非法访问从而造成信息泄露。有风险的还不仅是文件服务器,现在每天都会发布若干安全漏洞,可以说随处都隐藏着风险。因此,我们最好是阻止除了必需服务(也就是本例中的 Web 服务)以外的所有应用程序的包。
当我们要限定某个应用程序时,可以在判断条件中加上 TCP 头部或者 UDP 头部中的端口号。Web 服务器的端口号为 809 ,因此我们在刚才的接收方 IP 地址和发送方 IP 地址的基础上再加上 80 端口作为条件就可以了。也就是说,当包的接收方 IP 地址为 Web 服务器地址,且接收方端口号为 80 时,允许这些包通过(图 5.2 中表的第 1 行);或者当包的发送方 IP 地址为 Web 服务器地址,且发送方端口号为 80 时,允许这些包通过(图 5.2 中的表的第 3 行)。如果要允许访问除 Web 之外的其他应用程序,则只要将该应用程序的端口号设置到防火墙中并允许通过就可以了。
9 也可以不使用 80 端口而使用其他端口,但这种情况一定是在 Web 服务器程序中特别设置过的,因此只要按照服务器的设置来调整防火墙设置就可以了。
5.2.4 通过控制位判断连接方向
现在我们已经可以指定某个具体的应用程序了,但是条件还没达到,因为还没有办法阻止 Web 服务器访问互联网。Web 使用的 TCP 协议是双向收发网络包的,因此如果单纯地阻止从 Web 服务器发往互联网的包,则从互联网访问 Web 服务器的操作也会受到影响而无法进行。光判断包的流向还不够,我们必须要根据访问的方向来进行判断。这里就需要用到 TCP 头部中的控制位。TCP 在执行连接操作时需要收发 3 个包 10 ,其中第一个包的 TCP 控制位中 SYN 为 1,而 ACK 为 0。其他的包中这些值都不同,因此只要按照这个规则就能够过滤到 TCP 连接的第一个包。
10 第 2 章有具体介绍。
如果这第一个包是从 Web 服务器发往互联网的,那么我们就阻止它(图 5.2 表中的第 2 行)。这样设置之后,当然也不会收到对方返回的第二个响应包,TCP 连接操作就失败了。也就是说,只要以 Web 服务器为起点访问互联网,其连接操作必然会失败,这样一来,我们就阻止了 Web 服务器对互联网的访问。
那么,从互联网访问 Web 服务器会不会受影响呢?从互联网访问 Web 服务器时,第一个包是接收方为 Web 服务器,符合图 5.2 表中的第 1 行,因此允许通过。第二个包的发送方是 Web 服务器,但 TCP 控制位的规则与第二行不匹配 11 ,因此符合第三行的规则,允许通过。随后的所有包要么符合第一行,要么符合第三行,因此从互联网访问 Web 服务器的所有包都会被允许通过。
11 第二个包中,SYN 为 1,ACK 也为 1,因此不符合刚刚设定的规则。
通过接收方 IP 地址、发送方 IP 地址、接收方端口号、发送方端口号、TCP 控制位这些条件,我们可以判断出通信的起点和终点、应用程序种类,以及访问的方向。当然,如表 5.1 列出的那样,还有很多其他的字段可以用作判断条件。通过对这些条件进行组合,我们就可以对包进行筛选。这里也可以添加多个规则,直到能够将允许的访问和不允许的访问完全区分开为止。这样,我们就可以通过设置规则,让允许访问的包通过防火墙,其他的包则不能通过防火墙 12 。
12 还有一种思路是只阻止有风险的访问,允许其他所有的访问,这种方法有可能漏掉未知的有风险的网络包。因此,为了避免未知的风险,一般来说都是只允许必要的包通过,其他的包全部阻止。
不过,实际上也存在无法将希望允许和阻止的访问完全区分开的情况,其中一个代表性的例子就是对 DNS 服务器的访问。DNS 查询使用的是 UDP 协议,而 UDP 与 TCP 不同,它没有连接操作,因此无法像 TCP 一样根据控制位来判断访问方向。所以,我们无法设置一个规则,只允许公司内部访问互联网上的 DNS 服务器,而阻止从互联网访问公司内部的 DNS 服务器。这一性质不仅适用于 DNS,对于所有使用 UDP 协议的应用程序都是共通的。在这种情况下,只能二者择其一——要么冒一定的风险允许该应用程序的所有包通过,要么牺牲一定的便利性阻止该应用程序的所有包通过 13 。
13 如果是使用包过滤之外的其他方式的防火墙,有时候是可以判断 UDP 应用程序的访问方向的。
5.2.5 从公司内网访问公开区域的规则
图 5.2 这样的网络结构中,我们不仅要设置互联网和公开区域之间的包过滤规则,还需要设置公司内网和互联网之间,或者公司内网与公开区域之间的包过滤规则。这时,需要注意的是不要让这些规则互相干扰。例如,为了让公司内网与公开区域之间的网络包自由流动,我们可以将接收方 IP 地址为公开区域的包设置成全部允许通过。但是,如果在这条规则里没有限定发送方 IP 地址,那么连来自互联网的包也都会被无条件允许进入公开区域了,这会导致公开区域中的服务器全部暴露在危险状态中。因此,我们必须谨慎地设置规则,防止出现这样的情况。
5.2.6 从外部无法访问公司内网
包过滤方式的防火墙不仅可以允许或者阻止网络包的通过,还具备地址转换功能 14 ,因此还需要进行相关的设置。也就是说,互联网和公司内网之间的包需要进行地址转换才能传输,因此必须要进行相关的设置 15 。具体来说,就是和包过滤一样,以起点和终点作为条件,根据需要设置是否需要进行地址转换。私有地址和公有地址之间的对应关系,以及端口号的对应关系都是自动管理的,因此只需要设置是否允许地址转换就可以了。
14 关于地址转换请参见第 3 章。
15 互联网路由器的路由表中没有私有地址的路由信息,因此凡是接收方为私有地址的包,在经过互联网中的路由器时都会被丢弃,这就是为什么必须使用地址转换的原因。相对地,防火墙内置的路由功能可以由用户自行设置,因此可以在路由表中配置私有地址相关的路由,使得公司内网到公开区域的访问可以以私有地址的形式来进行,这意味着公司内网和公开区域之间传输的包不需要地址转换。
请大家回忆一下地址转换的工作原理,当使用地址转换时,默认状态下是无法从互联网访问公司内网的,因此我们不需要再设置一条包过滤规则来阻止从互联网访问公司内网。
5.2.7 通过防火墙
像这样,我们可以在防火墙中设置各种规则,当包到达防火墙时,会根据这些规则判断是允许通过还是阻止通过。
如果判断结果为阻止,那么这个包会被丢弃并被记录下来 16 。这是因为这些被丢弃的包中通常含有非法入侵的痕迹,通过分析这些包能够搞清楚入侵者使用的手法,从而帮助我们更好地防范非法入侵。
16 如果将内置包过滤功能的路由器用作防火墙,则在丢弃包时基本上不会留下记录,这是因为路由器的内存容量小,没有足够的空间用来记录日志。
如果包被判断为允许通过,则该包会被转发出去,这个转发的过程和路由器是相同的。如果我们只关注判断是否允许包通过这一点,可能会觉得防火墙是一种特殊机制,而且市面上销售的防火墙大多是专用的硬件设备或者软件,这也加深了大家的这种印象。
实际上,在防火墙允许包通过之后,就没有什么特别的机制了,因此包过滤并不是防火墙专用的一种特殊机制,而是应该看作在路由器的包转发功能基础上附加的一种功能。只不过当判断规则比较复杂时,通过路由器的命令难以维护这些规则,而且对阻止的包进行记录对于路由器来说负担也比较大,因此才出现了专用的硬件和软件。如果规则不复杂,也不需要记录日志,那么用内置包过滤功能的普通路由器来充当防火墙也是可以的。
包过滤方式的防火墙可根据接收方 IP 地址、发送方 IP 地址、接收方端口号、发送方端口号、控制位等信息来判断是否允许某个包通过。
5.2.8 防火墙无法抵御的攻击
防火墙可以根据包的起点和终点来判断是否允许其通过,但仅凭起点和终点并不能筛选出所有有风险的包。比如,假设 Web 服务器在收到含有特定数据的包时会引起宕机。但是防火墙只关心包的起点和终点,因此即便包中含有特定数据,防火墙也无法发现,于是包就被放行了。然后,当包到达 Web 服务器时,就会引发服务器宕机。通过这个例子大家可以看出,只有检查包的内容才能识别这种风险,因此防火墙对这种情况无能为力。
要应对这种情况有两种方法。这个问题的根源在于 Web 服务器程序的 Bug,因此修复 Bug 防止宕机就是其中一种方法。这类 Bug 中,危险性较高的会作为安全漏洞公布出来,开发者会很快发布修复了 Bug 的新版本,因此持续关注安全漏洞信息并更新软件的版本是非常重要的。
另一种方法就是在防火墙之外部署用来检查包的内容并阻止有害包的设备或软件 17 。当然,即便是采用这种方法也并不是完美无缺的,因为包的内容是否有风险,是由 Web 服务器有没有 Bug 决定的,因此当服务器程序中有潜在的 Bug 并且尚未被发现时,我们也无法判断包中的风险,也无法阻止这样的包。也就是说,我们无法抵御未知的风险。从这一点来看,这种方法和直接修复 Bug 的方法是基本等效的,但如果服务器数量较多,更新软件版本需要花费一定的时间,或者容易忘记更新软件,这时对包的内容进行检查就会比较有效。
17 有时会作为防火墙的附件提供。
5.3 通过将请求平均分配给多台服务器来平衡负载
5.3.1 性能不足时需要负载均衡
当服务器的访问量上升时,增加服务器线路的带宽是有效的,但并不是网络变快了就可以解决所有的问题。高速线路会传输大量的网络包,这会导致服务器的性能跟不上 18 。尤其是通过 CGI 等应用程序动态生成数据的情况下,对服务器 CPU 的负担更重,服务器性能的问题也会表现得越明显。
18 无论服务器部署在公司里还是数据中心里,这个问题都是共通的。
要解决这个问题,大家可能首先想到的是换一台性能更好的服务器,但当很多用户同时访问时,无论服务器的性能再好,仅靠一台服务器还是难以胜任的。在这种情况下,使用多台服务器来分担负载的方法更有效。这种架构统称为分布式架构,其中对于负载的分担有几种方法,最简单的一种方法就是采用多台 Web 服务器,减少每台服务器的访问量。假设现在我们有 3 台服务器,那么每台服务器的访问量会减少到三分之一,负载也就减轻了。要采用这样的方法,必须有一个机制将客户端发送的请求分配到每台服务器上。具体的做法有很多种,最简单的一种是通过 DNS 服务器来分配。当访问服务器时,客户端需要先向 DNS 服务器查询服务器的 IP 地址,如果在 DNS 服务器中填写多个名称相同的记录,则每次查询时 DNS 服务器都会按顺序返回不同的 IP 地址。例如,对于域名 www.lab.glasscom.com,如果我们给它分配如下 3 个 IP 地址。
192.0.2.60
192.0.2.70
192.0.2.80
当第 1 次查询这个域名时,服务器会返回如下内容。
192.0.2.60 192.0.2.70 192.0.2.80
当第 2 次查询时,服务器会返回如下内容。
192.0.2.70 192.0.2.80 192.0.2.60
当第 3 次查询时,服务器会返回如下内容。
192.0.2.80 192.0.2.60 192.0.2.70
当第 4 次查询时就又回到第 1 次查询的结果(图 5.3)。这种方式称为轮询(round-robin),通过这种方式可以将访问平均分配给所有的服务器。
图 5.3 DNS 轮询
但这种方式是有缺点的。假如多台 Web 服务器中有一台出现了故障,这时我们希望在返回 IP 地址时能够跳过故障的 Web 服务器,然而普通的 DNS 服务器并不能确认 Web 服务器是否正常工作,因此即便 Web 服务器宕机了,它依然可能会返回这台服务器的 IP 地址 19 。
19 如果浏览器在访问 DNS 服务器返回的第一个 IP 地址失败时,能够继续尝试第二个 IP 地址,就可以回避这个问题了,最近的浏览器有很多都已经具备了这样的功能。
此外,轮询分配还可能会引发一些问题。在通过 CGI 等方式动态生成网页的情况下,有些操作是要跨多个页面的,如果这期间访问的服务器发生了变化,这个操作就可能无法继续。例如在购物网站中,可能会在第一个页面中输入地址和姓名,在第二个页面中输入信用卡号,这就属于刚才说的那种情况。
5.3.2 使用负载均衡器分配访问
为了避免出现前面的问题,可以使用一种叫作负载均衡器的设备。使用负载均衡器时,首先要用负载均衡器的 IP 地址代替 Web 服务器的实际地址注册到 DNS 服务器上。假设有一个域名 www.lab.glasscom.com,我们将这个域名对应的 IP 地址设置为负载均衡器的 IP 地址并注册到 DNS 服务器上。于是,客户端会认为负载均衡器就是一台 Web 服务器,并向其发送请求,然后由负载均衡器来判断将请求转发给哪台 Web 服务器(图 5.4)20 。这里的关键点不言而喻,那就是如何判断将请求转发给哪台 Web 服务器。
20 转发请求消息使用的是后面要讲到的“代理”机制,缓存服务器也使用这种机制。此外,有些负载均衡器中也内置缓存功能。负载均衡器和缓存服务器很相似,或者可以说它是由缓存服务器进一步发展而来的。
图 5.4 用于对多台 Web 服务器分配访问的负载均衡器
判断条件有很多种,根据操作是否跨多个页面,判断条件也会有所不同。如果操作没有跨多个页面,则可以根据 Web 服务器的负载状况来进行判断。负载均衡器可以定期采集 Web 服务器的 CPU、内存使用率,并根据这些数据判断服务器的负载状况,也可以向 Web 服务器发送测试包,根据响应所需的时间来判断负载状况。当然,Web 服务器的负载可能会在短时间内上下波动,因此无法非常准确地把握负载状况,反过来说,如果过于密集地去查询服务器的负载,这个查询操作本身就会增加 Web 服务器的负载。因此也有一种方案是不去查询服务器的负载,而是根据事先设置的服务器性能指数,按比例来分配请求。无论如何,这些方法都能够避免负载集中在某一台服务器上。
当操作跨多个页面时,则不考虑 Web 服务器的负载,而是必须将请求发送到同一台 Web 服务器上。要实现这一点,关键在于我们必须要判断一个操作是否跨了多个页面。HTTP 的基本工作方式是在发送请求消息之前先建立 TCP 连接,当服务器发送响应消息后断开连接,下次访问 Web 服务器的时候,再重新建立 TCP 连接 21 。因此,在 Web 服务器看来,每一次 HTTP 访问都是相互独立的,无法判断是否和之前的请求相关。
21 现在越来越多的服务器在发送响应消息之后会等待一段时间再断开连接,这个等待时间大约只有几秒钟,像购物网站这种跨多页面填写信息的场景已经超过了这个等待时间,因此还是会断开连接。
之所以会这样,是因为 Web 中使用的 HTTP 协议原本就是这样设计的。如果要判断请求之间的相关性,就必须在 Web 服务器一端保存相应的信息,这会增加服务器的负担。此外,Web 服务器最早并不是用来运行 CGI 程序的,而是主要用来提供静态文件的,而静态文件不需要判断请求之间的相关性,因此最早设计 HTTP 规格的时候,就有意省略了请求之间相关性的判断。
那么在不知道请求之间的相关性时,能不能根据一系列请求的发送方 IP 地址相同这一点来判断呢?也不行。如果使用了我们后面要讲的代理机制 22 ,所有请求的发送方 IP 地址都会变成代理服务器的 IP 地址,无法判断实际发送请求的客户端是哪个。此外,如果使用了地址转换,发送方 IP 地址则会变成地址转换设备的 IP 地址,也无法判断具体是哪个客户端。
22 代理:一种介于客户端与 Web 服务器之间,对访问操作进行中转的机制。这部分内容稍后会在 5.4 节进行介绍。
于是,人们想出了一些方案来判断请求之间的相关性。例如,可以在发送表单数据时在里面加上用来表示关联的信息,或者是对 HTTP 规格进行扩展,在 HTTP 头部字段中加上用来判断相关性的信息 23 。这样,负载均衡器就可以通过这些信息来作出判断,将一系列相关的请求发送到同一台 Web 服务器,对于不相关的请求则发送到负载较低的服务器了。
23 这种信息俗称 Cookie。
5.4 使用缓存服务器分担负载
5.4.1 如何使用缓存服务器
除了使用多台功能相同的 Web 服务器分担负载之外,还有另外一种方法,就是将整个系统按功能分成不同的服务器 24 ,如 Web 服务器、数据库服务器。缓存服务器就是一种按功能来分担负载的方法。
24 也可以将“使用多台功能相同的服务器”和“使用多台功能不同的服务器”这两种方法结合起来使用。
缓存服务器是一台通过代理机制对数据进行缓存的服务器。代理介于 Web 服务器和客户端之间,具有对 Web 服务器访问进行中转的功能。当进行中转时,它可以将 Web 服务器返回的数据保存在磁盘中,并可以代替 Web 服务器将磁盘中的数据返回给客户端。这种保存的数据称为缓存,缓存服务器指的也就是这样的功能。
Web 服务器需要执行检查网址和访问权限,以及在页面上填充数据等内部操作过程,因此将页面数据返回客户端所需的时间较长。相对地,缓存服务器只要将保存在磁盘上的数据读取出来发送给客户端就可以了,因此可以比 Web 服务器更快地返回数据。
不过,如果在缓存了数据之后,Web 服务器更新了数据,那么缓存的数据就不能用了,因此缓存并不是永久可用的。此外,CGI 程序等产生的页面数据每次都不同,这些数据也无法缓存。无论如何,在来自客户端的访问中,总有一部分访问可以无需经过 Web 服务器,而由缓存服务器直接处理。即便只有这一部分操作通过缓存服务器提高了速度,整体性能也可以得到改善。此外,通过让缓存服务器处理一部分请求,也可以减轻 Web 服务器的负担,从而缩短 Web 服务器的处理时间。
5.4.2 缓存服务器通过更新时间管理内容
下面来看一看缓存服务器的工作过程 25 。缓存服务器和负载均衡器一样,需要代替 Web 服务器被注册到 DNS 服务器中。然后客户端会向缓存服务器发送 HTTP 请求消息(图 5.5(a)①、图 5.6(a))。这时,缓存服务器会接收请求消息,这个接收操作和 Web 服务器相同。Web 服务器的接收操作我们会在第 6 章的 6.2 节进行介绍 26 ,简单来说就是创建用来等待连接的套接字,当客户端进行连接时执行连接操作,然后接收客户端发送的请求消息。从客户端来看,缓存服务器就相当于 Web 服务器。接下来,缓存服务器会检查请求消息的内容,看看请求的数据是否已经保存在缓存中。根据是否存在缓存数据,后面的操作会有所不同,现在我们假设不存在缓存数据。这时,缓存服务器会像图 5.6(b)②这样,在 HTTP 头部字段中添加一个 Via 字段,表示这个消息经过缓存服务器转发,然后将消息转发给 Web 服务器(图 5.5(a)②)。
25 要理解缓存服务器的工作过程,需要先理解 Web 服务器和 HTTP 协议,这些内容在第 1 章进行了介绍。
26 数据收发操作的基本知识在第 2 章也有相关介绍。
图 5.5 临时保存内容并代替 Web 服务器返回内容的缓存服务器
图 5.6 缓存中没有数据的情况
在这个过程中,我们需要判断应该将请求消息转发给哪台 Web 服务器。如果只有一台 Web 服务器,那么情况比较简单,只要将 Web 服务器的域名和 IP 地址配置在缓存服务器上,让它无条件转发给这台服务器就可以了。不过,如果一台缓存服务器对应多台 Web 服务器就没那么简单了,需要根据请求消息的内容来判断应该转发给哪台 Web 服务器。要实现这个目的有几种方法,其中比较有代表性的是根据请求消息的 URI(图 5.6(b)①)中的目录名来进行判断。使用这种方法时,我们首先需要在缓存服务器上进行如下设置。
当 URI 为 /dir1/ 这个目录时,转发给 www1.lab.glasscom.com
当 URI 为 /dir2/ 这个目录时,转发给 www2.lab.glasscom.com
缓存服务器会根据上述规则来转发请求消息,在这个过程中,缓存服务器会以客户端的身份向目标 Web 服务器发送请求消息。也就是说,它会先创建套接字,然后连接到 Web 服务器的套接字,并发送请求消息。从 Web 服务器来看,缓存服务器就相当于客户端。于是,缓存服务器会收到来自 Web 服务器的响应消息(图 5.5(a)③、图 5.6(c)),接收消息的过程也是以客户端的身份来完成的。
接下来,缓存服务器会在响应消息中加上图 5.6(d)①这样的 Via 头部字段,它表示这个消息是经过缓存服务器中转的,然后缓存服务器会以 Web 服务器的身份向客户端发送响应消息(图 5.5(a)④)。同时,缓存服务器会将响应消息保存到缓存中,并记录保存的时间(图 5.5(a)④’)。
这种在客户端和 Web 服务器之间充当中间人的方式就是代理的基本原理。在中转消息的过程中,缓存服务器还会顺便将页面数据保存下来,随着缓存数据的积累,用户访问的数据命中缓存的几率也会提高。接下来我们来看一看命中缓存的情况(图 5.5(b))。
首先,接收客户端的请求消息并检查缓存的过程和刚才是一样的(图 5.5(b)①、图 5.6(a))。然后,如图 5.7(a),缓存服务器会添加一个 If-Modified-Since 头部字段并将请求转发给 Web 服务器,询问 Web 服务器用户请求的数据是否已经发生变化(图 5.5(b)②、图 5.7(a))。
然后,Web 服务器会根据 If-Modified-Since 的值与服务器上的页面数据的最后更新时间进行比较,如果在指定时间内数据没有变化,就会返回一个像图 5.7(b)一样的表示没有变化的响应消息(图 5.5(b)③)。这时, Web 服务器只要查询一下数据的最后更新时间就好了,比返回页面数据的负担要小一些。而且返回的响应消息也比较短,能相应地减少负担。接下来,返回消息到达缓存服务器,然后缓存服务器就会知道 Web 服务器上的数据和本地缓存中的数据是一样的,于是就会将缓存的数据返回给客户端(图 5.5(b)④)。缓存服务器返回的响应消息的内容和没有命中缓存的情况是一样的(图 5.6(d))。
此外,当 Web 服务器上的数据有变化时,后面的过程和没有命中缓存的情况是一样的。Web 服务器会返回最新版本的数据(图 5.5(a)③、图 5.6(c)),然后缓存服务器加上 Via 字段发送给客户端,同时将数据保存在缓存中。
图 5.7 缓存中有数据的情况
5.4.3 最原始的代理——正向代理
刚才讲的是在 Web 服务器一端部署一个代理,然后利用其缓存功能来改善服务器的性能,还有一种方法是在客户端一侧部署缓存服务器。下面先稍微脱离一下主线,介绍一下客户端一侧的缓存服务器。
实际上,缓存服务器使用的代理机制最早就是放在客户端一侧的,这才是代理的原型,称为正向代理 27 (forward proxy)。
27 其实正向代理并不是一开始就叫这个名字,最早说的“代理”指的就是我们现在说的正向代理,或者也叫“代理服务器”。这是因为最早只有这么一种代理,后来出现了各种其他方式的代理,为了相互区别才起了“××代理”这样的名字。此外,由于代理种类变多了,叫“××代理服务器”实在太长,一般都会省略“服务器”3 个字。
正向代理刚刚出现的时候,其目的之一就是缓存,这个目的和服务器端的缓存服务器相同。不过,当时的正向代理还有另外一个目的,那就是用来实现防火墙。
防火墙的目的是防止来自互联网的非法入侵,而要达到这个目的,最可靠的方法就是阻止互联网和公司内网之间的所有包。不过,这样一来,公司员工就无法上外网了,因此还必须想一个办法让必要的包能够通过,这个办法就是利用代理。简单来说,代理的原理如图 5.8 所示,它会先接收来自客户端的请求消息,然后再转发到互联网中 28 ,这样就可以实现只允许通过必要的网络包了。这时,如果能够利用代理的缓存,那么效果就会更好,因为对于以前访问过的数据,可以直接从位于公司内网的代理服务器获得,这比通过低速线路访问互联网要快很多 29 。
28 代理(Proxy)本来的意思并不是“转发”消息,而是先把消息收下来,然后“伪装”成原始客户端向 Web 服务器发出访问请求。
29 代理出现于 ADSL、FTTH 等技术实用化之前,那个时候还没有廉价高速的接入网,因此必须想办法榨干低速接入网中的所有能力。代理的缓存功能正是有效利用低速接入网的一种方法。
图 5.8 利用代理实现防火墙
此外,由于代理在转发过程中可以查看请求的内容,所以可以根据内容判断是否允许访问。也就是说,通过代理可以禁止员工访问危险的网站,或者是与工作内容无关的网站。包过滤方式的防火墙只能根据 IP 地址和端口号进行判断,因此无法实现这一目的。
在使用正向代理时,一般需要在浏览器的设置窗口中的“代理服务器”一栏中填写正向代理的 IP 地址,浏览器发送请求消息的过程也会发生相应的变化。在没有设置正向代理的情况下,浏览器会根据网址栏中输入的 http://... 字符串判断 Web 服务器的域名,并向其发送请求消息;当设置了正向代理时,浏览器会忽略网址栏的内容,直接将所有请求发送给正向代理。请求消息的内容也会有一些不同。没有正向代理时,浏览器会从网址中提取出 Web 服务器域名后面的文件名或目录名,然后将其作为请求的 URI 进行发送;而有正向代理时,浏览器会像图 5.9 这样,在请求的 URI 字段中填写完整的 http://... 网址。
图 5.9 正向代理的HTTP 消息
正向代理转发消息的过程也和服务器端的缓存服务器有一些不同,不同点在于对转发目标 Web 服务器的判断上。使用正向代理时,URI 部分为 http://... 这样的完整网址,因此可以根据这个网址来转发,不需要像服务器端的缓存服务器一样实现设置好转发目标 Web 服务器,而且可以发给任意 Web 服务器。而服务器端的缓存服务器只能向事先设置好的目标进行转发,这就是两者不同的地方。
5.4.4 正向代理的改良版——反向代理
正如前面讲过的,使用正向代理需要在浏览器中进行设置,这可以说是识别正向代理的一个特征。但是,设置浏览器非常麻烦,如果设置错误还可能导致浏览器无法正常工作。
需要设置浏览器这一点除了麻烦、容易发生故障之外,还有其他一些限制。如果我们想把代理放在服务器端,那么服务器不知道谁会来访问,也没办法去设置客户端的浏览器,因此无法采用这种方法来实现。
于是,我们可以对这种方法进行改良,使得不需要在浏览器中设置代理也可以使用。也就是说,我们可以通过将请求消息中的 URI 中的目录名与 Web 服务器进行关联,使得代理能够转发一般的不包含完整网址的请求消息。我们前面介绍的服务器端的缓存服务器采用的正是这种方式,这种方式称为反向代理(reverse proxy)。
5.4.5 透明代理
缓存服务器判断转发目标的方法还有一种,那就是查看请求消息的包头部。因为包的 IP 头部中包含接收方 IP 地址,只要知道了这个地址,就知道用户要访问哪台服务器了 30 。这种方法称为透明代理(transparent proxy)。
30 HTTP 1.1 版本增加了一个用于表示访问目标 Web 服务器的 Host 字段,因此也可以通过 Host 字段来判断转发目标。
这种方法也可以转发一般的请求消息,因此不需要像正向代理一样设置浏览器参数,也不需要在缓存服务器上设置转发目标,可以将请求转发给任意 Web 服务器。
透明代理集合了正向代理和反向代理的优点,是一个非常方便的方式,但也需要注意一点,那就是如何才能让请求消息到达透明代理。由于透明代理不需要设置在浏览器中,那么浏览器还是照常向 Web 服务器发送请求消息。反向代理采用的是通过 DNS 服务器解析引导的方法,但透明代理是不能采用这种方法的,否则透明代理本身就变成了访问目标,也就无法通过接收方 IP 地址判断转发目标了,这就失去了透明代理的意义。总之,正常情况下,请求消息是从浏览器直接发送到 Web 服务器,并不会到达透明代理。
于是,我们必须将透明代理放在请求消息从浏览器传输到 Web 服务器的路径中,当消息经过时进行拦截。可能大家觉得这种方法太粗暴,但只有这样才能让消息到达透明代理,然后再转发给 Web 服务器。如果请求消息有多条路径可以到达 Web 服务器,那么就必须在这些路径上都放置透明代理,因此一般是将网络设计成只有一条路可以走的结构,然后在这一条路径上放置透明代理。连接互联网的接入网就是这样一个关口,因此可以在接入网的入口处放置反向代理 31 。使用透明代理时,用户不会察觉到代理的存在,也不会注意到 HTTP 消息是如何被转发的,因此大家更倾向于将透明代理说成是缓存 32 。
31 也可以采用在网络中的某些地方将 Web 访问包筛选出来并转发给透明代理的方法。
32 最近有很多场合中已经将透明代理直接叫作“缓存”而不是“代理”了,不过无论叫什么名字,其内部结构是相同的。
5.5 内容分发服务
5.5.1 利用内容分发服务分担负载
缓存服务器部署在服务器端还是客户端,其效果是有差别的。如图 5.10(a)所示,当缓存服务器放在服务器端时,可以减轻 Web 服务器的负载,但无法减少互联网中的流量。这一点上,将缓存服务器放在客户端更有效(图 5.10(b))。互联网中会存在一些拥塞点,通过这些地方会比较花时间。如果在客户端部署缓存服务器,就可以不受或者少受这些拥塞点的影响,让网络流量更稳定,特别是当访问内容中含有大图片或视频时效果更明显。
图 5.10 缓存服务器的 3 种部署方式
不过,客户端的缓存服务器是归客户端网络运营管理者所有的,Web 服务器的运营者无法控制它。比如,某网站的运营者觉得最近网站上增加了很多大容量的内容,因此想要增加缓存服务器的容量。如果缓存放在服务器端,那么网站运营者可以自己通过增加磁盘空间等方式来进行扩容,但对于放在客户端的缓存就无能为力了。进一步说,客户端有没有缓存服务器还不一定呢。
因此,这两种部署缓存服务器的方式各有利弊,但也有一种方式能够集合两者的优点。那就是像图 5.10(c)这样,Web 服务器运营者和网络运营商签约,将可以自己控制的缓存服务器放在客户端的运营商处。
这样一来,我们可以把缓存服务器部署在距离用户很近的地方,同时 Web 服务器运营者还可以控制这些服务器,但这种方式也有问题。对于在互联网上公开的服务器来说,任何地方的人都可以来访问它,因此如果真的要实现这个方式,必须在所有的运营商 POP 中都部署缓存服务器才行,这个数量太大了,非常不现实。
要解决这个问题也有一些办法。首先,我们可以筛选出一些主要的运营商,这样可以减少缓存服务器的数量。尽管这样做可能会导致有些用户访问到缓存服务器还是要经过很长的距离,但总比直接访问 Web 服务器的路径要短多了,因此还是可以产生一定的效果。
接下来这个问题更现实,那就是即便减少了数量,作为一个 Web 服务器运营者,如果自己和这些运营商签约并部署缓存服务器,无论是费用还是精力都是吃不消的。为了解决这个问题,一些专门从事相关服务的厂商出现了,他们来部署缓存服务器,并租借给 Web 服务器运营者。这种服务称为内容分发服务 33 。下面我们来具体了解一下这种服务。
33 内容分发服务也叫 CDS(Content Delivery Service)。(现在更常用的名称叫 CDN(Content Delivery Network 或 Content Distribution Network)。——译者注)
提供这种服务的厂商称为 CDSP34 ,他们会与主要的供应商签约,并部署很多台缓存服务器 35 。另一方面,CDSP 会与 Web 服务器运营者签约,使得 CDSP 的缓存服务器配合 Web 服务器工作。具体的方法我们后面会介绍,只要 Web 服务器与缓存服务器建立关联,那么当客户端访问 Web 服务器时,实际上就是在访问 CDSP 的缓存服务器了。
34 CDSP:Content Delivery Service Provider,内容分发服务运营商。
35 有些 CDSP 会在互联网中部署几百台缓存服务器。
缓存服务器可以缓存多个网站的数据,因此 CDSP 的缓存服务器就可以提供给多个 Web 服务器的运营者共享。这样一来,每个网站运营者的平均成本就降低了,从而减少了网站运营者的负担。而且,和运营商之间的签约工作也由 CDSP 统一负责,网站运营者也节省了精力。
5.5.2 如何找到最近的缓存服务器
在使用内容分发服务时,如图 5.11 所示,互联网中有很多缓存服务器,如何才能从这些服务器中找到离客户端最近的一个,并让客户端去访问那台服务器呢?
图 5.11 访问目标服务器的所在地
我们可以像正向代理一样在浏览器中进行设置,但用户那么多,也没办法帮所有人去设置浏览器。因此,我们需要一种机制,即便用户不进行任何设置,也能够将请求消息发送到缓存服务器。
这样的方法有几种,下面我们按顺序来介绍。第一个方法是像负载均衡一样用 DNS 服务器来分配访问。也就是说,我们可以在 DNS 服务器返回 Web 服务器 IP 地址时,对返回的内容进行一些加工,使其能够返回距离客户端最近的缓存服务器的 IP 地址。在解释这种方法的具体原理之前,我们先来复习一下 DNS 的基本工作方式。
互联网中有很多台 DNS 服务器,它们通过相互接力来处理 DNS 查询,这个过程从客户端发送查询消息开始,也就是说客户端会用要访问的 Web 服务器域名生成查询消息,并发送给自己局域网中的 DNS 服务器 36 (图 5.12 ①)。然后,客户端 DNS 服务器会通过域名的层次结构找到负责管理该域名的 DNS 服务器,也就是 Web 服务器端的那个 DNS 服务器,并将查询消息发送给它(图 5.12 ②)。Web 服务器端的 DNS 服务器收到查询消息后,会查询并返回域名相对应的 IP 地址。在这台 DNS 中,有一张管理员维护的域名和 IP 地址的对应表,只要按照域名查表,就可以找到相应的 IP 地址(图 5.12 ③)。接下来,响应消息回到客户端的 DNS 服务器,然后再返回给客户端(图 5.12 ④)。
36 如果自己的本地局域网中没有 DNS 服务器,则将请求发送给运营商的 DNS 服务器。
图 5.12 DNS 服务器的一般工作方式
上面讲的是 Web 服务器的域名只对应一个 IP 地址的情况,如果一个域名对应多个 IP 地址,则按照前面图 5.3 的轮询方式按顺序返回所有的 IP 地址。
如果按照 DNS 服务器的一般工作方式来看,它只能以轮询方式按顺序返回 IP 地址,完全不考虑客户端与缓存服务器的远近,因此可能会返回离客户端较远的缓存服务器 IP 地址。
如果要让用户访问最近的缓存服务器,则不应采用轮询方式,而是应该判断客户端与缓存服务器的距离,并返回距离客户端最近的缓存服务器 IP 地址。这里的关键点不言自明,那就是到底该怎样判断客户端与缓存服务器之间的距离呢?
方法是这样的。首先,作为准备,需要事先从缓存服务器部署地点的路由器收集路由信息(图 5.13)。例如,在图 5.13 的例子中,一共有 4 台缓存服务器,在这 4 台服务器的部署地点又分别有 4 台路由器,则我们需要分别获取这 4 台路由器的路由表,并将 4 张路由表集中到 DNS 服务器上。
图 5.13 DNS 服务器参照路由信息时的工作方式
接下来,DNS 服务器根据路由表查询从本机到 DNS 查询消息的发送方,也就是客户端 DNS 服务器的路由信息。例如,根据图 5.13 路由器 A 的路由表,可以查出路由器 A 到客户端 DNS 服务器的路由。通过互联网内部的路由表中的路由信息可以知道先通过运营商 X,然后通过运营商 Y,最后到达运营商 Z 这样的信息,通过这样的信息可以大致估算出距离。依次查询所有路由器的路由表之后,我们就可以通过比较找出哪一台路由器距离客户端 DNS 服务器最近。提供路由表的路由器位于缓存服务器的位置,而客户端 DNS 服务器也应该和客户端在同一位置,这样就等于估算出了缓存服务器与客户端之间的距离,从而能够判断出哪台缓存服务器距离客户端最近了。实际上,客户端 DNS 服务器不一定和客户端在同一位置,因此可能无法得出准确的距离,但依然可以达到相当的精度。
5.5.3 通过重定向服务器分配访问目标
还有另一个让客户端访问最近的缓存服务器的方法。HTTP 规格中定义了很多头部字段,其中有一个叫作 Location 的字段。当 Web 服务器数据转移到其他服务器时可以使用这个字段,它的意思是“您要访问的数据在另一台服务器上,请访问那台服务器吧。”这种将客户端访问引导到另一台 Web 服务器的操作称为重定向,通过这种方法也可以将访问目标分配到最近的缓存服务器。
当使用重定向告知客户端最近的缓存服务器时,首先需要将重定向服务器注册到 Web 服务器端的 DNS 服务器上。这样一来,客户端会将 HTTP 请求消息发送到重定向服务器上。重定向服务器和刚才一种方法中的 DNS 服务器一样,收集了来自各个路由器的路由信息,并根据这些信息找到最近的缓存服务器,然后将缓存服务器的地址放到 Location 字段中返回响应。这样,客户端就会重新去访问指定的缓存服务器了(图 5.14、图 5.15)。
图 5.14 通过重定向让客户端访问最近的缓存服务器的机制
图 5.15 使用重定向时 HTTP 消息的内容
这种方法的缺点在于增加了 HTTP 消息的交互次数,相应的开销也比较大,但它也有优点。对 DNS 服务器进行扩展的方法是估算客户端 DNS 服务器到缓存服务器之间的距离,因此精度较差;相对而言,重定向的方法是根据客户端发送来的 HTTP 消息的发送方 IP 地址来估算距离的,因此精度较高。
此外,也可以使用除路由信息之外的其他一些信息来估算距离,进一步提高精度。重定向服务器不仅可以返回带有 Location 字段的 HTTP 消息,也可以返回一个通过网络包往返时间估算到缓存服务器的距离的脚本,通过在客户端运行脚本来找到最优的缓存服务器。这个脚本可以向不同的缓存服务器发送测试包并计算往返时间,然后将请求发送到往返时间最短的一台缓存服务器,这样就可以判断出对于客户端最优的缓存服务器,并让客户端去访问该服务器。
5.5.4 缓存的更新方法会影响性能
还有一个因素会影响缓存服务器的效率,那就是缓存内容的更新方法。缓存本来的思路是像图 5.5 那样,将曾经访问过的数据保存下来,然后当再次访问时拿出来用,以提高访问操作的效率。不过,这种方法对于第一次访问是无效的,而且后面的每次访问都需要向原始服务器查询数据有没有发生变化,如果遇到网络拥塞,就会使响应时间恶化。
要改善这一点,有一种方法是让 Web 服务器在原始数据发生更新时,立即通知缓存服务器,使得缓存服务器上的数据一直保持最新状态,这样就不需要每次确认原始数据是否有变化了,而且从第一次访问就可以发挥缓存的效果。内容分发服务采用的缓存服务器就具备这样的功能。
此外,除了事先编写好内容的静态页面之外,还有一些在收到请求后由 CGI 程序生成的动态页面,这种动态页面是不能保存在缓存服务器上的。这种情况下,我们可以不保存整个页面,而是将应用程序生成的部分,也就是每次内容都会发生变化的动态部分,与内容不会发生变化的静态部分分开,只将静态部分保存在缓存中。
Web 服务器前面存在着各种各样的服务器,如防火墙、代理服务器、缓存服务器等。请求消息最终会通过这些服务器,到达 Web 服务器。Web 服务器接收请求之后,会查询其中的内容,并根据请求生成并返回响应消息。关于这一部分,我们将在下一章进行介绍。
小测验
本章的旅程告一段落,我们为大家准备了一些小测验题目,确认一下自己的成果吧。
问题
1. 现在主流的防火墙方式叫什么?
2. 当防火墙需要确定应用程序种类时要检查什么信息?
3. 用于分担 Web 服务器负载,将访问分配到多台服务器上的设备叫什么?
4. 部署在服务器端的代理是正向代理还是反向代理?
5. 在互联网中部署多台缓存服务器,并将其租借给 Web 服务器运营者的服务叫什么?
Column 网络术语其实很简单
当通信线路变成局域网
探索队员 :局域网和通信线路有什么不同啊?探索
探索队长 :其实局域网这个词本来的意思呢……
队员 :我知道我知道,我已经查过字典了。不过我的字典里面没有这个词啊,是不是我上学时买的字典太老了?
队长 :语言日新月异,你该去买本新的啦。
队员 :说得轻巧,还有一个礼拜才发工资呢……
队长 :没办法,好吧,我借你一本。
队员 :哦,查到了,局域网英文全称叫 Local Area Network,这个 local 是中央和地方的那个地方的意思吗?
队长 :这里的 local 指的是一个小的区域,是“本地”的意思,比如本地线、本地局。局域网是在一幢楼里面使用的,一幢楼就是一小块地方,所以才叫 local。
队员 :这个我知道的,我问的是它和通信线路有什么不同?
队长 :通信线路是通信运营商,也就是电话公司部署的遍布全球的线路,所以在世界各地都可以使用,这跟局域网完全是两码事吧?
队员 :这个我也知道啊,我想问的不是这个,我想问的是,局域网是不是比通信线路更快更便宜?
队长 :算是吧。
队员 :那么通信线路为什么不能像局域网一样又快又便宜呢?
队长 :原来如此,我很理解你的想法,也很赞同,不过事情可没那么简单。
队员 :为什么呢?
队长 :回想一下,我们探索 ADSL 的时候曾经说过,离电话局越远,速度就越慢,对不对?
队员 :对。
队长 :在一幢楼里,距离近的时候,局域网可以做到又快又便宜,但局域网可不能直接扩展到全世界。
队员 :噢……
队长 :看来还是没懂啊?
队员 :ADSL 确实是越远越慢,但 FTTH 什么的不是跟局域网一样快吗?
队长 :唔,你还真是不撞南墙不回头。
队员 :不,我只是想知道真相而已,
队长 阁下!
队长 :FTTH 之所以又快又便宜,是因为它能够使用局域网的技术。
队员 :可是为什么局域网不能用在距离远的地方呢?
队长 :我就知道你会这么问,所以我才不想回答这种问题啊。刚才我说局域网只能用在近的地方,那是光纤普及之前的事了。
队员 :什么嘛,原来是老黄历了。(马上又开始倚老卖老了……)
队长 :你说什么?
队员 :没……没什么。
队长 :使用现在的光纤技术,的确可以将线路延伸到几十公里,因此用局域网技术也可以将距离很远的地方连接起来。
队员 :原来如此。
队长 :而且,随着网络的普及,现在光纤可以大批量生产了,还很廉价。
队员 :那我们把通信线路全都换成局域网不就好了吗?
队长 :也许将来会有这一天吧……
队长 :哎,真的吗?
队长 :谁知道呢……
小测验答案
1. 包过滤方式(参见【5.2.1】)
2. 端口号(参见【5.2.3】)
3. 负载均衡器(参见【5.3.2】)
4. 反向代理(参见【5.3.7】)
5. 内容分发服务(CDS 或 CDN)(参见【5.3.8】)