一、Nginx之反向代理
二、Nginx之负载均衡
三、Nginx之页面缓存
四、Nginx之URL重写
五、Nginx之读写分离

一、Nginx之反向代理
ngx_http_proxy_module
支持缓存,nginx需要同时连接client和端s
    前端:建议使用短的长连接
    后端s:建议使用长链接,节约端口和带宽  //502:bad gateway原因:可能是后端s的设置的超时时间较短    导致proxy长时间得不到响应

正向代理://隐藏client
    比如默认你不能访问谷歌,可以购买一个国外的服务器,这个服务器是可以访问google的。这个服务器就是你的正向代理
    你向代理服务器发送(google)请求,代理服务器请求后把结果返回给你。//我们常说的跳板机就是这样做的
反向代理://保护server
    对于客户端而言反代服务器就像是原始服务器,可以对后端server进行负载均衡,HA等。
    
1.环境简介:
配置httpd(2.2)监听在8080&8888: 192.168.2.108
配置nginx监听在80:192.168.2.118
nginx反代到httpd:

2.环境配置
192.168.2.108配置)

[root@localhost html]# vim /etc/httpd/conf/httpd.conf
    #DocumentRoot "/var/www/html"  //注释中心主机
    Listen 192.168.2.108:8080
    Listen 192.168.2.108:8888

    
[root@localhost html]# vim /etc/httpd/conf.d/virtual.conf

#NameVirtualHost 192.168.2.108  //这个只在httpd2.2基于主机名的虚拟主机才会用到
[root@localhost a.com]# cat /etc/httpd/conf.d/virtual.conf
#NameVirtualHost 192.168.2.108
<VirtualHost 192.168.2.108:8080>
        DocumentRoot "/www/a.com"
        <Directory "/www/a.com">
                Options Indexes FollowSymlinks
                AllowOverride None
        </Directory>
</VirtualHost>
<VirtualHost 192.168.2.108:8888>
        DocumentRoot "/www/b.net"
        <Directory "/www/b.net">
                Options Indexes FollowSymlinks
                AllowOverride None
        </Directory>
</VirtualHost>

httpd -S //测试virtualhost配置    
[root@localhost ~]# mkdir /www/{a.com,b.net} -pv
[root@localhost html]# echo "<h1>a.com:8080</h1>" > /www/a.com/index.html
[root@localhost html]# echo "<h1>b.net:8888</h1>" > /www/b.net/index.html

192.168.2.118配置)
HTTP/1.0无法使用keepalive(后端服务器将为每个请求创建并且删除连接)
nginx为浏览器发送HTTP/1.1并为后端服务器发送HTTP/1.0,这样浏览器就可以为浏览器处理keepalive。    

[root@localhost conf.d]# vim /etc/nginx/conf.d/defalut.conf  //listen为192.168.2.118:80

[root@localhost conf.d]# cat default.conf
# The default server
server {
    listen       192.168.2.118:80 default_server;
#    listen       [::]:80 default_server;
    server_name  _;
    root         /usr/share/nginx/html;
    include /etc/nginx/default.d/*.conf;
    location / {
        proxy_pass http://192.168.2.108:8080;
    }
    error_page 404 /404.html;
        location = /40x.html {
    }
    error_page 500 502 503 504 /50x.html;
        location = /50x.html {
    }
}

http主机:192.168.2.108上写入测试页
[root@localhost conf.d]# echo "nginx-to-http:8080" > /www/a.com/8080.html
nginx主机上测试
[root@localhost a.com]# curl http://192.168.2.118/8080.html
nginx-to-http:8080

nginx日志:[root@www ~]# tail /var/log/nginx/access.log  
    192.168.2.107 - - [25/Feb/2018:12:14:23 +0800] "GET /favicon.ico HTTP/1.1" 404 290 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:57.0) Gecko/20100101 Firefox/57.0" "-"
    //107是client地址
http日志:[root@localhost conf.d]# tail /var/log/httpd/access_log
    192.168.2.118 - - [25/Feb/2018:12:14:23 +0800] "GET /favicon.ico HTTP/1.0" 404 290 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:57.0) Gecko/20100101 Firefox/57.0"
    //118是nginx地址
由此可见http不能获取真实的client的ip

3.配置nginx让httpd获取真实的client-ip

[root@localhost a.com]# vim /etc/nginx/conf.d/default.conf
....
    location / {
        proxy_pass http://192.168.2.108:8080;
        proxy_set_header X-Real-IP $remote_addr;
    }
....

proxy_set_header:允许将发送到被代理服务器的请求头重新定义或者增加一些字段。
这个值可以是一个文本,变量或者它们的组合。proxy_set_header在指定的字段中没有定义时会从它的上级字段继承。

[root@localhost a.com]# vim /etc/httpd/conf/httpd.conf
修改原有的"combined"列的%h为"%{X-Real-IP}i"
LogFormat "%{X-Real-IP}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
LogFormat "%{Referer}i -> %U" referer
LogFormat "%{User-agent}i" agent

再次使用浏览器访问,就可以看到真实的clientip了。

4.proxy_pass指令简介

proxy_pass URL //发送给后端url指定的主机Context:location 
    location /bbs/ {
        proxy_pass http://192.168.0.1; //后端的uri没有的话,继承location的url,就是说访问http://$ngx_ip/bbs/访问的是http://192.168.0.1/bbs/ 
    }
    location /bbs/ {
        proxy_pass http://192.168.0.1/test2/; //访问http://$ngx_ip/bbs/访问的是http://192.168.0.1/test2/目录,注意形式要么“/bbs/","http://192.168.0.1/bbs/"要么"/bbs","http://192.168.0.1/bbs" 要么都带,要么都不带后面的"/"
    }
    location ~|~* PATTERN {
        proxy_pass http://192.168.0.1; //uri不能有,连斜线也不能有
    }
    location ~* \.(jpg|gif|png) {
        proxy_pass http://192.168.10.129;  //正则模式,后面不能带uri
    }
    location /bbss/ {
        proxy_pass http://192.168.4.134/; //    "/"访问bbss的时候,直接定位到主目录,访问http://$ngx_ip/bbss/访问的是http://192.168.4.134的DocumentRoot指定目录下的index.html 
        index index.html index.htm;
    }

proxy_pass后面路径是一个uri时,其会将location的uri替换为proxy_pass后端主机的uri;
如果其location定义其uri时使用了正则表达式模式匹配机制
    则proxy_pass后的路径必须不能使用uri
            
二、Nginx之负载均衡
1.配置案例
[root@nginx ~]# vim /etc/nginx/nginx.conf

upstream webservers {
    ip_hash;
    server 192.168.18.201 weight=1 max_fails=2 fail_timeout=2;
    server 192.168.18.202 weight=1 max_fails=2 fail_timeout=2;
    server 127.0.0.1:8080 backup;
}
    server {
        listen       80;
        server_name  localhost;
        #charset koi8-r;
        #access_log  logs/host.access.log  main;
        location / {
            proxy_pass      http://webservers;
            proxy_set_header  X-Real-IP  $remote_addr;
    }
}

upstream是定义在server{ }之外的,不能定义在server{ }内部。定义好upstream之后,用proxy_pass引用一下即可。
2.upstream支持的调度算法
    轮询(默认)。每个请求按时间顺序逐一分配到不同的后端服务器,如果后端某台服务器宕机,故障系统被自动剔除,使用户访问不受影响。Weight 指定轮询权值,Weight值越大,分配到的访问机率越高,主要用于后端每个服务器性能不均的情况下。
    ip_hash。每个请求按访问IP的hash结果分配,这样来自同一个IP的访客固定访问一个后端服务器,有效解决了动态网页存在的session共享问题。
    fair。这是比上面两个更加智能的负载均衡算法。此种算法可以依据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间来分配请求,响应时间短的优先分配。Nginx本身是不支持fair的,如果需要使用这种调度算法,必须下载Nginx的upstream_fair模块。
    url_hash。此方法按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,可以进一步提高后端缓存服务器的效率。Nginx本身是不支持url_hash的,如果需要使用这种调度算法,必须安装Nginx 的hash软件包。
3.支持的状态参数
在HTTP Upstream模块中,可以通过server指令指定后端服务器的IP地址和端口,同时还可以设定每个后端服务器在负载均衡调度中的状态。常用的状态有:      
    down,表示当前的server暂时不参与负载均衡。
    backup,预留的备份机器。当其他所有的非backup机器出现故障或者忙的时候,才会请求backup机器,因此这台机器的压力最轻。
    max_fails,允许请求失败的次数,默认为1。当超过最大次数时,返回proxy_next_upstream 模块定义的错误。
    fail_timeout,在经历了max_fails次失败后,设置server不可用的时间。max_fails可以和fail_timeout一起使用。
注,当负载调度算法为ip_hash时,后端服务器在负载均衡调度中的状态不能是weight和backup。

三、Nginx之页面缓存
缓存相关的选项(缓存先定义,后调用)
    内存:key-value
        key:是url
        value:对应的文件的内容的校验码md5
        //文件名,不再使用,而是对文件的内容进行校验,查询的时候将基于校验码查询
        
[root@localhost html]# md5sum /etc/fstab
221bbfd1a7ae8ae21ab53bbf9e1b3be7  /etc/fstab

1.定义
proxy_cache_path //只能定义在http中,
    2 2//表示,22当做以及子目录的名字,1b当做二级子目录的名字,后面才是真实的文件名
    否则需要全盘扫描,加快查找速度
    proxy_cache_path path [levels=number] keys_zone=zone_name:zone_size [inactive=time] [max_size=size];  
        level:级
        keys_zone:内存空间
        inactive=time:kev-value数据的失效时间
        max_size//disk上最大使用的大小,满了就基于lRU算法清理
        loader_files:服务器刚启动时加载多少

    proxy_cache_path  /data/nginx/cache  levels=1:2   keys_zone=one:10m;
    文件名类似:/data/nginx/cache/c/29/b7f54b2df7773722d382f4809d65029c
    levels指定目录结构,可以使用任意的1位或2位数字作为目录结构,如 X, X:X,或X:X:X 例如: “2”, “2:2”, “1:1:2“,但是最多只能是三级目录。
    所有活动的key和元数据存储在共享的内存池中,这个区域用keys_zone参数指定。one指的是共享池的名称,10m指的是共享池的大小。  
    注意每一个定义的内存池必须是不重复的路径,例如:
    proxy_cache_path  /data/nginx/cache/one    levels=1      keys_zone=one:10m;
    proxy_cache_path  /data/nginx/cache/two    levels=2:2    keys_zone=two:100m;
    proxy_cache_path  /data/nginx/cache/three  levels=1:1:2  keys_zone=three:1000m;
如果在inactive参数指定的时间内缓存的数据没有被请求则被删除,默认inactive为10分钟。一个名为cache manager的进程控制磁盘的缓存大小,它被用来删除不活动的缓存和控制缓存大小,这些都在max_size参数中定义,当目前缓存的值超出max_size指定的值之后,超过其大小后最少使用数据(LRU替换算法)将被删除。内存池的大小按照缓存页面数的比例进行设置,一个页面(文件)的元数据大小按照操作系统来定,如FreeBSD/i386下为64字节,FreeBSD/amd64下为128字节。    
    
2.调用缓存
    proxy_cache zone|off //默认为关闭
    location / {
        proxy_cache pcache;
        }
设置一个缓存区域的名称,一个相同的区域可以在不同的地方使用。  
在0.7.48后,缓存遵循后端的”Expires”, “Cache-Control: no-cache”, “Cache-Control: max-age=XXX”头部字段,0.7.66版本以后,”Cache-Control:“private”和”no-store”头同样被遵循。nginx在缓存过程中不会处理”Vary”头,为了确保一些私有数据不被所有的用户看到,后端必须设置 “no-cache”或者”max-age=0”头,或者proxy_cache_key包含用户指定的数据如$cookie_xxx,使用cookie的值作为proxy_cache_key的一部分可以防止缓存私有数据,所以可以在不同的location中分别指定proxy_cache_key的值以便分开私有数据和公有数据。  
缓存指令依赖代理缓冲区(buffers),如果proxy_buffers设置为off,缓存不会生效。    

3.指定key键
    proxy_cache_key string;
    定义缓存键:
        proxy_cache_key $request_uri
        proxy_cache_key $scheme$proxy_host$request_uri //请求的服务,代理主机,uri
            //缓存键定义了缓存的内容及对象,太细的话,命中率不高
    location / {
        proxy_cache pcache;
        proxy_cache_key
        }    
    
4.有效的响应码
    proxy_cache_valid //为不同的响应码定义不同的缓存时长
    示例:
        proxy_cache_valid 200 302 10m;
        proxy_cache_valid 404 1m;
    //支队200,302,404的应答进行缓存    
    
5.proxy_cache_use_stale
    哪种情况下可以使用缓存,返回结果
    proxy_cache_use_stale error | timeout | invalid_header | updating | http_500 | http_502 | http_503 | http_504 | http_403 | http_404 | off ...;

6.缓存变量说明
$server_addr
    服务器地址,在完成一次系统调用后可以确定这个值,如果要绕开系统调用,则必须在listen中指定地址并且使用bind参数。
$upstream_cache_status
0.8.3版本中其值可能为:
    MISS 未命中
    EXPIRED - expired。请求被传送到后端。
    UPDATING - expired。由于proxy/fastcgi_cache_use_stale正在更新,将使用旧的应答。
    STALE - expired。由于proxy/fastc    

[root@nginx ~]# vim /etc/nginx/nginx.conf
proxy_cache_path /data/nginx/cache/webserver levels=1:2 keys_zone=webserver:20m max_size=1g;
server {
    listen       80;
    server_name  localhost;
    #charset koi8-r;
    #access_log  logs/host.access.log  main;
   #增加两头部
    add_header X-Via $server_addr;
    add_header X-Cache $upstream_cache_status;
    location / {
            proxy_pass      http://webservers;
            proxy_set_header  X-Real-IP  $remote_addr;
            proxy_cache webserver;
            proxy_cache_valid 200 10m;
    }
}

打开浏览器开发者模式验证    
    
示例:

http {
    proxy_cache_path /var/cache/nginx/proxy levels=2:2 keys_zone=pcache:10m max_size=1g;
    location / {
    #         root         /var/www/html;
        proxy_cache pcache;
        proxy_cache_key $request_uri;
        proxy_cache_valid 200 302 10m;
        proxy_cache_valid 404 1m;
        proxy_pass http://192.168.4.134;
        index index.html index.htm;
    }
    }

    
四、Nginx之URL重写(Rewrite)
1.Rewrite模块
    该模块允许使用正则表达式重写URI(需PCRE库),并且可以根据相关变量重定向和选择不同的配置。
如果这个指令在server字段中指定,那么将在被请求的location确定之前执行,如果在指令执行后所选择的location中有其他的重写规则,那么它们也被执行。如果在location中执行这个指令产生了新的URI,那么location又一次确定了新的URI。这样的循环可以最多执行10次,超过以后nginx将返回500错误。
//URL基于正则表达式重定向到其他URL,让用户对其他的URI重新发起请求
//自上而下逐个匹配,匹配则返回,不再向下匹配    
    (.*)\.jpg$ -- > $1.html
    (.*)\.html$---> $1.jpg //一直循环,在内部是自上而下,逐条处理

2.相关指令
break/if/return/rewrite/rewrite_log/set/
break) //位置:使用字段,location,if;完成当前设置的规则,停止执行其他的重写指令
示例:
if ($sloww) {
    limit_rate 10k;
    break;
}
跳出循环直接终止

if) //位置:server,location. 语法:if (condition) {...}
condition:
    比较表达式
    使用符号~*和~模式匹配的正则表达式
    ==,!=
    ~:模式匹配,区分字符大小写
    ~*:模式匹配,不区分字符大小写
    !~:模式不匹配,区分字母大小写
    !~*:模式不匹配,不区分字符大小写
文件及目录存在性判断
    -f,!-f //存在且为文件
    -d,!-d 目录
    -e,!-e //存在是否
    -x,!-x 执行权限
            
判断一个条件,如果条件成立,则后面的大括号内的语句将执行,相关配置从上级继承。  
可以在判断语句中指定下列值:
    一个变量的名称;不成立的值为:空字符传”“或者一些用“0”开始的字符串。
示例配置:

if ($http_user_agent ~ MSIE) { //判断浏览器类型
    rewrite ^(.*)$ /msie/$1 break;
}
if ($http_cookie ~* "id=([^;]+)(?:;|$)") { //请求报文中的cookie首部,
    set $id $1;
}
if ($request_method = POST) { //方法为POST,返回状态码405,拒绝用户使用此方法
    return 405;
}
if ($slow) {  //限制low内的用户
    limit_rate 10k;
}
if ($invalid_referer) { //非法引用,return403
    return 403;
}        
if (!-f $request_filename) {
  break;
  proxy_pass  http://127.0.0.1;
}
if ($args ~ post=140){
  rewrite ^ http://example.com/ permanent;
}

内置变量$invalid_referer用指令valid_referers指定。    
    
return)位置:server,location,if ;语法return code
这个指令结束执行配置语句并为客户端返回状态代码,可以使用下列的值:204,400,402-406,408,410, 411, 413, 416与500-504。此外,非标准代码444将关闭连接并且不发送任何的头部。
return URL;
retunr code URL;
    if ($uri ~* .*admin.* ) {
        return 403 "go away";
    }

rewrite)位置server,location,if 语法:rewrite regex replacement flag
    按照相关的正则表达式与字符串修改URI,指令按照在配置文件中出现的顺序执行。  
    可以在重写指令后面添加标记。  
    如果替换的字符串以http://开头,请求将被重定向,并且不再执行多余的rewrite指令。  
    在同一个location中存在的多个rewrite规则会自上而下逐个检查(循环);可以使用flag控制此循环功能
    如果replacement是以http://或https://开头,则结果会以重定向方式返回给客户端;
尾部的标记(flag)可以是以下的值:
    last:重写完成后,continue停止向下匹配,并由nginx使用新的uri再次从头开始匹配,在nginx内部实现
    break:重写完成后停止对当前url在当前location中的后续其他重写操作,直接跳出循环,nginx内部实现
    redirect:匹配到之后直接返回给client新的url,让浏览器重新发起请求    
    permanent:永久的redirect,重写完成后以重定向方式直接重写后生成的新URL给客户端,由客户对新的URL进行请求
        //redirect:302临时,permanent:301永久
注意如果一个重定向是相对的(没有主机名部分),nginx将在重定向的过程中使用匹配server_name指令的“Host”头或者server_name指令指定的第一个名称,如果头不匹配或不存在,如果没有设置server_name,将使用本地主机名,如果你总是想让nginx使用“Host”头,可以在server_name使用“*”通配符(查看http核心模块中的server_name)。例如:
    rewrite  ^(/download/.*)/media/(.*)\..*$  $1/mp3/$2.mp3  last;
    rewrite  ^(/download/.*)/audio/(.*)\..*$  $1/mp3/$2.ra   last;
    return   403;
但是如果我们将其放入一个名为/download/的location中,则需要将last标记改为break,否则nginx将执行10次循环并返回500错误。
location /download/ {
    rewrite  ^(/download/.*)/media/(.*)\..*$  $1/mp3/$2.mp3  break;
    rewrite  ^(/download/.*)/audio/(.*)\..*$  $1/mp3/$2.ra   break;
    return   403;
}

如果替换字段中包含参数,那么其余的请求参数将附加到后面,为了防止附加,可以在最后一个字符后面跟一个问号:    
    rewrite  ^/users/(.*)$  /show?user=$1?  last;

注意:大括号({和}),可以同时用在正则表达式和配置块中,为了防止冲突,正则表达式使用大括号需要用双引号(或者单引号)。例如要重写以下的URL:
    /photos/123456 为
    /path/to/photos/12/1234/123456.png
使用:rewrite  "/photos/([0-9] {2})([0-9] {2})([0-9] {2})" /path/to/photos/$1/$1$2/$1$2$3.png;    
如果指定一个“?”在重写的结尾,Nginx将丢弃请求中的参数,即变量$args,当使用$request_uri或$uri&$args时可以在rewrite结尾使用“?”以避免nginx处理两次参数串。  
在rewrite中使用$request_uri将www.example.com重写到example.com:
    server {
       server_name www.example.com;
       rewrite ^ http://example.com$request_uri? permanent;
    }
同样,重写只对路径进行操作,而不是参数,如果要重写一个带参数的URL,可以使用以下代替:    
    if ($args ^~ post=100){
      rewrite ^ http://example.com/new-address.html? permanent;
    }    
注意$args变量不会被编译,与location过程中的URI不同(参考http核心模块中的location)。

rewrite_log) 语法rewrite_log on|off;位置server,location,if
    启用时将在error log中记录notice 标记的重写日志。

set)语法set variable value,位置server,location,if
    指令设置一个变量并为其赋值,其值可以是文本,变量和它们的组合。  
    可以使用set定义一个新的变量,但是不能使用set设置$http_xxx头部变量的值。
    设置用户自定义变量
    
uninitialized_variable_warn)语法:uninitialized_variable_warn on|off/使用字段:http, server, location, if  
    开启或关闭在未初始化变量中记录警告日志。  
    事实上,rewrite指令在配置文件加载时已经编译到内部代码中,在解释器产生请求时使用。
这个解释器是一个简单的堆栈虚拟机,如下列指令:

location /download/ {
    if ($forbidden) {
    return   403;
    }
    if ($slow) {
    limit_rate  10k;
    }
rewrite  ^/(download/.*)/media/(.*)\..*$  /$1/mp3/$2.mp3  break;
将被编译成以下顺序:
variable $forbidden
checking to zero
recovery 403
completion of entire code
variable $slow
checking to zero
checkings of regular excodession
copying "/"
copying $1
copying "/mp3/"
copying $2
copying ".mp3"
completion of regular excodession
completion of entire sequence
注意并没有关于limit_rate的代码,因为它没有提及ngx_http_rewrite_module模块,“if”块可以类似”location”指令在配置文件的相同部分同时存在。  
如果$slow为真,对应的if块将生效,在这个配置中limit_rate的值为10k。      
    rewrite  ^/(download/.*)/media/(.*)\..*$  /$1/mp3/$2.mp3  break;
如果我们将第一个斜杠括入圆括号,则可以减少执行顺序:
    rewrite  ^(/download/.*)/media/(.*)\..*$  $1/mp3/$2.mp3  break; //
之后的顺序类似如下:    
    checking regular excodession
    copying $1
    copying "/mp3/"
    copying $2
    copying ".mp3"
    completion of regular excodession
    completion of entire code

3.简单实验
[root@nginx nginx]# vim /etc/nginx/nginx.conf

[root@localhost html]# cat /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
# Load dynamic modules. See /usr/share/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
    worker_connections  1024;
}
http {
    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 default_server;
            server_name _;
            root /var/www/html;
            location / {
                    index index.html index.htm;
                    rewrite ^/bbs/(.*)$ http://192.168.11.10/forum/$1;
            }
    }
    access_log  /var/log/nginx/access.log  main;
    include /etc/nginx/conf.d/*.conf;
}

    
创建测试页:vim /var/www/html/forum/index.html //浏览器测试访问,查看状态码是否为302

永久重定向:
[root@nginx nginx]# vim /etc/nginx/nginx.conf

server {
    listen 80 default_server;
    server_name _;
    root /var/www/html;
    location / {
            index index.html index.htm;
            rewrite ^/bbs/(.*)$ http://192.168.11.10/forum/$1;
    }
}

五、Nginx之读写分离
1.实验拓扑
该实验,使用一台主机实现。分别为eth0配置别名实现
nginx:192.168.3.10:80
http:192.168.3.21:8888(rw)/192.168.3.22:8888(r)
WebDAV (Web-based Distributed Authoring and Versioning) 一种基于 HTTP 1.1协议的通信协议。
扩展了HTTP 1.1,在GET、POST、HEAD等几个HTTP标准方法以外添加了一些新的方法,使应用程序可直接对Web Server直接读写,并支持写文件锁定(Locking)及解锁(Unlock),还可以支持文件的版本控制。
2.nginx配置
[root@localhost conf.d]# cat /etc/nginx/nginx.conf
...

http {
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 192.168.3.10:80 default_server;
        server_name _;
        root /var/www/html;
        location / {
            index index.html index.htm;
            proxy_pass http://192.168.3.21:8888;
            if ($request_method = "PUT" ) {
                proxy_pass http://192.168.3.22:8888;
            }
        }
    }
    access_log  /var/log/nginx/access.log  main;
    include /etc/nginx/conf.d/*.conf;
}

[root@localhost conf.d]#
3.http配置
[root@localhost conf.d]# cat /etc/httpd/conf/httpd.conf
注释listen和DocumentRoot
[root@localhost conf.d]# vim /etc/httpd/conf.d/vhosts.conf

Listen 192.168.3.21:8888
Listen 192.168.3.22:8888
<VirtualHost 192.168.3.21:8888>
    ServerName 192.168.3.21
    DocumentRoot "/www/a.com"
    <Directory "/www/a.com">
        Dav on
    </Directory>
</VirtualHost>
<VirtualHost 192.168.3.22:8888>
    ServerName 192.168.3.22
    DocumentRoot "/www/b.com"
</VirtualHost>

4.创建测试页:
echo "192.168.3.21" > /www/a.com/index.html
echo "192.168.3.22" > /www/b.com/index.html
chmod -m u:apache:rw /www/a.com
 
[root@localhost conf.d]# curl -T /etc/issue http://192.168.3.22:8888

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>405 Method Not Allowed</title>
</head><body>
<h1>Method Not Allowed</h1>
<p>The requested method PUT is not allowed for the URL /issue.</p>
<hr>
<address>Apache/2.2.15 (CentOS) Server at 192.168.3.22 Port 8888</address>
</body></html>

[root@localhost conf.d]# curl -T /etc/issue http://192.168.3.21:8888 -I

HTTP/1.1 100 Continue
HTTP/1.1 204 No Content
Date: Wed, 28 Feb 2018 02:04:29 GMT
Server: Apache/2.2.15 (CentOS)
Connection: close
Content-Type: text/plain; charset=UTF-8

附件一:rewrite实现

1.
http{
    ....
    server {
        ...
        root /web/www/;  //root假如在server中没有指定,可以放在location中
        index index.html index.htm;
        location /status {
                stub_status;
        }
        location / {
                rewrite (.*)\.txt$ $1.html;
        }
    }
}
touch /web/www/test.html
nginx -s reload
https://www.mt.com/test.txt    //将被重定向为test.html
2.
    location / {
        root /web/www/;
        rewrite (.*)\.txt$ $1.html;
    }
    location ~* \.html$ {
        root html;
        index index.html;
        rewrite (.*)\.html $1.txt;
    }
    
https://www.mt.com/test.html
https://www.mt.com/test.txt$
//500 500 Internal Server Error //服务器端循环匹配
3.
    location / {
            root /web/www/;
            rewrite (.*)\.txt$ $1.html break;
    }
    location ~* \.html$ {
            root html;
            index index.html;
            rewrite (.*)\.html $1.txt break;
    }
https://www.mt.com/test.html //not found,因为根本没有test.html
https://www.mt.com/test.txt //可以访问
4.
    location / {
            root /web/www/;
            rewrite (.*)\.txt$ $1.html redirect;
    }
https://www.mt.com/test.txt //响应码为302
5.
     location / {
                root /web/www/;
                rewrite (.*)\.txt$ $1.html permanent;
        }
https://www.mt.com/test.txt //响应码为301


参考博客:

<https://blog.51cto.com/freeloda/1288553 >
<http://www.nginx.cn/doc/  >
<http://nginx.org/en/docs/>