7.4.2 案例分享二:企业级Web负载均衡高可用之Nginx+Keepalived

推荐掌握企业级的成熟的Nginx+Keepalived负载均衡高可用方案,其拓扑图如图7-7所示。

阅读 ‧ 电子书库

广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元

图7-7 Nginx+Keepalived负载均衡高可用网络拓扑图

一般为了维护方便,企业网站的服务器都在自己的内部机房里,只开放了Keepalived的VIP地址的两个端口80、443,通过Juniper SSG550防火墙映射出去,外网DNS对应映射后的公网IP。此架构的防火墙及网络安全说明如下。

此系统架构仅映射内网VIP的80及443端口于外网的Juniper SSG550防火墙下,其他端口均关闭,内网的所有机器均关闭iptables及ipfw防火墙;外网DNS指向通过Juniper或华赛USG5000映射出来的外网地址。

本节内容出自笔者的项目方案,这种负载均衡的方式同时也应用于笔者公司的电子商务网站中,目前已经稳定上线一年多了。通过下面的内容,大家可以迅速地架构起一个企业级的负载均衡高可用的Web环境。在负载均衡高可用技术上,笔者一直推崇以Nginx+Keepalived做Web的负载均衡高可用架构,并积极将其应用于真实项目中,此架构极适合灵活稳定的环境。Nginx负载均衡作服务器遇到的故障一般有:

·服务器网线松动等网络故障。

·由于服务器硬件故障而导致宕机。

·Nginx服务死掉。

遇到前两种情况时,Keepalived是能起到HA的作用的;然而遇到第三种情况时就没有办法了,但可以通过Shell脚本监控解决这问题,从而实现真正意义上的负载均衡高可用。笔者在电子商务网站上就采用了这种方法,下面将其安装步骤详细说明一下。

1.Nginx+Keepalived的说明及环境说明

关于服务器系统,从早期的CentOS 5.1 x86_64到现在的CentOS 5.5 x86_64我们均有涉及,有时应客户的要求,也有大量RHEL 5.x x86_64系列的主机。整个系统的IP情况如表7-2所示。

表7-2 Nginx+Keepalived服务器的IP分配表

阅读 ‧ 电子书库

2.分别安装Nginx负载均衡器及相关的配置脚本

先安装Nginx负载均衡器,Nginx负载的设置就用一般的模板来配置。

1)添加运行Nginx的用户和组www及Nginx存放日志的位置,并安装gcc等基础库,以免发生libtool报错现象,命令如下:

yum -y install gcc gcc+ gcc-c++ openssl openssl-devel

groupadd www

useradd -g www www

mdkir –

p /data/logs/

chown –

R www:www /data/logs/

2)下载并安装Nginx0.8.15(当时最新最稳定的版本),另外建议在工作中养成良好的习惯,下载的软件包均放到/usr/local/src下,命令如下:

cd /usr/local/src

wget http://blog.s135.com/soft/linux/nginx_php/pcre/pcre-7.9.tar.gz

tar zxvf pcre-7.9.tar.gz

cd pcre-7.9/

./configure

make && make install

cd ../

wget http://sysoev.ru/nginx/nginx-0.8.15.tar.gz

tar zxvf nginx-0.8.15.tar.gz

cd nginx-0.8.15/

./configure --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module

make && make install

cd ../

配置Nginx负载均衡器的配置文件是vim/usr/local/nginx/conf/nginx.conf,下面的配置文件仅仅是笔者某项目的配置文档,纯HTTP转发;如果要添加SSL支持也很简单,后面会有相关的说明,记得将购买的GeoTrust证书文件放到Nginx负载均衡器上(两台Nginx机器均要放),而非置于后面的Web机器上,配置文件内容如下:

user www www;

worker_processes 8; #老版的

Nginx跟新版的

Nginx此处的配置是不一样的,具体请参考

Nginx官方文档

pid /usr/local/nginx/logs/nginx.pid;

worker_rlimit_nofile 51200;

events

{

use epoll;

worker_connections 51200;

}

http{

include mime.types;

default_type application/octet-stream;

server_names_hash_bucket_size 128;

client_header_buffer_size 32k;

large_client_header_buffers 4 32k;

client_max_body_size 8m;

sendfile on;

tcp_nopush on;

keepalive_timeout 60;

tcp_nodelay on;

fastcgi_connect_timeout 300;

fastcgi_send_timeout 300;

fastcgi_read_timeout 300;

fastcgi_buffer_size 64k;

fastcgi_buffers 4 64k;

fastcgi_busy_buffers_size 128k;

fastcgi_temp_file_write_size 128k;

gzip on;

gzip_min_length 1k;

gzip_buffers 4 16k;

gzip_http_version 1.0;

gzip_comp_level 2;

gzip_types text/plain application/x-javascript text/css application/xml;

gzip_vary on;

upstream backend {

ip_hash;

server 192.168.1.106:80;

server 192.168.1.107:80;

}

server {

listen 80;

server_name www.1paituan.com;

location / {

root /var/www/html ;

index index.php index.htm index.html;

proxy_redirect off;

proxy_set_header Host $host;

proxy_set_header X-Real-IP $remote_addr;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_pass http://backend;

}

location /nginx {

access_log off;

auth_basic "NginxStatus";

#auth_basic_user_file /usr/local/nginx/htpasswd;

}

log_format access '$remote_addr - $remote_user [$time_local] "$request" '

'$status $body_bytes_sent "$http_referer" '

'"$http_user_agent" $http_x_forwarded_for';

access_log /data/logs/access.log access;

}

}

分别在两台Nginx负载均衡器上执行/usr/local/nginx/sbin/nginx命令,启动Nginx进程,然后用如下命令来检查:

lsof -i:80

此命令显示结果如下:

COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME

nginx 13875 root 6u IPv4 25918 TCP *:http (LISTEN)

nginx 13876 www 6u IPv4 25918 TCP *:http (LISTEN)

nginx 13877 www 6u IPv4 25918 TCP *:http (LISTEN)

nginx 13878 www 6u IPv4 25918 TCP *:http (LISTEN)

nginx 13879 www 6u IPv4 25918 TCP *:http (LISTEN)

nginx 13880 www 6u IPv4 25918 TCP *:http (LISTEN)

nginx 13881 www 6u IPv4 25918 TCP *:http (LISTEN)

nginx 13882 www 6u IPv4 25918 TCP *:http (LISTEN)

nginx 13883 www 6u IPv4 25918 TCP *:http (LISTEN)

Nginx程序正常启动后,两台Nginx负载均衡器就算安装成功了,现在我们要安装Keepalived来实现这两台Nginx负载均衡器的高可用。

3.安装Keepalived,让其分别做Web及Nginx的HA

1)安装Keepalived,并将其做成服务模式,以方便后续调试,Keepalived的安装方法如下:

wget http://www.keepalived.org/software/keepalived-1.1.15.tar.gz

tar zxvf keepalived-1.1.15.tar.gz

cd keepalived-1.1.15

./configure --prefix=/usr/local/keepalived

make

make install

2)安装成功后做成服务模式,方便启动和关闭,方法如下:

cp /usr/local/keepalived/sbin/keepalived /usr/sbin/

cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/

cp /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/init.d/

3)接下来就是分别设置主和备Nginx上的Keepalived配置文件了。先配置主Nginx上的keepalived.conf文件,如下所示:

mkdir /etc/keepalived

cd /etc/keepalived/

可以用vim编辑/etc/keepalived.conf,内容如下:

! Configuration File for keepalived

global_defs {

notification_email {

yuhongchun027@163.com

}

notification_email_from keepalived@chtopnet.com

smtp_server 127.0.0.1

smtp_connect_timeout 30

router_id LVS_DEVEL

}

vrrp_instance VI_1 {

state MASTER

interface eth0

virtual_router_id 51

mcast_src_ip 192.168.1.103 #mcast_src_ip此处是发送多播包的地址,如果不设置,则默认使用绑定的网卡

priority 100 #此处的

priority是

100,注意跟

backup机器的区分

advert_int 1

authentication {

auth_type PASS

auth_pass chtopnet

}

virtual_ipaddress {

192.168.1.108

}

}

下面设置备用Nginx上的keepalived.conf的配置文件,注意将其与主Nginx上的keepalived.conf区分开,代码如下:

! Configuration File for keepalived

global_defs {

notification_email {

yuhongchun027@163.com

}

notification_email_from keepalived@chtopnet.com

smtp_server 127.0.0.1

smtp_connect_timeout 30

router_id LVS_DEVEL

}

vrrp_instance VI_1 {

state MASTER

interface eth0

virtual_router_id 51

mcast_src_ip 192.168.1.104

priority 99

advert_int 1

authentication {

auth_type PASS

auth_pass chtopnet

}

virtual_ipaddress {

192.168.1.108

}

}

在两台负载均衡器上分别启动Keepalived程序,命令如下:

service keepalived start

下面来看一下主Nginx机器上与Keepalived相关的日志,可用如下命令查看:

tail /var/log/messages

此命令显示结果如下:

May 6 05:10:42 localhost Keepalived_vrrp: Configuration is using : 62610 Bytes

May 6 05:10:42 localhost Keepalived_vrrp: VRRP sockpool: [ifindex(2), proto(112), fd(8,9)]

May 6 05:10:43 localhost Keepalived_vrrp: VRRP_Instance(VI_1) Transition to MASTER STATE

May 6 05:10:44 localhost Keepalived_vrrp: VRRP_Instance(VI_1) Entering MASTER STATE

May 6 05:10:44 localhost Keepalived_vrrp: VRRP_Instance(VI_1) setting protocol VIPs.

May 6 05:10:44 localhost Keepalived_healthcheckers: Netlink reflector reports IP 192.168.1.108 added

May 6 05:10:44 localhost Keepalived_vrrp: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 192.168.1.108

May 6 05:10:44 localhost Keepalived_vrrp: Netlink reflector reports IP 192.168.1.108 added

May 6 05:10:44 localhost avahi-daemon[2212]: Registering new address record for 192.168.1.108 on eth0.

May 6 05:10:49 localhost Keepalived_vrrp: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 192.168.1.108

很显然VRRP已经启动,还可以通过命令“ip addr”来检查主Nginx上的IP分配情况,通过下面的显示内容可以清楚地看到VIP地址已经绑定到主Nginx的机器上了。

ip addr

1: lo: mtu 16436 qdisc noqueue

link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

inet 127.0.0.1/8 scope host lo

inet6 ::1/128 scope host

valid_lft forever preferred_lft forever

2: eth0: mtu 1500 qdisc pfifo_fast qlen 1000

link/ether 00:0c:29:51:59:df brd ff:ff:ff:ff:ff:ff

inet 192.168.1.103/24 brd 192.168.1.255 scope global eth0

inet 192.168.1.108/32 scope global eth0

inet6 fe80::20c:29ff:fe51:59df/64 scope link

valid_lft forever preferred_lft forever

3: sit0: mtu 1480 qdisc noop

link/sit 0.0.0.0 brd 0.0.0.0

在这个过程中,有大量的VRRP数据包,那么什么是VRRP呢?为了让大家对Keepalived有所了解,这里向大家详细说明下虚拟路由冗余协议(Virtual Router Redundancy Protocol,VRRP)。

随着Internet的迅猛发展,基于网络的应用逐渐增多,这就对网络的可靠性提出了越来越高的要求。斥资对所有的网络设备进行更新当然是一种很好的可靠性解决方案,但从保护现有资产的角度考虑,可以采用廉价冗余的思路,在可靠性和经济性方面找到平衡点。

虚拟路由冗余协议就是一种很好的解决方案。在该协议中,对共享多存取访问介质(如以太网)上的终端IP设备的默认网关(Default Gateway)进行冗余备份,当其中一台路由设备宕机时,备份路由设备及时接管转发工作,向用户提供透明的切换,提高了网络服务质量。

(1)协议概述

在基于TCP/IP协议的网络中,为了保证没有直接物理连接的设备之间的通信,必须指定路由。目前常用的指定路由的方法有两种:一种是通过路由协议(比如:内部路由协议RIP和OSPF)动态学习;另一种是静态配置。在每一个终端都运行动态路由协议是不现实的,大多数客户端操作系统平台都不支持动态路由协议,即使支持也会受到管理开销、收敛度、安全性等许多问题的限制。因此普遍采用对终端IP设备进行静态路由配置的方式,一般是给终端设备指定一个或多个默认网关。静态路由的方法简化了网络管理的复杂度,也减轻了终端设备的通信开销,但是它仍然有一个缺点:如果作为默认网关的路由器损坏,所有使用该网关为下一跳主机的通信必然要中断。即便配置了多个默认网关,如不重新启动终端设备,也不能切换到新的网关上。但是采用虚拟路由冗余协议(VRRP)就可以很好地避免静态指定网关的缺陷。

在VRRP协议中,有两组重要的概念:VRRP路由器和虚拟路由器,主控路由器和备份路由器。VRRP路由器是指运行VRRP的路由器,是物理实体,虚拟路由器是指VRRP协议创建的路由器,是逻辑概念。一组VRRP路由器协同工作,共同构成一台虚拟路由器。该虚拟路由器对外表现为一个具有唯一固定IP地址和MAC地址的逻辑路由器。处于同一个VRRP组中的路由器具有两种互斥的角色:主控路由器和备份路由器,一个VRRP组中有且只有一台处于主控角色的路由器,但可以有一个或多个处于备份角色的路由器。VRRP协议使用选择策略从路由器组中选出一台作为主控路由器,负责ARP响应和转发IP数据包,组中的其他路由器作为备份的角色处于待命状态。当由于某种原因主控路由器发生故障时,备份路由器能在几秒钟的延时后升级为主控路由器。由于此切换非常迅速而且不用改变IP地址和MAC地址,故对终端使用者的系统来说是透明的。

(2)工作原理

一个VRRP路由器有唯一的标识:VRID,范围为0~255。该路由器对外表现为唯一的虚拟MAC地址,地址的格式为00-00-5E-00-01-[VRID]。主控路由器负责对ARP请求用该MAC地址做应答。这样,无论如何切换,保证给终端设备的都是唯一一致的IP和MAC地址,减少了切换对终端设备的影响。

VRRP控制报文只有一种:VRRP通告(advertisement)。它使用IP多播数据包进行封装,组地址为224.0.0.18,发布范围只限于同一局域网内。这点保证了VRID在不同的网络中可以重复使用。为了减少网络带宽的消耗,只有主控路由器才可以周期性地发送VRRP通告报文。若备份路由器在连续三个通告间隔内收不到VRRP或收到优先级为0的通告则启动新一轮的VRRP选举。

在VRRP路由器组中,按优先级选举主控路由器,VRRP协议中的优先级范围是0~255。若VRRP路由器的IP地址和虚拟路由器的接口IP地址相同,则称该虚拟路由器为VRRP组中的IP地址所有者,IP地址所有者自动具有最高优先级255。优先级0一般用在IP地址所有者主动放弃主控者角色时。可配置的优先级范围为1~254。优先级的配置原则可以依据链路的速度、成本、路由器的性能和可靠性,以及其他管理策略来设定。在主控路由器的选举中,高优先级的虚拟路由器会获胜,因此,如果在VRRP组中有IP地址所有者,则它总是作为主控路由的角色。对于有相同优先级的候选路由器,则按照IP地址的大小顺序进行选举。VRRP还提供了优先级抢占策略,如果配置了该策略,高优先级的备份路由器便会剥夺当前低优先级的主控路由器而成为新的主控路由器。

为了保证VRRP协议的安全性,这里有两种安全认证措施:明文认证和IP头认证。明文认证方式要求:在加入一个VRRP路由器组时,必须同时提供相同的VRID和明文密码。这种方法可以避免在局域网内的配置错误,但不能防止通过网络监听方式获得密码。IP头认证的方式提供了更高的安全性,能够防止报文重放和修改等攻击。

我们可以通过TCPDump抓包发现两台Nginx负载均衡器上均有大量VRRP包,在任何一台机器上开启TCPDump进行抓包,命令如下:

tcpdump vrrp

命令显示结果如下:

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode

listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes

18:04:16.372116 IP 192.168.1.103 > VRRP.MCAST.NET: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20

18:04:17.374134 IP 192.168.1.103 > VRRP.MCAST.NET: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20

18:04:18.375461 IP 192.168.1.103 > VRRP.MCAST.NET: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20

18:04:19.376198 IP 192.168.1.103 > VRRP.MCAST.NET: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20

18:04:20.377229 IP 192.168.1.103 > VRRP.MCAST.NET: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20

18:04:20.378986 IP 192.168.1.104 > VRRP.MCAST.NET: VRRPv2, Advertisement, vrid 51, prio 99, authtype simple, intvl 1s, length 20

18:04:20.381515 IP 192.168.1.103 > VRRP.MCAST.NET: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20

18:04:21.383936 IP 192.168.1.103 > VRRP.MCAST.NET: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20

可以看到,优先级高的一方(即priority为100的机器)通过VRRPv2获得了VIP地址;而且VRRPv2包的发送极有规律,每秒发送一次,当然了,这是通过配置文件进行控制的。通俗地讲,它会不断地发送VRRPv2包来告诉从机(作为“老二”的机器),我是“老大”,VIP地址我已经抢到手了,你不要再抢啦。

4.用nginx_pid.sh脚本来监控Nginx进程

针对Nginx+Keepalived方案,编写的Nginx监控脚本nginx_pid.sh实现了真正意义上的高可用。此脚本的思路其实也很简单,即将其放置在后台一直监控Nginx进程。如果进程消失,则尝试重启Nginx;如果失败,则立即停掉本机的Keepalived服务,让另一台负载均衡器接手。此脚本直接从生产环境下载,内容如下所示:

#!/bin/bash

while :

do

nginxpid=`ps -C nginx --no-header | wc -l`

if [ $nginxpid -eq 0 ];then

/usr/local/nginx/sbin/nginx

sleep 5

if [ $nginxpid -eq 0 ];then

/etc/init.d/keepalived stop

fi

fi

sleep 5

done

然后将其置于后台运行“sh/root/nginx_pid.sh&”(也可以将此程序交由Supervisor托管),做到这步时大家要注意一下,这种写法是有问题的,我们用root用户退出终端后,此进程便会消失,正确写法为“nohup/bin/bash/root/nginx_pid.sh&”。

此脚本是直接从生产服务器上下载的,大家不要怀疑它会引起死循环和有效性的问题。这是一个无限循环的脚本,放在主Nginx机器上(因为目前主要是由它来提供服务),每隔5秒执行一次,用ps-C命令来收集Nginx服务的PID值到底是否为0,如果是0的话(即Nginx进程死掉了),尝试启动Nginx进程;如果继续为0,即Nginx启动失败,则关闭本机的Keepalived进程,VIP地址将会由备机接管。当然了,整个网站就会由备机的Nginx来提供服务了,这样就保证了Nginx进程的高可用(虽然在实际生产环境中基本没发现Nginx进程死掉的情况,多此一步操作算是有备无患吧)。我们在几次的线上维护工作中,手动人为重启了主Nginx服务器,而从Nginx在非常短的时间就切换过来了,客户没有因为网站故障而进行投诉,事实证明此脚本还是有效的。

阅读 ‧ 电子书库

说明

介绍一下nohup的作用。如果你正在运行一个进程,而且你觉得在退出账户时该进程还不应该结束,那么可以使用nohup命令,该命令可以在你退出root账户之后继续运行相应的进程,nohup就是不挂起的意思(no hang up)。

5.模拟故障测试

整套系统配置完成后,我们就可以通过http://192.168.1.108/ 来访问了,接下来要做一些模拟性的故障测试,比如关掉一台Nginx负载均衡器,抽掉某台Web机器的网线或直接关机,甚至停掉其中一台Nginx服务器的Nginx服务。我们会发现无论在什么情况下,Nginx+Keepalived都可以正常提供服务,笔者的许多项目(包括电子商务网站)所用的都是此架构,并且已经在线上稳定运行好几年了。

6.Nginx作为负载均衡器在工作中遇到的问题

(1)如何让Nginx负载均衡器也支持HTTPS

要让Nginx支持HTTPS,方法其实很简单,在负载均衡器上开启SSL功能,监听443端口(防火墙上也要做好映射),将证书放在Nginx负载均衡器上(而不是后面的Web服务器),即可轻松解决此问题,详见以下nginx.conf配置文件:

server

{

listen 443;

server_name www.cn7788.com;

ssl on;

ssl_certificate /usr/local/nginx/keys/www.cn7788.com.crt;

ssl_certificate_key /usr/local/nginx/keys/www.cn7788.com.key;

ssl_protocols SSLv3 TLSv1;

ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:-LOW:-SSLv2:-EXP;

}

(2)如何让后端的Apache服务器获取客户端的真实IP

运行在后端Apache服务器上的应用所获取到的IP都是Nginx负载均衡所在服务器的IP,或者是本机127.0.0.1。查看Apache的访问日志,就会见到来来去去的都是内网的IP。虽然可以通过Nginx日志来判断客户端的IP,但有些考虑不周全的应用,例如Tattertools(一款优秀的博客程序)就会犯错,在后台的访问日志上总是显示访客数为1,IP来自127.0.0.1。这时候就要想办法来处理了。其实我们可以通过修改Nginx proxy的参数令后端应用获取到Nginx发来的请求报文,并获取外网的IP,在Nginx的配置文件中记得加上如下命令:

proxy_set_header Host $host;

proxy_set_header X-Real-IP $remote_addr;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

这仅仅是让Nginx获取外网IP,Apache未必买账呢!也就是说Apache端同样需要设置,搜寻了一下,发现Apache有一个来自第三方的mod(模块)可配合Nginx proxy使用。下面简要说一下这个模块。

该模块相关说明可参考:http://stderr.net/apache/rpaf/ 。

该模块的下载地址为:http://stderr.net/apache/rpaf/download/ 。

该模块的最新版本是mod_rpaf-0.6.tar.gz。

该模块的安装也相当简单,命令如下:

tar zxvf mod_rpaf-0.6.tar.gz

下载后解压,命令如下:

cd mod_rpaf-0.6

Apache的目录可按自己的环境进行修改,现在选择相应的安装方式,命令如下:

/usr/local/apache/bin/apxs -i -c -n mod_rpaf-2.0.so mod_rpaf-2.0.c

完成后会在http.conf的LoadModule区域多加了一行内容,命令如下:

LoadModule mod_rpaf-2.0.so_module modules/mod_rpaf-2.0.so

经Apache 2.2.6的实验证明,使用这一行启动Apache的时候会报错。所以将其改为:

LoadModule rpaf_module modules/mod_rpaf-2.0.so

并在下方添加:

RPAFenable On

RPAFsethostname On

RPAFproxy_ips 127.0.0.1 192.168.1.101 192.168.102

RPAFheader X-Forwarded-For

在填写Nginx所在的内网IP时,Nginx的内网地址是必写的,不然一样会失败,另外,有几个代理服务器的IP就写几个代理服务器的IP。

保存退出后重启Apache,再看看Apache的日志内容,应该已经很完美地解决了这个问题。

(3)正确区分Nginx的分发请求

笔者在负责某个小项目时,原本是基于Nginx的1+3架构,开发人员突然要求增加一台机器(Windows Server 2003系统),专门用于存放图片及PDF文件等,项目要求能在Nginx后的3台Web机器上显示图片,并且可以下载PDF。当时笔者感觉有点为难,因为程序用的是Zend Framework,所以一直在用正则表达式作为跳转。后来才想明白其中的“玄机”,IE程序先在Nginx负载均衡器上提出申请,所以nginx.conf是在做分发而非正则跳转,此时最前端的Nginx既是负载均衡器也是反向代理,明白这个就好办了。另外要注意location/StockInfo与location~^/StockInfo的差异性,Nginx默认是正则优先的,顺便也说一下,proxy_pass支持直接写IP的方式。Nginx配置文件的部分代码如下所示:

upstream mysrv {

ip_hash;

server 192.168.110.62;

server 192.168.110.63;

}

upstream myjpg {

server 192.168.110.3:88;

}

server

{

listen 80;

server_name web.tfzq.com;

proxy_redirect off;

location ~ ^/StockInfo{

proxy_pass http://myjpg;

}

关于这个案例,在此总结一下:目前此套架构在2000并发的电子商务网站上运行非常稳定,唯一不足之处就是Nginx_backup一直处于闲置状态。相对于双主Nginx负载均衡器而言,此架构比较简单,出问题的概率相对也较小,而且出问题时很容易排除故障,在网站收录方面需要考虑的问题也非常少,所以我一直采用这种方案。通过线上的观察,我们不难发现,Nginx作负载均衡器/反向代理也是相当稳定的,可以媲美硬件级的F5了,相信这也是越来越多的朋友喜欢它的原因之一。Nginx+Keepalived用于生产环境的优势还是很多的,不过由于其自身的限制,它目前只应用于Web集群环境;如果大家的网站或项目有这种需求,不妨考虑应用一下。