首页 > 技术文章 > Nginx反向代理与负载均衡应用实践(一)

ywb123 2019-07-09 14:30 原文

Nginx反向代理与负载均衡应用实践(一)

链接:https://pan.baidu.com/s/1xB20bnuanh0Avs4kwRpSXQ
提取码:migq
复制这段内容后打开百度网盘手机App,操作更方便哦

第4,5,小节为重点范例

1.集群简介

集群就是指一组(若干个)相互独立的计算机,利用高速通信网络组成的一个较大的计算机服务系统,每个集群节点(即集群中的每台计算机)都是运行各自服务的独立服务器。这些服务器之间可以彼此通信,协同向用户提供应用程序,系统资源和数据,并以单一系统的模式加以管理。当用户客户机请求集群系统时,集群给用户的感觉就是一个单一独立的服务器,而实际上用户请求的是一组集群服务器。

2.为什么要使用集群

2.1高性能

一些国家重要的计算密集型应用(如天气预报,核试验模拟等),需要计算机有很强的运算处理能力。以全世界现有的技术,即使是大型机,其计算能力也是有限的,很难单独完成此任务。因为计算时间可能会相当长,也许几天,甚至几年或更久。因此,对于这类复杂的计算业务,便使用了计算机集群技术,集中几十上百台,甚至成千上万台计算机进行计算。

image_1clt4m40f8deb2b1mfbdsmq6lv.png-342.2kB

假如你配一个LNMP环境,每次只需要服务10个并发请求,那么单台服务器一定会比多个服务器集群要快。只有当并发或总请求数量超过单台服务器的承受能力时,服务器集群才会体现出优势。

2.2价格有效性

通常一套系统集群架构,只需要几台或数十台服务器主机即可。与动辄价值上百万元的专用超级计算机相比便宜了很多。在达到同样性能需求的条件下,采用计算机集群架构比采用同等运算能力的大型计算机具有更高的性价比

2.3可伸缩性

  • 当服务负载,压力增长时,针对集群系统进行较简单的扩展即可满足需求,且不会降低服务质量。
  • 通常情况下,硬件设备若想扩展性能,不得不增加新的CPU和存储器设备,如果加不上去了,就不得不够买更高性能的服务器,就拿我们现在的服务器来讲,可以增加的设备总是有限的。如果采用集群技术,则只需要将新的单个服务器加入现有集群架构中即可,从访问的客户角度来看,系统服务无论是连续性还是性能上都几乎没有变化,系统在不知不觉中完成了升级,加大了访问能力,轻松地实现了扩展。集群系统中的节点数目可以增长到几千乃至上万个,其伸缩性远超过单台超级计算机。

2.4高可用性

  • 单一的计算机系统总会面临设备损毁的问题,如CPU,内存,主板,电源,硬盘等,只要一个部件坏掉,这个计算机系统就可能会宕机,无法正常提供服务。在集群系统中,尽管部分硬件和软件也还是会发生故障,但整个系统的服务可以是7*24小时可用的。
  • 集群架构技术可以使得系统在若干硬件设备故障发生时仍可以继续工作,这样就将系统的停机时间减少到了最小。集群系统在提高系统可靠性的同时,也大大减小了系统故障带来的业务损失,目前几乎100%的互联网网站都要求7*24小时提供服务。

2.5透明性

多个独立计算机组成的松耦合集群系统构成一个虚拟服务器。用户或客户端程序访问集群系统时,就像访问一台高性能,高可用的服务器一样,集群中一部分服务器的上线,下线不会中断整个系统服务,这对用户也是透明的。

2.6可管理性

整个系统可能在物理上很大,但其实容易管理,就像管理一个单一映像系统一样。在理想状况下,软硬件模块的插入能做到即插即用。

2.7可编程性

在集群系统上,容易开发及修改各类应用程序。

3.集群的常见分类

3.1计算机集群架构按功能和结构可以分成以下几类:

  • 负载均衡集群,简称LBC或者LB
  • 高可用性集群,简称HAC
  • 高性能计算集群,简称HPC
  • 网格计算集群

3.2不同种类的集群介绍

3.2.1负载均衡集群

  • 负载均衡集群为企业提供了更为实用,性价比更高的系统架构解决方案。负载均衡集群可以把很多客户集中的访问请求负载压力尽可能平均地分摊在计算机集群中处理。客户访问请求负载通常包括应用程序处理负载和网络流量负载。这样的系统非常适合使用同一组应用程序为大量用户提供服务的模式,每个节点都可以承担一定的访问请求负载压力,并且可以实现访问请求在各节点之间动态分配,以实现负载均衡。
  • 负载均衡集群运行时,一般是通过一个或多个前端负载均衡器将客户访问请求分发到后端的一组服务器上,从而达到整个系统的高性能和高可用性。一般高可用性集群和负载均衡集群会使用类似的技术,或同时具有高可用性与负载均衡的特点。

负载均衡集群的作用为:

  • 分摊用户访问请求及数据流量(负载均衡)
  • 保持业务连续性,即7*24小时服务(高可用性)。
  • 应用于Web业务及数据库从库等服务器的业务

负载均衡集群典型的开源软件包括LVS,Nginx,Haproxy等。如下图所示:

image_1clt5acu96id13bnmiu1bqe1me3c.png-221kB

提示:不同的业务会有若干秒的切换时间,DB业务明显长于Web业务切换时间。

3.2.2高可用性集群

一般是指在集群中任意一个节点失效的情况下,该节点上的所有任务会自动转移到其他正常的节点上。此过程并不影响整个集群的运行。

  • 当集群中的一个节点系统发生故障时,运行着的集群服务会迅速作出反应,将该系统的服务分配到集群中其他正在工作的系统上运行。考虑到计算机硬件和软件的容错性,高可用性集群的主要目的是使集群的整体服务尽可能可用。如果高可用性集群中的主节点发生了故障,那么这段时间内将由备节点代替它。备节点通常是主节点的镜像。当它代替主节点时,它可以完全接管主节点(包括IP地址及其他资源)提供服务,因此,使集群系统环境对于用户来说是一致的,既不会影响用户的访问。
  • 高可用性集群使服务器系统的运行速度和响应速度会尽可能的快。他们经常利用在多台机器上运行的冗余节点和服务来相互跟踪。如果某个节点失败,它的替补者将在几秒钟或更短时间内接管它的职责。因此,对于用户而言,集群里的任意一台机器宕机,业务都不会受影响(理论情况下)。

高可用性集群的作用为:

  • 当一台机器宕机时,另外一台机器接管宕机的机器的IP资源和服务资源,提供服务。
  • 常用于不易实现负载均衡的应用,比如负载均衡器,主数据库,主存储对之间。

高可用性集群常用的开源软件包括Keepalived,Heartbeat等,其架构图如下图所示:
image_1clt5gt64i0i7f0agk156f1n7i3p.png-222.8kB

3.2.3高性能计算集群

高性能计算集群也称并行计算。通常,高性能计算集群涉及为集群开发的并行应用程序,以解决复杂的科学问题(天气预报,石油勘探,核反应模拟等)。高性能计算集群对外就好像一个超级计算机,这种超级计算机内部由数十至上万个独立服务器组成,并且在公共消息传递层上进行通信以运行并行应用程序。在生产环境中实际就是把任务切成蛋糕,然后下发到集群节点计算,计算后返回结果,然后继续领新任务计算,如此往复。

3.2.4网格计算集群

略。。。


特别提示:在互联网网站运维中,比较常用的就是负载均衡集群和高可用性集群

4.快速实践Nginx负载均衡环境准备

下图是快速实践Nginx负载均衡的逻辑架构图

image.png-45.1kB

在上图中,所有用户的请求统一发送到Nginx负载均衡器,然后由负载均衡器根据调度算法来请求Web01和Web02

4.1软硬件准备

4.1.1硬件准备

准备3台VM虚拟机(有物理服务器更佳),一台做负载均衡,两台做RS,如下表:

HOSTNAME IP 说明
lb 192.168.200.64 Nginx负载均衡器
web01 192.168.200.63 Web01服务器
web02 192.168.200.60 Web02服务器

4.1.2软件准备

  • 系统:CentOS6.5 x86_64
  • 软件:nginx-1.10.2.tar.gz

4.2安装Nginx软件

下面将在以上3台服务器上安装Nginx.

[root@lb /]# yum install -y pcre-devel openssl-devel gcc gcc-c++ make curl
[root@lb /]# useradd -s /sbin/nologin -M www
[root@lb yang]# tar xf nginx-1.10.2.tar.gz -C /usr/src/
[root@lb yang]# cd /usr/src/nginx-1.10.2/
[root@lb nginx-1.10.2]# ./configure --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module
以下省略。。。
[root@lbx nginx-1.10.2]# make && make install
以下省略。。。
[root@lb nginx-1.10.2]# ln -s /usr/local/nginx/sbin/* /usr/local/sbin/
[root@lb nginx-1.10.2]# /usr/local/nginx/sbin/nginx

4.3配置用于测试的(两台)Web服务

将在两台NginxWeb服务器的节点上操作:配置并查看Web服务器的配置结果

[root@web01 conf]# pwd
/usr/local/nginx/conf
[root@web01 conf]# cat nginx.conf
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    log_format main '$remote_addr-$remote_user[$time_local]"$request"'
    '$status $body_bytes_sent "$http_referer"'
    '"$http_user_agent""$http_x_forwarded_for"';
    server {
        listen       80;
        server_name  bbs.yunjisuan.com;
        location / {
            root   html/bbs;
            index  index.html index.htm;
        }
    access_log logs/access_bbs.log main;
    }
    server {
        listen       80;
        server_name  www.yunjisuan.com;
        location / {
            root   html/www;
            index  index.html index.htm;
        }
    access_log logs/access_www.log main;
    }
}
#提示:这里故意将www虚拟主机放在下面,便于用后面的参数配置测试效果

4.4配置完成后检查语法,启动Nginx服务并关闭防火墙(两台Web)

[root@web01 conf]# /usr/local/nginx/sbin/nginx
[root@web01 conf]# service iptables stop
iptables: Setting chains to policy ACCEPT: filter          [  OK  ]
iptables: Flushing firewall rules:                         [  OK  ]
iptables: Unloading modules:                               [  OK  ]
[root@web01 conf]# netstat -antup | grep nginx
tcp   0    0 0.0.0.0:80    0.0.0.0:*   LISTEN      1238/nginx

4.5然后填充测试文件数据(两台Web),如下:

[root@web01 conf]# mkdir /usr/local/nginx/html/{www,bbs}
[root@web01 conf]# echo "`hostname -I `www" >> /usr/local/nginx/html/www/index.html
[root@web01 conf]# cat /usr/local/nginx/html/www/index.html
192.168.200.63 www
[root@web01 conf]# echo "`hostname -I `bbs" >> /usr/local/nginx/html/bbs/index.html
[root@web01 conf]# cat /usr/local/nginx/html/bbs/index.html
192.168.200.63 bbs

4.6配置解析两台Web的IP和主机名后,用curl测试一下

4.6.1 Web01

[root@web01 conf]# tail -2 /etc/hosts
192.168.200.63 www.yunjisuan.com
192.168.200.63 bbs.yunjisuan.com
[root@web01 conf]# which curl
/usr/bin/curl
[root@web01 conf]# curl www.yunjisuan.com
192.168.200.63 www
[root@web01 conf]# curl bbs.yunjisuan.com
192.168.200.63 bbs

4.6.2 Web02

[root@web02 conf]# tail -2 /etc/hosts
192.168.200.63 www.yunjisuan.com
192.168.200.63 bbs.yunjisuan.com
[root@web02 conf]# which curl
/usr/bin/curl
[root@web02 conf]# curl www.yunjisuan.com
192.168.200.63 www
[root@web02 conf]# curl bbs.yunjisuan.com
192.168.200.63 bbs

提示:

  • 不同Web测试节点,返回的结果是不同的,这是为了方便测试演示!
  • 通过上面配置就实现了两台Web服务器基于域名的虚拟主机配置。

4.7实现一个简单的负载均衡

4.7.1配置环境

HOSTNAME IP 说明
lb 192.168.200.64 Nginx负载均衡器

4.7.2进行一个简单的Nginx负载均衡配置

代理www.yunjisuan.com服务,节点为Web01和Web02.nginx.conf配置文件内容如下:

[root@lb conf]# pwd
/usr/local/nginx/conf
[root@lb conf]# cat nginx.conf
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    upstream www_server_pools {        #这里定义Web服务器池,包含了63,60两个Web节点  
    server 192.168.200.63:80 weight=1;    #这里代表1:1
    server 192.168.200.60:80 weight=1;    #这里代表1:1
    }

    server {             #这里定义代理的负载均衡域名虚拟主机
        listen       80;
        server_name  www.yunjisuan.com;
        location / {
        proxy_pass http://www_server_pools;  #访问www.yunjisuan.com,请求发送给www_server_pools里面的节点
        }
    }
}

4.7.3检查语法,启动Nginx服务并关闭防火墙

[root@lb conf]# /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@lb conf]# /usr/local/nginx/sbin/nginx
[root@lb conf]# service iptables stop
iptables: Setting chains to policy ACCEPT: filter          [  OK  ]
iptables: Flushing firewall rules:                         [  OK  ]
iptables: Unloading modules:                               [  OK  ]
[root@lb conf]# netstat -antup | grep nginx
tcp       0      0 0.0.0.0:80     0.0.0.0:*    LISTEN    1281/nginx

4.7.4检查负载均衡测试结果,Linux作为客户端的测试结果如下:

[root@lb ~]# tail -1 /etc/hosts
192.168.200.64 www.yunjisuan.com
[root@lb ~]# hostname -I
192.168.200.64              #这里是lb负载均衡器IP
[root@lb ~]# which curl
/usr/bin/curl
-------------------------------------------------------------------
[root@lb ~]# curl www.yunjisuan.com
192.168.200.63 bbs          #可以看出两个Web节点按照1:1的比例被访问.
[root@lb ~]# curl www.yunjisuan.com
192.168.200.60 bbs          #可以看出两个Web节点按照1:1的比例被访问.
[root@lb ~]# curl www.yunjisuan.com
192.168.200.63 bbs
[root@lb ~]# curl www.yunjisuan.com
192.168.200.60 bbs
[root@lb ~]# curl www.yunjisuan.com
192.168.200.63 bbs
[root@lb ~]# curl www.yunjisuan.com
192.168.200.60 bbs

4.7.5下面宕掉任意一个Web节点

[root@web01 ~]# /usr/local/nginx/sbin/nginx -s stop  #宕掉任意一个Web节点
-------------------------------------------------------------------
[root@lb ~]# curl www.yunjisuan.com
192.168.200.60 bbs
#可以看出网站业务不受影响,访问请求都定位到了正常的节点上.
[root@lb ~]# curl www.yunjisuan.com
192.168.200.60 bbs
[root@lb ~]# curl www.yunjisuan.com
192.168.200.60 bbs

4.7.6宕掉所有Web节点

[root@web01 ~]# /usr/local/nginx/sbin/nginx -s stop 
[root@web02 ~]# /usr/local/nginx/sbin/nginx -s stop
#宕掉所有Web节点
-------------------------------------------------------------------
[root@lb ~]# curl www.yunjisuan.com    #可以看到Nginx代理下面没有节点了,因此Nginx向用户报告了502错误
<html>
<head><title>502 Bad Gateway</title></head>
<body bgcolor="white">
<center><h1>502 Bad Gateway</h1></center>
<hr><center>nginx/1.10.2</center>
</body>
</html>
[root@lb ~]# curl www.yunjisuan.com
<html>
<head><title>502 Bad Gateway</title></head>
<body bgcolor="white">
<center><h1>502 Bad Gateway</h1></center>
<hr><center>nginx/1.10.2</center>
</body>
</html>

4.7.7现在开启所有Web节点

[root@web01 ~]# /usr/local/nginx/sbin/nginx
[root@web02 ~]# /usr/local/nginx/sbin/nginx
-------------------------------------------------------------------
[root@lb ~]# curl www.yunjisuan.com
192.168.200.60 bbs     
#结果是Nginx又把请求一比一分配到了Nginx后面的节点上
[root@lb ~]# curl www.yunjisuan.com
192.168.200.63 bbs
#结果是Nginx又把请求一比一分配到了Nginx后面的节点上
[root@lb ~]# curl www.yunjisuan.com
192.168.200.60 bbs
[root@lb ~]# curl www.yunjisuan.com
192.168.200.63 bbs
[root@lb ~]# curl www.yunjisuan.com
192.168.200.60 bbs
[root@lb ~]# curl www.yunjisuan.com
192.168.200.63 bbs

从测试结果可以看出,已经实现了反向代理,负载均衡功能,但是有一个特殊问题,出来的结果并不是带有www的字符串,而是bbs的字符串,根据访问结果,我们推测是访问了Web节点下bbs的虚拟主机,明明代理的是www虚拟主机,为什么结果是访问了后端的bbs虚拟主机了呢?问题又该如何解决?

4.8使访问的结果和访问的域名就完全对应上

4.8.1查看负载均衡服务器配置文件

[root@lb conf]# pwd
/usr/local/nginx/conf
[root@lb conf]# cat nginx.conf
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    upstream www_server_pools {          
    server 192.168.200.63:80 weight=1;    
    server 192.168.200.60:80 weight=1;    
    }

    server {             
        listen       80;
        server_name  www.yunjisuan.com;
        location / {
        proxy_pass http://www_server_pools;
	    proxy_set_header host $host;       #在代理向后端服务器发送的http请求头中加入host字段信息,用于当后端服务器配置有多个虚拟主机时,可以识别代理的是哪个虚拟主机。这是节点服务器多虚拟主机时的关键配置
        }
    }
}

4.8.2重启服务

[root@lb conf]# /usr/local/nginx/sbin/nginx -s reload

4.8.3检查负载均衡测试结果,Linux作为客户端的测试结果如下:

[root@lb conf]# curl www.yunjisuan.com
192.168.200.63 www   #可以看到访问结果和访问的域名已经完全对应上了
[root@lb conf]# curl www.yunjisuan.com
192.168.200.60 www
[root@lb conf]# curl www.yunjisuan.com
192.168.200.63 www
[root@lb conf]# curl www.yunjisuan.com
192.168.200.60 www
[root@lb conf]# curl www.yunjisuan.com
192.168.200.63 www
[root@lb conf]# curl www.yunjisuan.com
192.168.200.60 www

4.9经过反向代理后的节点服务器记录用户IP

4.9.1修改负载均衡配置文件

[root@lb conf]# pwd
/usr/local/nginx/conf
[root@lb conf]# cat nginx.conf
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    upstream www_server_pools {          
    server 192.168.200.63:80 weight=1;    
    server 192.168.200.60:80 weight=1;    
    }

    server {             
        listen       80;
        server_name  www.yunjisuan.com;
        location / {
        proxy_pass http://www_server_pools;
	    proxy_set_header host $host;  
	     	proxy_set_header X-Forwarded-For $remote_addr;
	     	    #在代理向后端服务器发送的http请求头中加入X-Forwarded-For字段信息,用于后端服务器程序,日志等接收记录真实用户的IP,而不是代理服务器的IP
        }
    }
}

[root@lb conf]# /usr/local/nginx/sbin/nginx -s reload             #重启Nginx服务

4.9.2修改web01与web02的配置文件

[root@web01 conf]# pwd
/usr/local/nginx/conf
[root@web01 conf]# cat nginx.conf
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
log_format main '$remote_addr-$remote_user[$time_local]"$request"'
    '$status $body_bytes_sent "$http_referer"'
    '"$http_user_agent""$http_x_forwarded_for"';
#就是这里的“$http_x_forwarded_for”参数,如果希望在第一行显示,可以替换掉第一行的$remote_addr变量。
    server {
        listen       80;
        server_name  bbs.yunjisuan.com;
        location / {
            root   html/bbs;
            index  index.html index.htm;
        }
    access_log logs/access_bbs.log main;   #启动日志
    }
    server {
        listen       80;
        server_name  www.yunjisuan.com;
        location / {
            root   html/www;
            index  index.html index.htm;
        }
    access_log logs/access_www.log main;   #启动日志
    }
}

[root@web01 conf]# /usr/local/nginx/sbin/nginx -s reload
#重启Nginx服务

以上注释详解:

log_format main   #让日志记录字段的顺序按照我想的来
'$remote_addr     #来源IP
-$remote_user     #来源用户名
[$time_local]     #时间
"$request"'       #请求
'$status          #状态码
$body_bytes_sent             #主体发送的大小
"$http_referer"'             #来源的浏览器
'"$http_user_agent"          #用户的客户端
"$http_x_forwarded_for"';    #客户IP

4.9.3映射到pc电脑文件,使用电脑原始浏览器访问

image_1cm4ibd7c193h1occ19ejc5n9i19.png-8.5kB
image_1cm4ic3cv900129njvn2v21v8rm.png-8.4kB

4.9.4检查web日志文件

[root@web01 logs]# cat access_www.log | tail -2
192.168.200.64--[30/Aug/2018:20:44:10 +0800]"GET / HTTP/1.0"200 19 "-""Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko""192.168.200.1"
192.168.200.64--[30/Aug/2018:20:44:46 +0800]"GET / HTTP/1.0"200 19 "-""Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko""192.168.200.1"
  • 由上可知日志里的192.168.200.64为反向代理的IP,对应Nginx日志格式里的
    remote_addr变量,而日志结尾的192.168.200.1对应的时日志格式里的http_x_forwarded_for变量,即接收了前面反向代理配置中“proxy_set_header X-Forwarded-For $remote_addr;”参数X-Forwarded-For的IP了。
  • 关于X-Forwarded-For的详细说明,可见http://en.wikipedia.org/wiki/X-Forwwawrded-For。下列是反向代理相关重要基础参数的总结,仅供参考。
Nginx反向代理重要参数 解释说明
proxy_pass http://server_pools; 通过proxy_pass功能把用户的请求转向到反向代理定义的upstream服务器池
proxy_set_header Host $host; 在代理向后端服务器发送的http请求头中加人host字段信息,用于当后端服务器配置有多个虚拟主机时,可以识别代理的是哪个虚拟主机。这是节点服务器多虚拟主机时的关键配置
proxy_set_header X-Forwarded-For Sremote_addr; 在代理向后端服务器发送的http请求头中加人X-Forwarded-For字段信息,用于后端服务器程序、日志等接收记录真实用户的IP,而不是代理服务器的IP。这是反向代理时,节点服务器获取用户真实IP的必要功能配置

4.10与反向代理配置相关的更多参数说明

由于参数众多,最好把这些参数放到一个配置文件里,然后用include方式包含到虚拟主机配置里,效果如下:

4.10.1查看反向代理主配置文件

[root@lb conf]# pwd
/usr/local/nginx/conf
[root@lb conf]# cat nginx.conf
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    upstream www_server_pools {          
    server 192.168.200.63:80 weight=1;    
    server 192.168.200.60:80 weight=1;    
    }

    server {             
        listen       80;
        server_name  www.yunjisuan.com;
        location / {
        proxy_pass http://www_server_pools;
    	include extar/proxy.conf;   #文件导入(导入的就是下文的副配置文件)
        }
    }
}

4.10.2查看反向代理副配置文件

[root@lb extar]# pwd
/usr/local/nginx/conf/extar
[root@lb extar]# cat proxy.conf 
proxy_set_header host $host;
proxy_set_header x-forwarded-for $remote_addr;
proxy_connect_timeout 60;
proxy_send_timeout 60;
proxy_read_timeout 60;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;

5. upstream模块

5.1upstream模块语法

5.1.1基本的upstream配置案例

upstream www_server_pools {
#upstream是关键字必须有,后面的www_server_pools为一个Upstream集群组的名字,可以自己起名,调用时就用这个名字
server 192.168.200.63:80 weight=5;
server 192.168.200.60:80 weight=10;
#server关键字是固定的,后面可以接域名(客户会用)或IP。如果不指定端口,默认是80端口。weight代表权重,数值越大被分配的请求越多,结尾有分号,比例为1:2
}

5.1.2较完整的upstream配置案例

upstream blog_server_pool {
server 192.168.200.63;   #这行标签和下行是等价的
server 192.168.200.60:80 weight=1 max_fails=1 fail_timeout=10s; #这行标签和上一行是等价的,此行多余的部分就是默认配置,不写也可以。
server 192.168.0.225:80 weight=1 max_fails=2 fail_timeout=20s backup;
#server最后面可以加很多参数,具体参数作用看下文的表格
}

5.1.3使用域名及socket的upstream配置案例

upstream backend {
server backend1.example.com weight=5;
server backend2.example.com:8080;   #域名加端口,转发到后端的指定端口上
server unix:/tmp/backend3;          #指定socket文件
#提示:server后面如果接域名,需要内网有DNS服务器或者在负载均衡器的hosts文件做域名解析。
server 192.168.0.223;
server 192.168.0.224:8080;
server backup1.example.com:8080 backup;
#备份服务器,等上面指定的服务器都不可访问的时候会启动,backup的用法和Haproxy中用法一样
server backup2.example.com:8080 backup;
}

如果是两台Web服务器做高可用,常规方案就需要keepalived配合,那么这里使用Nginx的backup参数通过负载均衡功能就可以实现Web服务器集群了,对于企业应用来说,能做集群就不做高可用

5.2upstream模块相关说明

upstream模块内参数 参数说明
server 10.0.10.8:80 负载均衡后面的RS配置, 可以是IP或域名, 如果端口不写,默认是80端口。高并发场景下,IP可换成域名,通过DNS做负载均衡
weight= 1 代表服务器的权重,默认值是1。权重数字越大表示接受的请求比例越大
max_ fails=1 Nginx尝试连接后端主机失败的次数,这个数值是配合proxy_ next_ upstream,fastcgi_ next_ upstream和memcached_ next _upstream 这三个参数来使用的,当Nginx接收后端服务器返回这三个参数定义的状态码时,会将这个请求转发给正常工作的后端服务器,例如404,502,503.Max_fails的默认值是1;企业场景下建议2~3次。如京东1次,蓝汛10次,根据业务需求去配置
backup 热备配置(RS节点的高可用),当前面激活的RS都失败后会自动启用热备RS。这标志着这个服务器作为备份服务器,若主服务器全部宕机了,就会向它转发请求;注意,当负载调度算法为ip_hash时,后端服务器在负载均衡调度中的状态不能是weight和backup
fail_timeout=10s 在max_fails定义的失败次数后,距离下次检查的间隔时间,默认是10s ; 如果max_fails是5,它就检测5次,如果5次都是502。那么,它就会根据fail_timeout的值,等待10s再去检查,还是只检查一次,如果持续502,在不重新加载Nginx配置的情况下,每隔10s都只检测一次。常规业务2~3秒比较合理,比如京东3秒,蓝汛3秒,可根据业务需求去配置
down 这标志着服务器永远不可用,这个参数可配合ip_hash使用

提示:以上参数与专业的Haproxy参数很类似,但不如Haproxy的参数易懂.

5.3简单示例如下

upstream backend {
server backend1.example.com weight=5;       #如果就是单个Server,没必要设置权重
server 127.0.0.1:8080 max_fail=5 fail_timeout=10s;
#当检测次数等于5的时候,5次连续检测失败后,间隔10s再重新检测。
server unix:/tmp/backend3;
server backup1.example.com:8080 backup;     #热备机器设置
}

5.4如果是Nginx代理Cache服务,可能需要使用hash算法,此时若宕机,可通过设置down参数确保客户端用户按照当前的hash算法访问

upstream backend {
ip_hash;
server backend1.example.com;
server backend2.example.com;
server backend3.example.com down;   #末尾加个down代表不可用
server backend4.example.com;
}

5.5下面是Haproxy负载均衡器server标签的配置示例

#开启对后端服务器的健康检测,通过GET /test/index.php来判断后端服务器的健康情况
server php_server_1 192.168.0.223:80 cookie 1 check inter 2000 rise 3 fall 3 weight 2
server php_server_2 192.168.0.224:80 cookie 2 check inter 2000 rise 3 fall 3 weight 1
server php_server_bak 192.168.0.225:80 cookie 3 check inter 1500 rise 3 fall 3 backup

上述命令的说明如下:

  • weight:调节服务器的请求分配权重。
  • check:开启对该服务器健康检查。
  • inter:设置连续两次的健康检查间隔时间,单位毫秒,默认值2000
  • rise:指定多少次连续成功的健康检查后,即可认定该服务器处于可用状态。
  • fall:指定多少次不成功的健康检查后,即认为服务器为宕机状态,默认值3.
  • maxconn:指定可被发送到该服务器的最大并发连接数。

5.6upstream模块调度算法

5.6.1调度算法一般分为两类:

  • 第一类为静态调度算法,即负载均衡器根据自身设定的规则进行分配,不需要考虑后端节点服务器的情况,例如:rr,wrr,ip_hash等都属于静态调度算法。
  • 第二类为动态调度算法,即负载均衡器会根据后端节点的当前状态来决定是否分发请求,例如:连接数少的优先获得请求,响应时间短的优先获得请求。例如:least_conn,fair等都属于动态调度算法

5.6.2下面介绍一下常见的调度算法。

rr轮询(默认调度算法,静态调度算法)

  • 按客户端请求顺序把客户端的请求逐一分配到不同的后端节点服务器,这相当于LVS中的rr算法,如果后端节点服务器宕机(默认情况下Nginx只检测80端口),宕机的服务器会被自动从节点服务器池中剔除,以使客户端的用户访问不受影响。新的请求会分配给正常的服务器。

wrr(权重轮询,静态调度算法)

  • 在rr轮询算法的基础上加上权重,即为权重轮询算法,当使用该算法时,权重和用户访问成正比,权重值越大,被转发的请求也就越多。可以根据服务器的配置和性能指定权重值大小,有效解决新旧服务器性能不均带来的请求分配问题。

ip_hash(静态调度算法)(会话保持)

  • 每个请求按客户端IP的hash结果分配,当新的请求到达时,先将其客户端IP通过哈希算法哈希出一个值,在随后的客户端请求中,客户IP的哈希值只要相同,就会被分配至同一台服务器,该调度算法可以解决动态网页的session共享问题,但有时会导致请求分配不均,即无法保证1:1的负载均衡,因为在国内大多数公司都是NAT上网模式,多个客户端会对应一个外部IP,所以,这些客户端都会被分配到同一节点服务器,从而导致请求分配不均。LVS负载均衡的-p参数,Keepalived配置里的persistence_timeout 50参数都类似这个Nginx里的ip_hash参数,其功能都可以解决动态网页的session共享问题。

我们来看一个示例,如下:

upstream yunjisuan_lb{
ip_hash;
server 192.168.0.223:80;
server 192.168.0.224:8080;
}
upstream backend{
ip_hash;
server backend1.example.com;
server backend2.example.com;
server backend3.example.com down;
server backend4.example.com;
}

注意:当负载调度算法为ip_hash时,后端服务器在负载均衡调度中的状态不能有weight和backup,即使有也不会生效。


fair(动态调度算法)

  • 此算法会根据后端节点服务器的响应时间来分配请求,响应时间短的优先分配。这是更加智能的调度算法。此种算法可以根据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间来分配请求,响应时间短的优先分配。Nginx本身不支持fair调度算法,如果需要使用这种调度算法,必须下载Nginx相关模块upstream_fair。

示例如下:

upstream yunjisuan_lb{
server 192.168.0.223;
server 192.168.0.224;
fair;
}

least_conn

  • least_conn算法会根据后端节点的连接数来决定分配情况,哪个机器连接数少就分发。

url_hash算法(web缓存节点)

  • 与ip_hash类似,这里是根据访问URL的hash结果来分配请求的,让每个URL定向到同一个后端服务器,后端服务器为缓存服务器时效果显著。在upstream中加入hash语句,server语句中不能写入weight等其他的参数,hash_method使用的是hash算法。
  • url_hash按访问URL的hash结果来分配请求,使每个URL定向到同一个后端服务器,可以进一步提高后端缓存服务器的效率命令率。Nginx本身是不支持url_hash的,如果需要使用这种调度算法,必须安装Nginx的hash模块软件包。

url_hash(web缓存节点)和ip_hash(会话保持)类似。示例配置如下:

upstream yunjisuan_lb {
server squid1:3128;
server squid2:3128;
hash $request_uri;
hash_method crc32;
}

一致性hash算法

  • 一致性hash算法一般用于代理后端业务为缓存服务(如Squid,Memcached)的场景,通过将用户请求的URI或者指定字符串进行计算,然后调度到后端的服务器上,此后任何用户查找同一个URI或者指定字符串都会被调度到这一台服务器上,因此后端的每个节点缓存的内容都是不同的,一致性hash算法可以解决后端某个或几个节点宕机后,缓存的数据动荡最小,一致性hash算法知识比较复杂,详细内容可以参考百度上的相关资料,这里仅仅给出配置示例:
http {
upstream test {
consistent_hash $request_uri;
server 127.0.0.1:9001 id=1001 weight=3;
server 127.0.0.1:9002 id=1002 weight=10;
server 127.0.0.1:9003 id=1003 weight=20;
}
}

虽然Nginx本身不支持一致性hash算法,但Nginx得分支Tengine支持。详细可参考http://tengine.taobao.org/document_cn/http_upstream_consistent_hash_cn.html

6. http_proxy_module模块

6.1proxy_pass指令介绍

proxy_pass指令属于ngx_http_proxy_module模块,此模块可以将请求转发到另一台服务器,在实际的反向代理工作中,会通过location功能匹配指定的URI,然后把接收到的符合匹配URI的请求通过proxy_pass抛给定义好的upstream节点池。该指令官方地址1见:http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass

6.2下面proxy_pass的使用案例:

6.2.1URI为name的请求抛给http://127.0.0.1/remote/.

location /name/ {
proxy_pass http://127.0.0.1/remote/;
}

6.2.2将匹配URI为some/path的请求抛给http://127.0.0.1

location /some/path/ {
proxy_pass http://127.0.0.1;
}

6.2.3将匹配URI为name的请求应用指定的rewrite规则,然后抛给http://127.0.0.1

location /name/ {
rewrite /name/( [^/]+ )  /username=$1 break;
proxy_pass http://127.0.0.1;
}

6.3http proxy模块参数

Nginx的代理功能是通过http proxy模块来实现的。默认在安装Nginx时已经安装了http proxy模块,因此可直接使用http proxy模块.

http proxy模块相关参数 说明
proxy_set_header 设置http请求header项传给后端服务器节点,例如:可实现让代理后端的服务器节点获取访问客户端用户的真实IP地址
client_body_buffer_size 用于指定客户端请求主体缓冲区大小,此处如了解前文的http请求包的原理就好理解了
proxy_connect_timeout 表示反向代理与后端节点服务器连接的超时时间,即发起握手等候响应的超时时间
proxy_send_timeout 表示代理后端服务器的数据回传时间,即在规定时间之内后端服务器必须传完所有的数据,否则,Nginx 将断开这个连接
proxy_read_timeout 设置Nginx从代理的后端服务器获取信息的时间,表示连接建立成功后,Nginx等待后端服务器的响应时间,其实是Nginx已经进人后端的排队之中等候处理的时间
proxy_buffer_size 设置缓冲区大小,默认该缓冲区大小等于指令proxy_ buffers 设置的大小
proxy_buffers 设置缓冲区的数量和大小。Nginx从代理的后端服务器获取的响应信息,会放置到缓冲区
roxy_busy_buffers_size 用于设置系统很忙时可以使用的proxy_buffers大小,官方推荐的大小为proxy_ buffers*2
proxy_ temp_ file_ write_ size 指定proxy缓存临时文件的大小