高可用性 Linux Web 服务器

作者:Aaron Gowatch

想象一下您是某个大型网站的系统管理员。现在是星期一早上 5:00。您被“老大哥”的寻呼吵醒。三台 Web 服务器中的一台刚刚掉线了。突然,您三分之一的流量无人响应。您能做什么?去办公室的路程并不短,等您到达那里时,您已经丢失了数千次点击,这可能意味着收入损失、生产力下降或错过最后期限。无论情况如何,总会有人受到影响。当您开始上班的路程时,您想知道这个问题本可以如何避免。

事实上,有很多解决方案可用,其中许多解决方案需要昂贵的硬件或软件。本文概述了一种简单有效的方法,可以以经济高效的方式实现相同的功能。此方法使用路由器和 Linux Web 服务器的环回接口。我们通过配置多台主机在任何给定时间都能够为相同的 IP 地址提供服务来实现高可用性。按照惯例,我们认为虚拟 IP 地址被分配给以太网接口。但是,没有两个以太网接口可以共享相同的 IP 地址。通过将相同的 IP 地址绑定到环回接口,我们能够将相同的 IP 地址分配给多台主机。例如,一个 SYN 数据包,目标是其中一个环回接口,它会通过线路传输到路由器,路由器根据其路由表决定下一个数据包跃点。然后,数据包被转发到下一个跃点——多台冗余 Web 服务器之一的以太网接口。然后,数据包从以太网接口转发到系统上配置的环回接口之一。一个 ACK(确认)将沿相同的路径反向传输。数据包源于环回接口,被转发到以太网接口,然后返回到路由器,以便发送回发送 SYN 数据包的原始主机。同样,这种方案的优点在于能够配置绑定到环回接口的相同 IP 地址的多台主机。通过这样做,我们能够通过简单地更改最后一个跃点路由器中的路由来重定向特定 IP 地址甚至整个子网的流量。这节省了时间并最大限度地减少了流量损失。这个过程甚至可以使用简单的 shell 脚本自动化。

配置 Linux 内核

内核必须配置为支持 IP 别名。IP 别名是将多个 IP 地址绑定到给定网络接口的过程,从而创建“虚拟”接口。在 Linux 下,接口名称是线性分配的。例如,第一个环回接口称为 lo,第二个称为 lo:1,第三个称为 lo:2,依此类推。您可以通过键入以下命令查看系统上配置了哪些接口

/sbin/ifconfig

配置内核以支持 TCP/IP、网络别名和 IP 别名。在 Linux 2.0.x 下,可以通过对以下内核配置选项回答“是”来实现

Network aliasing (CONFIG_NET_ALIAS) [Y/n/?] y
TCP/IP networking (CONFIG_INET) [Y/n/?] y
IP: aliasing support (CONFIG_IP_ALIAS) [Y/m/n/?] y
我们的网络

我们虚构的网络将由四台机器组成,尽管您可以使用最少两台或最多您预计需要的机器来支持相同的功能。四台机器将使我们能够处理大量的流量,并且仍然有充足的增长空间。让所有四台机器处理单个网站的流量也将提供一些负载均衡,使用“轮询” DNS。如果您超过了 Web 服务器的容量,添加额外的机器是一项简单的任务。

我们将采用 C 类地址 192.168.1.0 并应用 27 位子网掩码,这将产生 8 个子网和 240 个可用主机。

请注意,根据 RFC,上层和下层子网将不可用。某些操作系统不允许您使用属于这些子网之一的地址配置接口。某些路由器要求您隐式启用此功能。例如,Cisco 要求路由器配置命令 ip subnet-zero。这取决于具体实现,尽管我还没有见过 UNIX 或基于 Microsoft 的主机在使用所有子网时遇到问题。如果您无法使用所有八个子网,或者您是 RFC 合规性狂热者,则此配置将产生 6 个子网和 180 个唯一主机。

流量可以轻松地分布在我们 4 台主机上的最多 30 个不同的 Web 服务器上。它还为我们留下了四个空闲子网以供未来扩展。使用子网允许使用一些简单的命令将流量从一台机器重定向到另一台机器。但是,您的需求可能不需要像我们示例中那样大的实现。可以使用主机路由来实现相同的功能,因此路由表中的条目不是针对整个子网,而是针对使用 32 位子网掩码的单个 IP 地址。我将尝试解释适用的差异。

在这里,我们可以使用 C 类中的子网作为我们的 Web 服务器的以太网接口;即,192.168.1.1 作为我们的路由器,以及 192.168.1.2、192.168.1.3 和 192.168.1.4 作为我们的 Web 服务器。在 Red Hat 下,这是通过编辑 /etc/sysconfig/network-scripts/eth0 文件来完成的,使其看起来像这样

DEVICE=eth0
IPADDR=192.168.1.2
NETMASK=255.255.255.224
NETWORK=192.168.1.0
BROADCAST=192.168.1.31
ONBOOT=yes

您还需要编辑 /etc/sysconfig/network 文件以配置适当的默认路由。我的看起来像这样

NETWORKING=yes
HOSTNAME=foohost.foo.com
DOMAINNAME=foo.com
GATEWAY=192.168.1.1
GATEWAYDEV=eth0
接口配置因发行版而异,因此您的结果可能会有所不同。
设置我们的路由器

应设置路由器,使其在与 Web 服务器相同的子网上具有接口。在我们的示例中,我们将路由上的一个接口分配给 IP 地址 192.168.1.1。这将是我们 Web 服务器的默认路由。

我们的第一个网站

现在,假设您与 Widgetco, Inc. 签订了您的第一份合同,他们希望您在 http://www.widgetco.com/ 上设置他们的网站。此域的注册(不在本文的范围之内)应已完成。首先要做的是在 Web 服务器的环回接口上配置地址。在我们的 Red Hat 机器上,我们使用 /etc/sysconfig/network-scripts/ifcfg-lo:[1-655536] 配置它们。我们希望我们的每台主机都能够在任何给定时间为任何其他主机提供流量服务,因此每台 Web 服务器都将其他 Web 服务器的环回 IP 地址绑定到其环回接口。请记住,我们使用第一个子网作为 Web 服务器的以太网接口,因此从第二个子网开始,我们将从四个子网中的每个子网中选择一个地址。我们将采用 192.168.1.33、192.168.1.65、192.168.1.97 和 192.168.1.129,并将它们绑定到所有 Web 服务器上的环回接口。这就是冗余的来源。例如,/etc/sysconfig/network-scripts/ifcfg-lo:1 应该看起来像这样

DEVICE=lo:1
IPADDR=192.168.1.33
NETMASK=255.255.255.224
NETWORK=192.168.1.32
BROADCAST=192.168.1.63
ONBOOT=yes

我们的 /etc/sysconfig/network-scripts/ifcfg-lo:2 应该看起来像这样

DEVICE=lo:2
IPADDR=192.168.1.65
NETMASK=255.255.255.224
NETWORK=192.168.1.64
BROADCAST=192.168.1.95
ONBOOT=yes
依此类推,适用于所有四个环回接口。同样,在每台 Web 服务器上使用相同的配置文件执行此操作。使用相同 IP 地址的多台主机不会成为问题,因为它们位于环回接口上。

您应该能够运行以下命令来启动您新创建的接口在每台主机上

/etc/rc.d/init.d/network start

要确保您的环回接口已配置,请运行

/sbin/ifconfig
如果一切都已正确完成,您的输出将类似于列表 1

此时,您应该能够从配置环回接口的主机 ping 通绑定到环回接口的四个地址。下一步是在路由器上设置路由表,以便路由器知道如何到达这些环回接口。我们将为四个子网中的每个子网设置一条路由,指向四台主机中的每一台。

Cisco 路由器的示例可能如下所示

ip route 192.168.1.32 255.255.255.224 192.168.1.2
ip route 192.168.1.64 255.255.255.224 192.168.1.3
ip route 192.168.1.96 255.255.255.224 192.168.1.4
ip route 192.168.1.128 255.255.255.224 192.168.1.5

如果您使用 Linux 作为路由器,它将如下所示

/sbin/route add -net 192.168.1.32 netmask\
255.255.255.224 192.168.1.2
/sbin/route add -net 192.168.1.64 netmask\
255.255.255.224 192.168.1.3
/sbin/route add -net 192.168.1.96 netmask\
255.255.255.224 192.168.1.4
/sbin/route add -net 192.168.1.128 netmask\
255.255.255.224 192.168.1.5
基本上,此信息告诉路由器,目标为 192.168.1.32 子网上任何主机的包的下一个跃点是我们第一台主机 192.168.1.2 的以太网接口。目标为 192.168.1.64 子网上任何主机的包的下一个跃点是我们第二台主机 192.168.1.3 的以太网接口。还为我们的第三个和第四个子网设置了路由表条目,它们分别指向第三个和第四个主机。设置这些条目将因您选择用作路由器的硬件而异。最好熟悉在硬件上添加和删除路由的过程。此时,您应该能够从路由器 ping 通 Web 服务器上的环回接口。使用此路由器的其他机器也应该能够访问环回接口。使用 TELNET 连接到 192.168.1.33 应该让您在第一台主机上获得登录提示,而 192.168.1.65 应该让您连接到第二台主机,依此类推。

现在,我们将设置 DNS,以便 www.widgetco.com 由我们的 Web 服务器轮换提供服务。对于 Red Hat Linux,我们将以下内容放在 /var/named/widgetco.com 中

@ IN SOA ns1.widgetco.com. hostmaster.widgetco.com.
(
 1998020100 ; serial (yyyymmddnn)
 86400 ; refresh (every day)
 3600 ; retry (every hour)
 1209600 ; expire (2 weeks)
 86400 ) ; minimum TTL (half day)
 IN NS ns.foo.com.
www IN A 192.168.1.33
         IN     A       192.168.1.65
         IN     A       192.168.1.97
         IN     A       192.168.1.129
配置 Apache

应在 /etc/conf/httpd.conf 中为 Red Hat Linux 配置 Apache,以侦听我们配置的每个环回接口。让我们看一个简单的例子

<VirtualHost 192.168.1.33 192.168.1.65 192.168.1.97
192.168.1.129>
ServerName www.widgetco.com
DocumentRoot /www/www.widgetco.com
</VirtualHost>

这告诉 Apache 侦听我们的所有四个环回接口,设置 ServerName 并设置 DocumentRoot,Apache 将从中为 www.widgetco.com 提供内容。尽管在正常操作期间 Apache 不会看到所有四个接口上的流量,但在之前配置 Apache 侦听将允许我们动态地将流量从一台 Web 服务器重定向到另一台。

重定向流量

将流量从一台机器重定向到另一台机器非常简单。这只是更改路由器认为给定子网或主机的下一个跃点。例如,如果我们需要重新启动我们的第一台 Web 服务器,我们可以使用以下 Cisco 路由器命令将流量重定向到第二台

no ip route 192.168.1.32 255.255.255.224
ip route 192.168.1.32 255.255.255.224 192.168.1.3

所有要发送到 192.168.1.2 的流量现在都被重新路由到 192.168.1.3,即第二台 Web 服务器,并且我们只丢失了在第一个和第二个路由器配置命令之间发送的数据包。如果您的路由器运行的是 Linux,您可以编写一个简单的 shell 脚本来自动为您更改这些路由。几行 Expect 可以更改专用硬件路由器中的路由。

其他应用?

这种流量重定向方法不仅限于 Web 服务器。其他使用 IP 并且可以从高可用性中受益的应用程序可以使用类似于我们已经介绍的方法。一些示例包括 DNS、FTP 和邮件服务器。

High Availability Linux Web Servers
Aaron Gowatch 是居住在加利福尼亚州旧金山的资深系统工程师。如今,他花在修理他的 Vespa 和 Lambretta 摩托车上的时间几乎与坐在控制台前的时间一样多。可以通过 aarong@divinia.com 联系到他。
加载 Disqus 评论