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

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

课堂笔记html


 

1、原理

 

1.1 为何要使用集群

(1)高性能前端

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

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

(2)价格有效性算法

一般一套系统集群架构,只须要几台或数十台服务器主机便可。与动辄价值上百万元的专用超级计算机相比便宜了不少。在达到一样性能需求的条件下,采用计算机集群架构比采用同等运算能力的大型计算机具备更高的性价比。 
早期的淘宝,支付宝的数据库等核心系统就是使用上百万元的小型机服务器。后因使用维护成本过高以及扩展设备费用成几何级数翻倍,甚至成为扩展瓶颈,人员维护也十分困难,最终使用PC服务器集群替换之,好比,把数据库系统从小机结合Oracle数据库迁移到MySQL开源数据库结合PC服务器上来。不但成本降低了,扩展和维护也更容易了。 
(3)可伸缩性
数据库

当服务负载,压力增加时,针对集群系统进行较简单的扩展便可知足需求,且不会下降服务质量。编程

一般状况下,硬件设备若想扩展性能,不得不增长新的CPU和存储器设备,若是加不上去了,就不得不够买更高性能的服务器,就拿咱们如今的服务器来说,能够增长的设备老是有限的。若是采用集群技术,则只须要将新的单个服务器加入现有集群架构中便可,从访问的客户角度来看,系统服务不管是连续性仍是性能上都几乎没有变化,系统在不知不觉中完成了升级,加大了访问能力,轻松地实现了扩展。集群系统中的节点数目能够增加到几千乃至上万个,其伸缩性远超过单台超级计算机。vim

(4)高可用性windows

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

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

(6)可管理性

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

(7)可编程性

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

 

1.二、集群的常见分类

计算机集群架构按功能和结构能够分红如下几类: 
一、负载均衡集群,简称LBC或者LB 
二、高可用性集群,简称HAC 
三、高性能计算集群,简称HPC 
四、网格计算集群 
五、负载均衡集群和高可用性集群是互联网行业经常使用的集群架构模式

 

1.三、不一样种类的集群介绍

一、负载均衡集群

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

(1)负载均衡集群的做用为:

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

负载均衡集群典型的开源软件包括LVS,Nginx,Haproxy等。以下图所示: 
image_1crs7rku611er1if91oqu1p2t4nh9.png-213.5kB

二、高可用性集群

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

高可用性集群的做用为: 
当一台机器宕机时,另一台机器接管宕机的机器的IP资源和服务资源,提供服务。 
经常使用于不易实现负载均衡的应用,好比负载均衡器,主数据库,主存储对之间。 
高可用性集群经常使用的开源软件包括Keepalived,Heartbeat等,其架构图以下图所示: 
image_1crs80p9u183vadkjrvd3p1dusm.png-214.9kB

三、高性能计算集群

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

在互联网网站运维中,比较经常使用的就是负载均衡集群和高可用性集群

 

1.四、LVS介绍

LVS是Linux Virtual Server的简写,意即Linux虚拟服务器,是一个虚拟的服务器集群系统。 
特色是:可伸缩网络服务的几种结构,它们都须要一个前端的负载调度器(或者多个进行主从备份)。咱们先分析实现虚拟网络服务的主要技术,指出IP负载均衡技术是在负载调度器的实现技术中效率最高的。在已有的IP负载均衡技术中,主要有经过网络地址转换(Network Address Translation)将一组服务器构成一个高性能的、高可用的虚拟服务器,咱们称之为VS/NAT技术(Virtual Server via Network Address Translation)。在分析VS/NAT的缺点和网络服务的非对称性的基础上,咱们提出了经过IP隧道实现虚拟服务器的方法VS/TUN (Virtual Server via IP Tunneling),和经过直接路由实现虚拟服务器的方法VS/DR(Virtual Server via Direct Routing),它们能够极大地提升系统的伸缩性。VS/NAT、VS/TUN和VS/DR技术是LVS集群中实现的三种IP负载均衡技术。

lvs是四层负载均衡,由于他工做在四层网络模型上,即为传输层。他不会执行tcp三次握手,他是经过转发用户请求来实现负载均衡,转发到后方的web服务器,用户是跟后面的web服务器执行的tcp三次握手。他支持极大的并发,效率及其高。数据统计基本能够实现30万并发。即为4层转发。

 

1.五、Nginx负载均衡集群介绍

一、搭建负载均衡服务的需求 
负载均衡集群提供了一种廉价,有效,透明的方法,来扩展网络设备和服务器的负载,带宽和吞吐量,同时增强了网络数据处理能力,提升了网络的灵活性和可用性。

搭建负载均衡服务的需求以下:

(1)把单台计算机没法承受的大规模并发访问或数据流量分担到多台节点设备上,分别进行处理,减小用户等待响应的时间,提高用户体验。 
(2)单个重负载的运算分担到多台节点设备上作并行处理,每一个节点设备处理结束后,将结果汇总,返回给用户,系统处理能力获得大幅度提升。 
(3)7*24小时的服务保证,任意一个或多个有限后面节点设备宕机,不能影响业务。

在负载均衡集群中,同组集群的全部计算机节点都应该提供相同的服务。集群负载均衡器会截获全部对该服务的入站请求。而后将这些请求尽量地平均地分配在全部集群节点上。

2 、Nginx负载均衡集群介绍

(1)反向代理与负载均衡概念简介

严格地说,Nginx仅仅是做为Nginx Proxy反向代理使用的,由于这个反向代理功能表现的效果是负载均衡集群的效果,因此本文称之为Nginx负载均衡。那么,反向代理和负载均衡有什么区别呢? 
普通负载均衡软件,例如大名鼎鼎的LVS,其实功能只是对请求数据包的转发(也可能会改写数据包),传递,其中DR模式明显的特征是从负载均衡下面的节点服务器来看,接收到的请求仍是来自访问负载均衡器的客户端的真实用户,而反向代理就不同了,反向代理接收访问用户的请求后,会代理用户从新发起请求代理下的节点服务器,最后把数据返回给客户端用户,在节点服务器看来,访问的节点服务器的客户端用户就是反向代理服务器了,而非真实的网站访问用户。 
一句话,LVS等的负载均衡是转发用户请求的数据包,而Nginx反向代理是接收用户的请求而后从新发起请求去请求其后面的节点。

Nginx是七层(反向代理)负载均衡器,他工做在第七层,即应用层。他发出去的包已经不是用户的包了,用户请求直接和反向代理执行的tcp3次握手。即为7层代理

(2)实现Nginx负载均衡的组件说明

实现Nginx负载均衡的组件主要有两个,以下表: 
image_1crs8g5qk1j0042q1mmb1k16lni13.png-49.6kB

 

2、快速实践Nginx负载均衡环境准备

image_1crs8hiqp1jnn1g6262crdgi2f1g.png-46.1kB

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

一、软硬件准备 
三台虚拟机,两台作web,一台作nginx,三台虚拟机都须要安装nginx

二、安装Nginx软件,命令以下

 
  1. yum install -y pcre-devel openssl-devel #用本地yum仓库安装依赖包
  2. wget -q http://nginx.org/download/nginx-1.10.2.tar.gz #下载软件源码包
  3. useradd -s /sbin/nologin -M www #建立程序用户
  4. tar xf nginx-1.10.2.tar.gz -C /usr/src/ #解压缩
  5. cd /usr/src/nginx-1.10.2
  6. ./configure --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module #预配置
  7. make && make install #编译和安装
  8. ln -s /usr/local/nginx/sbin/* /usr/local/sbin/ #给命令作软链接,以便PATH能找到
  9. /usr/local/nginx/sbin/nginx #启动nginx

加工Nginx配置文件

 
  1. cd /usr/local/nginx/conf
  2. egrep -v "#|^$" nginx.conf.default > nginx.conf
  3. /usr/local/nginx/sbin/nginx -s reload #平滑重启
  4. 以上Nginx就安装完成了。

三、配置用于测试的Web服务

 
  1. [root@Web conf]# cat nginx.conf
  2. worker_processes 1;
  3. events {
  4. worker_connections 1024;
  5. }
  6. http {
  7. include mime.types;
  8. default_type application/octet-stream;
  9. sendfile on;
  10. keepalive_timeout 65;
  11. log_format main '$remote_addr-$remote_user[$time_local]"$request"'
  12. '$status $body_bytes_sent "$http_referer"'
  13. '"$http_user_agent""$http_x_forwarded_for"'; #日志格式化
  14. server {
  15. listen 80;
  16. server_name bbs.mendermi.com;
  17. location / {
  18. root html/bbs;
  19. index index.html index.htm;
  20. }
  21. access_log logs/access_bbs.log main; #应用格式化
  22. }
  23. server {
  24. listen 80;
  25. server_name www.mendermi.com;
  26. location / {
  27. root html/www;
  28. index index.html index.htm;
  29. }
  30. access_log logs/access_www.log main;
  31. }
  32. }
  33. #提示:
  34. 这里故意将www虚拟主机放在下面,便于用后面的参数配置测试效果
  35. 配置文件在Web1里也写一份

配置完成后检查语法,并启动Nginx服务

 
  1. [root@Web conf]# nginx -t
  2. [root@Web conf]# /usr/local/nginx/sbin/nginx -s reload
  3. [root@Web conf]# netstat -antup | grep nginx
  4. tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 6760/nginx

而后填充测试文件数据,以下:

 
  1. [root@Web ~]# mkdir /usr/local/nginx/html/{www,bbs}
  2. [root@Web ~]# echo "`hostname -I `www" >> /usr/local/nginx/html/www/index.html
  3. [root@Web ~]# cat /usr/local/nginx/html/www/index.html
  4. 192.168.200.139 www
  5. [root@Web~]# echo "`hostname -I `bbs" >> /usr/local/nginx/html/bbs/index.html
  6. [root@Web ~]# cat /usr/local/nginx/html/bbs/index.html
  7. 192.168.200.139 bbs
  8. 以上一样的命令在Web1上也执行一遍

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

image_1crtoe2gbek7gdh1c171cq2gmi9.png-22.9kB

image_1crtofdhl111u1itn1vbg14p5bom.png-22.5kB

 

3、实现一个简单的负载均衡

本服务在nginx服务器操做

一、配置负载均衡,代理www.mendermi.com服务

 
  1. vim /usr/local/nginx/conf/nginx.conf
  2. worker_processes 1;
  3. events {
  4. worker_connections 1024;
  5. }
  6. http {
  7. include mime.types;
  8. default_type application/octet-stream;
  9. sendfile on;
  10. keepalive_timeout 65;
  11. upstream www_server_pools {
  12. server 192.168.200.135:80 weight=1;
  13. server 192.168.200.137:80 weight=1;
  14. }
  15. server {
  16. listen 80;
  17. server_name www.mendermi.com;
  18. location / {
  19. proxy_pass http://www_server_pools;
  20. }
  21. }
  22. }

image_1cru45j4jcp6172o14if1qb210m99.png-204.2kB

检查语法并启动

image_1crtpiotb14is7rkp0s1d5f165s20.png-12.8kB

检查负载均衡测试结果。Linux做为客户端的测试结果以下 
image_1crtpsnc25kf1qcaofeq436t92d.png-37.3kB

从上面的测试结果能够看出来。两个Web节点按照1:1的比例被访问。 下面宕掉任意一个Web节点,看看测试结果如何,测试以下:

例,关闭Web的nginx服务 
测试结果: 
image_1crtq66o61v251efj1p1u101pctn2q.png-31.2kB 
上图能够看到,网站业务不受影响,访问请求都定位到了正常的节点上。

例关闭全部Web的nginx服务 
测试结果: 
image_1crtr59sqc791eot1a2n16aai0r37.png-58.3kB 
上图能够看到,Nginx代理下面没有节点了,所以,Nginx向用户报告了502错误。

开启全部Web服务器的nginx服务 
测试结果: 
image_1crtrcjhr13hcso7vgu1inm1omj3k.png-27.3kB 
结果是Nginx又把请求一比一分配到了Nginx后面的节点上。

 

4、Nginx负载均衡核心组件介绍

 

1、Nginx upstream模块

1 、upstream模块介绍 
Nginx的负载均衡功能依赖于ngx_http_upsteam_module模块,所支持的代理方式包括proxy_pass,fastcgi_pass,memcached_pass等,新版Nginx软件支持的方式有所增长。咱们实验proxy_pass代理方式。 
ngx_http_upstream_module模块容许Nginx定义一组或多组节点服务器组,使用时能够经过proxy_pass代理方式把网站的请求发送到事先定义好的对应Upstream组的名字上,具体写法为“proxy_pass http:// www_server_pools”,其中www_server_pools就是一个Upstream节点服务器组名字。ngx_http_upstream_module模块官方地址为:http://nginx.org/en/docs/http/ngx_http_upstream_module.html

image_1cru5jl871980j8bigvq4458sm.png-64.9kB

image_1cru5k7fdtdftqh1kcr1meq1du313.png-70.3kB

二、upstream模块相关说明 
upstream模块的内容应放于nginx.conf配置的http{}标签内,其默认调度节点算法是wrr(weighted round-robin,即权重轮询)。下图为upstream模块内部server标签部分参数说明
image_1cru5m7l410bust5e7kk591ri81g.png-297.3kB

image_1cru5p9ca1lir49ec5t18vf7k81t.png-101.1kB

上述命令的说明以下:

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

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

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

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

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

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

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

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

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

image_1cru5thod1dhg1svg18pv18hes5d2a.png-29kB

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

(4)fair(动态调度算法)

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

示例以下: 
image_1cru9uao8s7d18qh1e2cr041d3b2n.png-7.6kB

(5)least_conn

least_conn算法会根据后端节点的链接数来决定分配状况,哪一个机器链接数少就分发。 
除了上面介绍的这些算法外,还有一些第三方调度算法,例如:url_hash,一致性hash算法等,介绍以下。

(6)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(会话保持)相似。示例配置以下: 
image_1crua1qh01evn1luu1rs8lui1c4g34.png-9.3kB

(7)一致性hash算法

一致性hash算法通常用于代理后端业务为缓存服务(如Squid,Memcached)的场景,经过将用户请求的URI或者指定字符串进行计算,而后调度到后端的服务器上,此后任何用户查找同一个URI或者指定字符串都会被调度到这一台服务器上,所以后端的每一个节点缓存的内容都是不一样的,一致性hash算法能够解决后端某个或几个节点宕机后,缓存的数据动荡最小,一致性hash算法知识比较复杂,详细内容能够参考百度上的相关资料,这里仅仅给出配置示

例: 
image_1crua35oc1c4m1tdi1dbu1ctr1l5m3h.png-15.9kB

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

 

2、 http_proxy_module模块

一、 proxy_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

image_1crubho08kfp1bps4631dfve4s4e.png-50.2kB

二、http proxy模块参数 
Nginx的代理功能是经过http proxy模块来实现的。默认在安装Nginx时已经安装了http proxy模块,所以可直接使用http proxy模块。下面详细解释模块1中每一个选项表明的含义,见下表:

image_1crubjcjtirrb711orh1sqk1h594r.png-250.1kB

 

5、Nginx负载均衡配置实战

 

1、Nginx负载均衡配置

  1. 查看nginx的配置文件以下:

    1. [root@nginx nginx]# cat /usr/local/nginx/conf/nginx.conf
    2. worker_processes 1;
    3. events {
    4. worker_connections 1024;
    5. }
    6. http {
    7. include mime.types;
    8. default_type application/octet-stream;
    9. sendfile on;
    10. keepalive_timeout 65;
    11. upstream www_server_pools {
    12. server 192.168.200.135:80 weight=1;
    13. server 192.168.200.137:80 weight=1;
    14. }
    15. server {
    16. listen 80;
    17. server_name www.mendermi.com;
    18. location / {
    19. proxy_pass http://www_server_pools;
    20. }
    21. }
    22. }

    image_1cs0ejepsdn9oupj2oftle9l9.png-81.3kB

在代理服务器nginx上进行测试: 
image_1cs0em00t1iuk1q0e245hnt1trrm.png-24.7kB

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

二、反向代理多虚拟主机节点服务器企业案例

上一节代理的结果不对,究其缘由是当用户访问域名时确实是携带了www.yunjisuan.com主机头请求Nginx反向代理服务器,可是反向代理向下面节点从新发起请求时,默认并无在请求头里告诉节点服务器要找哪台虚拟主机,因此,Web节点服务器接收到请求后发现没有主机头信息,所以,就把节点服务器的第一个虚拟主机发给了反向代理了(节点上第一个虚拟主机放置的是故意这样放置的bbs)。解决这个问题的方法,就是当反向代理向后从新发起请求时,要携带主机头信息,以明确告诉节点服务器要找哪一个虚拟主机。具体的配置很简单,就是在Nginx代理www服务虚拟主机配置里增长以下一行配置便可:

proxy_set_header host $host;

在代理向后端服务器发送的http请求头中加入host字段信息后,若后端服务器配置有多个虚拟主机,它就能够识别代理的是哪一个虚拟主机。这是节点服务器多虚拟主机时的关键配置。整个Nginx代理配置为:

 
  1. [root@nginx nginx]# cat /usr/local/nginx/conf/nginx.conf
  2. worker_processes 1;
  3. events {
  4. worker_connections 1024;
  5. }
  6. http {
  7. include mime.types;
  8. default_type application/octet-stream;
  9. sendfile on;
  10. keepalive_timeout 65;
  11. upstream www_server_pools {
  12. server 192.168.200.135:80 weight=1;
  13. server 192.168.200.137:80 weight=1;
  14. }
  15. server {
  16. listen 80;
  17. server_name www.mendermi.com;
  18. location / {
  19. proxy_pass http://www_server_pools;
  20. proxy_set_header host $host;
  21. }
  22. }
  23. }

image_1cs0f1jge4dd3gfaafnefelt13.png-70.9kB

在代理服务器nginx上进行测试:

image_1cs0f4c32det1rpdq4l1rui1mre2g.png-25.5kB

上图能够看到此次访问的结果和访问的域名就彻底对应上了,这样代理多虚拟主机的节点服务器就不会出问题了

三、通过反向代理后的节点服务器记录用户IP企业案例

完成了反向代理WWW服务后,节点服务器对应的WWW虚拟主机的访问日志的第一个字段记录的并非客户端的IP,而是反向代理服务器的IP,最后一个字段也是“-”!

例如:使用任意windows客户端计算机,访问已经解析好代理IP的www.yunjisuan.com后,去节点服务器www服务日志查看,就会发现以下日志:

 
  1. [root@Web1 logs]# cat access_www.log
  2. 192.168.200.139--[11/Nov/2018:21:26:01 +0800]"GET / HTTP/1.0"200 20 "-""Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko""-"

Web1节点服务器对应的WWW虚拟主机的访问日志的第一个字段记录的并非客户端的IP而是反向代理服务器自己的IP(192.168.0.221),最后一个字段也是一个“-”,那么如何解决这个问题?其实很简单,一样是增长以下一行参数:

 
  1. proxy_set_header X-Forwarded-For $remote_addr;
  2. #这是反向代理时,节点服务器获取用户真实IP的必要功能配置

在反向代理请求后端节点服务器的请求头中增长获取的客户端IP的字段信息,而后节点后端能够经过程序或者相关的配置接收X-Forwarded-For传过来的用户真实IP的信息。

image_1cs0k45tem3ig094hj1lc71tbg3q.png-67.3kB

从新加载Nginx反向代理服务:[root@nginx nginx]# nginx -s reload 
微信图片_20181111133652.png-41.7kB

测试检查 
image_1cs0keh66jt61o9i1iui114upvm6r.png-11kB 
image_1cs0keuf81q2gc541vj19rtqth78.png-10.9kB

去节点服务器WWW服务的访问日志里查看,会发现日志的结尾已经变化了: 
微信图片_20181111133958.png-10.5kB
此时尾部信息因为咱们虚拟机是NAT模式,因此显示的是NAT的网关。

其中,日志里的192.168.200.139为反向代理的IP,对应Nginx日志格式里的变量,而日志结尾的对应的时日志格式里的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。下图是反向代理相关重要基础参数的总结,供参考。

image_1cs0kool9nff7oq14o4j254k696.png-138.6kB

 

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

除了具备多虚拟主机代理以及节点服务器记录真实用户IP的功能外,Nginx软件还提供了至关多的做为反向代理和后端节点服务器对话的相关控制参数,具体见前面proxy模块时提供的图表。

一、因为参数众多,最好把这些参数放到一个配置文件里,而后用include方式包含到虚拟主机配置里,效果以下: 
image_1cs0l6l7j24lvlk1atj8hi1kp79j.png-45.4kB

image_1cs0lgufh1p5n3l5b9791m5qad.png-29.8kB

 

6、根据URL中的目录地址实现代理转发

一、例:经过Nginx实现动静分离,即经过Nginx反向代理配置规则实现让动态资源和静态资源及其余业务分别由不一样的服务器解析,以解决网站性能,安全,用户体验等重要问题。

下图为企业常见的动静分离集群架构图,此架构图适合网站前端只使用同一个域名提供服务的场景,例如,用户访问的域名是www.mendermi.com,而后,当用户请求www.mendermi.com/upload/xx地址时候,代理会分配请求到上传服务器池处理数据;当用户请求www.mendermi.com/static/xx地址的时候,代理会分配请求到静态服务器池请求数据;当用户请求www.mendermi.com/xx地址的时候,即不包含上述指定的目录地址路径时,代理会分配请求到默认的动态服务器池请求数据(注意:上面的xx表示任意路径)。

image_1cs0nqhe1rn4dgg1eb210nq76qaq.png-137.7kB

二、准备:配置实战

需求梳理: 
- 当用户请求www.mendermi.com/upload/xx地址时,实现由upload上传服务器池处理请求。 
- 当用户请求www.mendermi.com/static/xx地址时,实现由静态服务器池处理请求。 
- 除此之外,对于其余访问请求,全都由默认的动态服务器池处理请求。

了解了需求后,就能够进行upstream模块服务器池的配置了。

 
  1. #static_pools为静态服务器池,有一个服务器,地址为192.168.200.135,端口为80.
  2. upstream static_pools {
  3. server 192.168.200.135:80 weght=1;
  4. }
  5. #upload_pools为上传服务器池,有一个服务器地址为192.168.200.137,端口为80.
  6. upstream upload_pools {
  7. server 192.168.200.137:80 weight=1;
  8. }
  9. #default_pools为默认的服务器池,即动态服务器池,有一个服务器,地址为192.168.200.128,端口为80.
  10. upstream default_pools {
  11. server 192.168.200.128:80 weight=1;
  12. }
  13. #提示:须要增长一台测试Web节点Web03(ip:192.168.200.128),配置与Web01,Web02同样。

下面利用location或if语句把不一样的URI(路径)请求,分给不一样的服务器池处理,具体配置以下。 
方案1:以location方案实现

 
  1. #将符合static的请求交给静态服务器池static_pools,配置以下:
  2. location /static/ {
  3. proxy_pass http://static_pools;
  4. include proxy.conf;
  5. }
  6. #将符合upload的请求交给上传服务器池upload_pools,配置以下:
  7. location /upload/ {
  8. proxy_pass http://upload_pools;
  9. include proxy.conf;
  10. }
  11. #不符合上述规则的请求,默认所有交给动态服务器池default_pools,配置以下:
  12. location / {
  13. proxy_pass http://default_pools;
  14. include proxy.conf;
  15. }

方案2:以if语句实现。

 
  1. if ($request_uri ~* "^/static/(.*)$")
  2. {
  3. proxy_pass http://static_pools/$1;
  4. }
  5. if ($request_uri ~* "^/upload/(.*)$")
  6. {
  7. proxy_pass http://upload_pools/$1;
  8. }
  9. location / {
  10. proxy_pass http://default_pools;
  11. include proxy.conf;
  12. }

下面以方案1为例进行实验,Nginx反向代理的实际配置以下:

 
  1. [root@nginx nginx]# cat conf/nginx.conf
  2. worker_processes 1;
  3. events {
  4. worker_connections 1024;
  5. }
  6. http {
  7. include mime.types;
  8. default_type application/octet-stream;
  9. sendfile on;
  10. keepalive_timeout 65;
  11. upstream static_pools {
  12. server 192.168.200.135:80 weight=1;
  13. }
  14. upstream upload_pools {
  15. server 192.168.200.137:80 weight=1;
  16. }
  17. upstream default_pools {
  18. server 192.168.200.128:80 weight=1;
  19. }
  20. server {
  21. listen 80;
  22. server_name www.mendermi.com;
  23. location / {
  24. proxy_pass http://default_pools;
  25. include proxy.conf;
  26. }
  27. location /static/ {
  28. proxy_pass http://static_pools;
  29. include proxy.conf;
  30. }
  31. location /upload/ {
  32. proxy_pass http://upload_pools;
  33. include proxy.conf;
  34. }
  35. }
  36. }

从新加载配置生效 
image_1cs0pokeg17nk13iv167r11851c1sb7.png-17.5kB

暂时不要马上测试成果,为了实现上述代理的测试,还须要在Web01和Web02上作节点的测试配置,才能更好地展现测试效果。 
以Web1做为static静态服务,地址端口为:192.168.200.135:80,须要事先配置一个用于测试静态的地址页面,并测试访问,肯定它会返回正确结果。操做步骤以下:

 
  1. [root@Web1 html]# cd www/
  2. [root@Web1 www]# mkdir static
  3. [root@Web1 www]# echo "static_pools" >> static/index.html
  4. [root@Web1 www]# curl http://www.mendermi.com/static/index.html
  5. static_pools

image_1cs0q5h0m1jtef0k1i18i15l7nbk.png-35kB

以Web2做为upload上传服务,地址端口为:192.168.200.137:80,须要事先配置一个用于测试上传服务的地址页面,并测试访问,肯定它会返回正确结果。建立目录及文件同Web1类似,只是改了模块名,详见下图

image_1cs0qgop31s0k1v1lpa0hn318r5ce.png-16.1kB

image_1cs0qepif1q7dlu313icipq173vc1.png-22.1kB

在Web3做为动态服务节点,地址端口为192.168.200.128:80,一样须要事先配置一个默认的地址页面,并测试访问,肯定它会返回正确结果。操做步骤以下:

 
  1. [root@web3 www]# cd /usr/local/nginx/html/www
  2. [root@web3 www]# echo "default_pools" >> index.html
  3. [root@web3 www]# curl http://www.yunjisuan.com
  4. default_pools

image_1cs0qq3oncqkd4dc5luhq1d5vcr.png-5.4kB

以上准备了三台Web节点服务器,分别加入到了upstream定义的不一样服务器池,表明三组不一样的业务集群组,从本机经过hosts解析各自的域名,而后测试访问,其地址与实际访问的内容输出请对照下表:

image_1cs0rr3fk1eob160p1al01085gs513.png-22kB

使用客户端计算机访问测试时,最好选用集群之外的机器,这里先在浏览器客户端的hosts文件里把www.yunjisuan.com解析到Nginx反向代理服务器的IP,而后访问上述URL,看代理是否是把请求正确地转发到了指定的服务器上。若是能够获得与上表对应的内容,表示配置的Nginx代理分发的彻底正确,由于若是分发请求到错误的机器上就没有对应的URL页面内容,输出会是404错误。

image_1cs0rtnov3a63bm42r1r6d6831g.png-11.7kB

image_1cs0rugib1vj31nvv11fs1dv716kc1t.png-11.3kB

image_1cs0rvdi6duq1n0r17n1q5f77t2q.png-10.7kB 以上测试成功!

相关文章
相关标签/搜索