首页 > 其他 > 详细

nginx作为反向代理的应用

时间:2015-03-27 06:29:42      阅读:432      评论:0      收藏:0      [点我收藏+]

nginx反向代理


实验前提:
1、nginx反向代理服务器系统平台为RHEL 6.4(64bit),后面2个httpd服务器系统平台为RHEL 5.8(32bit)。
2、nginx反向代理服务器地址为
  nginx反向代理服务器IP:192.168.108.230
  上游httpd服务器IP:192.168.108.199(apache1)   192.168.108.201(apache2)
3、确保3台服务器时间同步

 

实验结构拓扑:

技术分享

 

 

 


一、nginx反向代理模块及其指令
nginx的反向代理功能是通过proxy模块来完成。proxy模块的可用配置指令非常多,它们分别用于定义proxy模块工作时的诸多属性,如连接超时时长、代理时使用http协议版本等。下面对常用的指令做一个简单说明。

proxy_connect_timeout:nginx将一个请求发送至upstream server之前等待的最大时长;
proxy_cookie_domain:将upstream server通过Set-Cookie首部设定的domain属性修改为指定的值,其值可以为一个字符串、正则表达式的模式或一个引用的变量;
proxy_cookie_path: 将upstream server通过Set-Cookie首部设定的path属性修改为指定的值,其值可以为一个字符串、正则表达式的模式或一个引用的变量;
proxy_hide_header:设定发送给客户端的报文中需要隐藏的首部;
proxy_pass:指定将请求代理至upstream server的URL路径;
proxy_set_header:将发送至upsream server的报文的某首部进行重写;
proxy_redirect:重写location并刷新从upstream server收到的报文的首部;
proxy_send_timeout:在连接断开之前两次发送至upstream server的写操作的最大间隔时长;
proxy_read_timeout:在连接断开之前两次从接收upstream server接收读操作的最大间隔时长;

如下面的一个示例:
 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;
 client_max_body_size 10m;
 client_body_buffer_size 128k;
 proxy_connect_timeout 30;
 proxy_send_timeout 15;
 proxy_read_timeout 15


二、nginx作为反向代理服务器
Nginx通过proxy模块实现反向代理功能。在作为web反向代理服务器时,nginx负责接收客户请求,并能够根据URI、客户端参数或其它的处理逻辑将用户请求调度至上游服务器上(upstream server)。nginx在实现反向代理功能时的最重要指令为proxy_pass,它能够将location定义的某URI代理至指定的上游服务器(组)上。如下面的示例中,location的/web将被替换为上游服务器上的/newweb。
不过这个/newweb必须在上游服务器(即我们常说的后端服务器)的根目录下创建。如果这个/newweb是个目录,还需要在这个目录下创建默认主页(如:index.html)。将nginx作为web代理服务器时,还需要在配置文件中添加如下信息:
 location /web {                                  
  proxy_pass http://www.xsl.com:8080/newweb;    这表示如果用户访问根目录下/web/下的默认主页时,实际访问的是上游服务器根目录下/newweb/下的默认主页。
 }


添加完成之后,还需要在上游服务器中创建/newweb目录,
#mkdir  /www/xsl.com/newweb                    这里的/www/xsl.com是我的上游httpd服务器的根目录,这里我是基于虚拟主机的方式来配置的。如果大家是采用的默认配置,则根目录为/var/www/html/,然后在这个目录下创建相应的目录和文件即可。
#vim   /www/xsl.com/newweb/index.html
<h1>node1.xsl.com</h1>

测试,在浏览器上输入http://www.xsl.com/web,测试结果如下:

技术分享


 
不过,这种处理机制中有两个例外。一个是如果location的URI是通过模式匹配定义的,其URI将直接被传递至上游服务器,因此不能为其指定转换的另一个URI。例如下面示例中的/bbs将被代理为http://www.xsl.com/bbs
 location ~ ^/bbs {
  proxy_pass http://www.xsl.com;   注意:如果上面是基于正则表达式来匹配url的话,这里不能指定url。
 }

第二个例外是,如果在loation中使用的URL重定向,那么nginx将使用重定向后的URI处理请求,而不再考虑上游服务器上定义的URI。如下面所示的例子中,传送给上游服务器的URI为/index.php?page=<match>,而不是/index。

 location / {
  rewrite /(.*)$ /index.php?page=$1 break;
  proxy_pass http://localhost:8080/index;
 }

 

 

三、upstream模块
与proxy模块结合使用的模块中,最常用的当属upstream模块。upstream模块可定义一个新的上下文,它包含了一组upstream服务器,这些服务器可能被赋予了不同的权重、不同的类型甚至可以基于维护等原因被标记为down。
upstream模块常用的指令有:
ip_hash:基于客户端IP地址完成请求的分发,它可以保证来自于同一个客户端的请求始终被转发至同一个upstream服务器;
keepalive:每个worker进程为发送到upstream服务器的连接所缓存的个数;
least_conn:最少连接调度算法;
server:定义一个upstream服务器的地址,还可包括一系列可选参数,如:
 weight:权重;如果定义了多个server和weight,则用户的每一个请求会负载均衡的被上游服务器进行响应。这种负载均衡是基于加权轮调的方式进行的。
 max_fails:最大失败连接次数,失败连接的超时时长由fail_timeout指定;
 fail_timeout:等待请求的目标服务器发送响应的时长;
 backup:用于fallback的目的,所有服务均故障时才启动此服务器;
 down:手动标记其后端的上游服务器不再处理任何请求;

例如:在配置文件中添加如下将信息,注意upstream的配置要在http内server外
 upstream webserver {
                server  192.168.108.199  weight=1  max_fails=3  fail_timeout=30s;
                server  192.168.108.201  weight=1;
               
        }
 location /up {
            proxy_pass  http://webserver;  这里接的是组名
        }
添加完成之后,还需要在后端的2个上游服务器中创建up目录和默认主页。
192.168.108.199上的配置
# mkdir  /www/xsl.com/up
# vim  /www/xsl.com/up/index.html
<h1>up server1  node1.xsl.com</h1>
然后在重启httpd服务器
# service httpd  restart

192.168.108.201上的配置
# mkdir  /www/xsl.com/up
# vim  /www/xsl.com/up/index.html
<h1>up server2  node2.xsl.com</h1>

然后在重启httpd服务器
# service httpd  restart

测试,在浏览器上方输入http://192.168.108.230/up,第一次测试结果如下:

技术分享


然后刷新该页面,显示结果如下:

技术分享


发现,用户的http请求均衡的被上游服务器进行响应。

当后端的所有服务器都down后,应该返回一个错误页面或提示页面给客户端,这样给用户看起来比较亲切。
需要在配置文件中添加如下信息:
server  127.0.0.1:8080  backup;   这一行信息添加在相应的upstream中。

server  {
        listen 8080;
        server_name  localhost;
        root /nginx/err ;
        index   index.html ;
    }

 
默认情况下,upstream使用的的复制均衡算法为轮调,有时候需要将同一个客户端的请求重定向到同一个服务器进行响应,以便重用session信息。为此,我们可以指定其算法为ip_hash,只要客户端的源ip相同,则以后该客户端所有的响应都由之前响应过的服务器进行响应。
ip_hash不可以和backup一起使用,它配置在upstream上下文中。

upstream模块的负载均衡算法主要有三种,轮调(round-robin)、ip哈希(ip_hash)和最少连接(least_conn)三种。

此外,upstream模块也能为非http类的应用实现负载均衡,如下面的示例定义了nginx为memcached服务实现负载均衡之目的。

 upstream memcachesrvs {
  server 172.16.100.6:11211;
  server 172.16.100.7:11211;
 }
 
 server {
  location / {
  set $memcached_key "$uri?$args";
  memcached_pass memcachesrvs;
  error_page 404 = @fallback;
  }
 
  location @fallback {
       proxy_pass http://127.0.0.1:8080;
  }
 }


 
四、定义请求报文头部的源地址
默认情况下,当nginx作为前端代理服务器时,用户的请求是通过nginx反向代理服务器调度到后端的上游服务器。因此,当nginx反向代理器收到请求后,会重新对请求的报文进行封装,然后在封装后的报文交给后端的上游服务器。因此,当后端的上游服务器接收请求时,则认为请求的源地址为nginx服务器的地址。
对于需要统计用户访问的网站而言,如果请求报文的源地址为nginx服务器的地址的话是无法进行统计的。对于请求的源地址,我们可以通过查看后端httpd服务器的访问日志来显示。如:
192.168.108.230 - - [24/Mar/2015:23:03:45 +0800] "GET /up/ HTTP/1.0" 200 35 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)"
192.168.108.230 - - [24/Mar/2015:23:03:45 +0800] "GET /up/ HTTP/1.0" 304 - "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)"
192.168.108.230 - - [24/Mar/2015:23:03:46 +0800] "GET /up/ HTTP/1.0" 304 - "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)"
192.168.108.230 - - [24/Mar/2015:23:03:46 +0800] "GET /up/ HTTP/1.0" 304 - "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)"
192.168.108.230 - - [24/Mar/2015:23:03:46 +0800] "GET /up/ HTTP/1.0" 304 - "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)"
192.168.108.230 - - [24/Mar/2015:23:03:46 +0800] "GET /up/ HTTP/1.0" 304 - "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)"
192.168.108.230 - - [24/Mar/2015:23:03:47 +0800] "GET /up/ HTTP/1.0" 304 - "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)"
192.168.108.230 - - [24/Mar/2015:23:03:47 +0800] "GET /up/ HTTP/1.0" 304 - "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)"
192.168.108.230 - - [24/Mar/2015:23:03:47 +0800] "GET /up/ HTTP/1.0" 304 - "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)"
192.168.108.230 - - [24/Mar/2015:23:03:47 +0800] "GET /up/ HTTP/1.0" 304 - "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)"
在这里192.168.108.230是nginx反向代理服务器的地址,因此,对于这种现象是无法统计用户的访问量的。


还好,在proxy模块中有一个命令proxy_set_header可以用来修改请求报文的源地址的。如果需要修改请求报文的真实源ip,可以在nginx反向代理服务器的配置文件中添加如下信息:
proxy_set_header X-Real-IP  $remote_addr;  这行命令添加在特定的location中即可。其中$remote_addr表示请求报文的源地址,后面X-Real-IP是一个自定义参数,这个参数的值就是$remote_addr,它会将该值传递给后端的上游服务器。
在nginx代理服务器上添加完成之后,要想显示的是请求报文的真实ip地址,,还需要在httpd的主配置文件修改如下这行信息:
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
将这行中的"%h"修改为%{X-Real-IP}i即可。如:
LogFormat "%{X-Real-IP}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
然后再在后端的服务器上查看httpd的相关日志信息,显示内容如下:
192.168.106.12 - - [26/Mar/2015:18:53:39 +0800] "GET /up/ HTTP/1.0" 200 34 "-" "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Tablet PC 2.0; {D9D54F49-E51C-445e-92F2-1EE3C2313240}; 2345Explorer)"
192.168.106.12为客户端的ip地址,因此,此信息表明请求报文的源ip设置成功。


五、rewrite模块指令
nginx的重写模块是一个简单的正则表达式匹配与一个虚拟堆叠机结合。依赖于PCRE库,因此需要安装pcre。根据相关变量重定向和选择不同的配置,从一个location跳转到另一个location,不过这样的循环最多可以执行10次,超过后nginx将返回500错误。同时,重写模块包含set指令,来创建新的变量并设其值,这在有些情景下非常有用的,如记录条件标识、传递参数到其他location、记录做了什么等等。

1、rewrite语法格式:
语法:rewrite regex replacement flag。
rewrite一般用在server, location, if当中。

2、重写规则
任何重写规则的第一部分都是一个正则表达式。可以使用括号来捕获,后续可以根据位置来将其引用,位置变量值取决于捕获正则表达式中的顺序,$1引用第一个括号中的值,$2引用第二个括号中的值,以此类推。
重写规则的第二部分是URI。URI可能包含正则表达式中的捕获的位置参数或这个级别下的nginx任何配置变量。注意:如果替换的字符串以http://开头,请求将被重定向,并且不再执行多余的rewrite指令。
第三部分也就是尾部的标记(flag)。


在rewrite语句后面还可以添加flag,这些flag可以是这些值:
last:本次重写完成之后,重新搜索location与更改后的URL匹配。这种flag是使用最多的,不过容易导致循环检查。不过循环次数最多也就10次。
break:本次重写完成后,直接执行后续操作。这种flag可以解决循环问题。
redirect:返回302临时重定向,如果替换字段是以http://开头则被使用
permanent:返回301永久重定向。
如:
location /image {
            index index.html;
            rewrite ^/image/bbs/(.*)$  http://192.168.108.201/jgp/$1;  ^/image/bbs/(.*)$ 表示url以/image开头,如果url不是"/"的话,那么^后面就必须加url了(如/image)。
        }
  
  
if判断语句(最好用在location中)
在location中使用if语句可以实现条件判断,其通常有一个return语句,且一般与有着last或break标记的rewrite规则一同使用。但其也可以按需要使用在多种场景下,需要注意的是,不当的使用可能会导致不可预料的后果。
if语句中的判断条件
正则表达式匹配:
 ~:与指定正则表达式模式匹配时返回“真”,判断匹配与否时区分字符大小写;
 ~*:与指定正则表达式模式匹配时返回“真”,判断匹配与否时不区分字符大小写;
 !~:与指定正则表达式模式不匹配时返回“真”,判断匹配与否时区分字符大小写;
 !~*:与指定正则表达式模式不匹配时返回“真”,判断匹配与否时不区分字符大小写;

文件及目录匹配判断:
 -f, !-f:判断指定的路径是否为存在且为文件;
 -d, !-d:判断指定的路径是否为存在且为目录;
 -e, !-e:判断指定的路径是否存在,文件或目录均可;
 -x, !-x:判断指定路径的文件是否存在且可执行;
 
字符串比较
 使用=或!=运算符

关键字:
break:终止退出。
return:直接返回状态码。状态码为0-99 

如: 
location / {
 if ($request_method == “PUT”) {
  proxy_pass http://upload.xsl.com:8080;
 }

 if ($request_uri ~ "\.(jpg|gif|jpeg|png)$") {
  proxy_pass http://imageservers;
  break;
 }
}
upstream imageservers {
 server 192.168.108.199:80 weight 2;
 server 192.168.108.201:80 weight 3;
}
 
nginx代理服务器实现读写分离
在这里我们使用的写操作为put方法,由于put方法是是基于WebDAV技术的。WebDAV (Web-based Distributed Authoring and Versioning) 一种基于 HTTP 1.1协议的通信协议。它扩展了HTTP 1.1,在GET、POST、HEAD等几个HTTP标准方法以外添加了一些新的方法,使应用程序可直接对Web Server直接读写,并支持写文件锁定(Locking)及解锁(Unlock),还可以支持文件的版本控制。
因此,需要在后端的httpd服务器中加载dav模块。如
LoadModule dav_module modules/mod_dav.so
LoadModule dav_fs_module modules/mod_dav_fs.so
加载完成之后,还需要在根目录<directory>容器中添加如下行:
dav  on

然后,编辑nginx的配置文件,修改文件内容为如下:
 location / {
                proxy_pass  http://192.168.108.199/;
                if ($request_method = "PUT") {
                        proxy_pass http://192.168.108.201;
                }
        }
然后还需要在192.18.108.201上设置apache用户对Apache的根目录具有写权限,如
#setfacl  -m u:apache:rwx  /www/xsl.com
 
然后再nginx服务器上上传文件
curl  -T /etc/issue  http://192.168.108.230

测试访问http://192.168.108.230和访问http://192.168.108.199/issue即可发现读写分离以实现。这里不在贴图了。


 
 
六、nginx的cache功能
nginx做为反向代理时,能够将来自upstream的响应缓存至本地,并在后续的客户端请求同样内容时直接从本地构造响应报文。
nginx的缓存空间包括共享内存空间和磁盘存储空间。其中共享内存空间存储的是键(key)和缓存对象的元数据。磁盘存储空间主要存储的就是数据。
如果想为nginx设定cahce功能,需要添加如下信息:
proxy_cache_path  /nginx/cache/web   levels=1:2   keys_zone=cachename:20m    miax_size=1G;    注意proxy_cache_path: 不能定义在server{}上下文中;
##其中/nginx/cache/web为缓存目录 ; levels=1:2   表示有几个子目录,1表示为一级子目录且该目录的名称为1个字符,2表示为二级子目录且该目录的名称为2个字符(子目录最多只能到三级,目录名称最大为2个); keys_zone表示共享内存的名称及存储空间大小; max_size表示数据存储空间大小,当需要缓存的对象超出此空间限定时,缓存管理器将基于LRU算法对其进行清理。
add_header  X-Via  $server_addr;           添加一个首部,显示服务器端的ip地址
addr_header X-Cache  $upstream_cache_status;   添加一个首部,显示缓存是否命中。$upstream_cache_status表示缓存的状态,它有5个值为{MISS|EXPIRED|UPDATING|STALE|HIT}。MISS表示没有命中;EXPIRED表示缓存过期了;UPDATING表示缓存更新了;STALE表示缓存失效了;HIT表示缓存命中。

 

设定完成之后,还需要在特定的location中启用cache功能,需要在特定的location中添加如下信息:
proxy_cache  cachename  启用cache功能,只需要引用共享内存的名称即可。如果不想启用cache功能,可以将proxy_cache 设置为off。
proxy_cache_vaild 200  1m;   用于为不同的状态响应码设定不同时长的有效缓存时长
proxy_cache_vaild any  10m;

另外常用的三种缓存:
 open_log_cache:日志缓存
 open_file_cache:文件缓存
 fastcgi_cache: fastcgi缓存

 


 

nginx作为反向代理的应用

原文:http://xslwahaha.blog.51cto.com/4738972/1625242

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!