Nginx 详细之反向代理、负载均衡、页面缓存、URL重写及读写分离详解

大纲

一、环境准备

二、编译安装Nginx

三、Nginx反向代理

四、Nginx负载均衡

五、Nginx缓存功能

六、Nginx之URL重写

七、Nginx读写分离






一、环境准备

系统环境

CentOS5.8 x86_64

172.16.1.101        nginx

172.16.1.102        web1

172.16.1.103        web2

软件包

nginx-1.8.0.tar.gz


1、时间同步

1
2
3
4
5
6
7
8
[root@nginx ~] # ntpdate s2c.time.edu.cn
20 Jan 10:20:44 ntpdate[31442]: adjust  time  server 202.112.10.36 offset -0.014753 sec
 
[root@web1 ~] # ntpdate s2c.time.edu.cn
20 Jan 10:12:53 ntpdate[31373]: adjust  time  server 202.112.10.36 offset -0.007873 sec
 
[root@web2 ~] # ntpdate s2c.time.edu.cn
20 Jan 10:12:46 ntpdate[4132]: step  time  server 202.112.10.36 offset 1432097.703563 sec

2、关闭iptables和selinux

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
nginx
[root@nginx ~] # service iptables stop
[root@nginx ~] # chkconfig iptables off
[root@nginx ~] # sed -r -i  "s/^(SELINUX=).*/\1permissive/g" /etc/sysconfig/selinux
[root@nginx ~] # setenforce 0
[root@nginx ~] # getenforce 
Permissive
 
web1
[root@web1 ~] # service iptables stop
[root@web1 ~] # chkconfig iptables off
[root@web1 ~] # sed -r -i  "s/^(SELINUX=).*/\1permissive/g" /etc/sysconfig/selinux
[root@web1 ~] # setenforce 0
[root@web1 ~] # getenforce 
Permissive
 
web2
[root@web2 ~] # service iptables stop
[root@web2 ~] # chkconfig iptables off
[root@web2 ~] # sed -r -i  "s/^(SELINUX=).*/\1permissive/g" /etc/sysconfig/selinux
[root@web2 ~] # setenforce 0
[root@web2 ~] # getenforce 
Permissive

3、下载所需的软件包

1
2
nginx
[root@nginx ~] # wget http://nginx.org/download/nginx-1.8.0.tar.gz


二、编译安装Nginx

1、解决依赖关系

1
2
[root@nginx ~] # yum groupinstall -y "Development Tools" "Development Libraries"
[root@nginx ~] # yum install openssl-devel pcre-devel

2、创建nginx用户和组

1
2
[root@nginx ~] # groupadd -r nginx 
[root@nginx ~] # useradd -r -g nginx nginx

3、编译安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
[root@nginx ~] # tar xf nginx-1.8.0.tar.gz 
[root@nginx ~] # cd nginx-1.8.0
[root@nginx nginx-1.8.0] # ls
auto  CHANGES  CHANGES.ru  conf  configure  contrib  html  LICENSE  Makefile   man   objs  README  src
 
[root@nginx nginx-1.8.0] # ./configure \
   --prefix= /usr  \
   --sbin-path= /usr/sbin/nginx  \
   --conf-path= /etc/nginx/nginx .conf \
   --error-log-path= /var/log/nginx/error .log \
   --http-log-path= /var/log/nginx/access .log \
   --pid-path= /var/run/nginx/nginx .pid  \
   --lock-path= /var/lock/nginx .lock \
   --user=nginx \
   --group=nginx \
   --with-http_ssl_module \
   --with-http_flv_module \
   --with-http_stub_status_module \
   --with-http_gzip_static_module \
   --http-client-body-temp-path= /var/tmp/nginx/client/  \
   --http-proxy-temp-path= /var/tmp/nginx/proxy/  \
   --http-fastcgi-temp-path= /var/tmp/nginx/fcgi/  \
   --http-uwsgi-temp-path= /var/tmp/nginx/uwsgi  \
   --http-scgi-temp-path= /var/tmp/nginx/scgi  \
   --with-pcre
 
显示我们自定义的配置信息和编译选项
Configuration summary
   + using system PCRE library
   + using system OpenSSL library
   + md5: using OpenSSL library
   + sha1: using OpenSSL library
   + using system zlib library
 
   nginx path prefix:  "/usr"
   nginx binary  file "/usr/sbin/nginx"
   nginx configuration prefix:  "/etc/nginx"
   nginx configuration  file "/etc/nginx/nginx.conf"
   nginx pid  file "/var/run/nginx/nginx.pid"
   nginx error log  file "/var/log/nginx/error.log"
   nginx http access log  file "/var/log/nginx/access.log"
   nginx http client request body temporary files:  "/var/tmp/nginx/client/"
   nginx http proxy temporary files:  "/var/tmp/nginx/proxy/"
   nginx http fastcgi temporary files:  "/var/tmp/nginx/fcgi/"
   nginx http uwsgi temporary files:  "/var/tmp/nginx/uwsgi"
   nginx http scgi temporary files:  "/var/tmp/nginx/scgi"
 
编译安装
[root@nginx nginx-1.8.0] # make && make install
 
补充:
Nginx可以使用Tmalloc(快速、多线程的malloc库及优秀性能分析工具)来加速内存分配
使用此功能需要事先安装gperftools,而后在编译nginx添加--with-google_perftools_module选项即可

4、为nginx提供SysV init脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
[root@nginx nginx-1.8.0] # vim /etc/rc.d/init.d/nginx
#!/bin/sh
#
# nginx - this script starts and stops the nginx daemon
#
# chkconfig:   - 85 15 
# description:  Nginx is an HTTP(S) server, HTTP(S) reverse \
#               proxy and IMAP/POP3 proxy server
# processname: nginx
# config:      /etc/nginx/nginx.conf
# config:      /etc/sysconfig/nginx
# pidfile:     /var/run/nginx.pid
  
# Source function library.
/etc/rc .d /init .d /functions
  
# Source networking configuration.
/etc/sysconfig/network
  
# Check that networking is up.
"$NETWORKING"  "no"  ] &&  exit  0
  
nginx= "/usr/sbin/nginx"
prog=$( basename  $nginx)
  
NGINX_CONF_FILE= "/etc/nginx/nginx.conf"
  
[ -f  /etc/sysconfig/nginx  ] && .  /etc/sysconfig/nginx
  
lockfile= /var/lock/subsys/nginx
  
make_dirs() {
    # make required directories
    user=`nginx -V 2>&1 |  grep  "configure arguments:"  sed  's/[^*]*--user=\([^ ]*\).*/\1/g'  -`
    options=`$nginx -V 2>&1 |  grep  'configure arguments:' `
    for  opt  in  $options;  do
        if  [ ` echo  $opt |  grep  '.*-temp-path' ` ];  then
            value=` echo  $opt |  cut  -d  "="  -f 2`
            if  [ ! -d  "$value"  ];  then
                # echo "creating" $value
                mkdir  -p $value &&  chown  -R $user $value
            fi
        fi
    done
}
  
start() {
     [ -x $nginx ] ||  exit  5
     [ -f $NGINX_CONF_FILE ] ||  exit  6
     make_dirs
     echo  -n $ "Starting $prog: "
     daemon $nginx -c $NGINX_CONF_FILE
     retval=$?
     echo
     [ $retval - eq  0 ] &&  touch  $lockfile
     return  $retval
}
  
stop() {
     echo  -n $ "Stopping $prog: "
     killproc $prog -QUIT
     retval=$?
     echo
     [ $retval - eq  0 ] &&  rm  -f $lockfile
     return  $retval
}
  
restart() {
     configtest ||  return  $?
     stop
     sleep  1
     start
}
  
reload() {
     configtest ||  return  $?
     echo  -n $ "Reloading $prog: "
     killproc $nginx -HUP
     RETVAL=$?
     echo
}
  
force_reload() {
     restart
}
  
configtest() {
   $nginx -t -c $NGINX_CONF_FILE
}
  
rh_status() {
     status $prog
}
  
rh_status_q() {
     rh_status > /dev/null  2>&1
}
  
case  "$1"  in
     start)
         rh_status_q &&  exit  0
         $1
         ;;
     stop)
         rh_status_q ||  exit  0
         $1
         ;;
     restart|configtest)
         $1
         ;;
     reload)
         rh_status_q ||  exit  7
         $1
         ;;
     force-reload)
         force_reload
         ;;
     status)
         rh_status
         ;;
     condrestart|try-restart)
         rh_status_q ||  exit  0
             ;;
     *)
         echo  $ "Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}"
         exit  2
esac
 
添加执行权限,并加入到服务列表中
[root@nginx nginx-1.8.0] # chmod +x /etc/rc.d/init.d/nginx
[root@nginx nginx-1.8.0] # chkconfig --add nginx
[root@nginx nginx-1.8.0] # chkconfig nginx on
[root@nginx nginx-1.8.0] # chkconfig --list nginx
nginx             0:off   1:off   2:on    3:on    4:on    5:on    6:off

5、启动Nginx服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@nginx nginx-1.8.0] # service nginx start
Starting nginx:                                            [  OK  ]
 
查看80端口是否处于监听状态
[root@nginx nginx-1.8.0] # netstat -tnlp 
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address      Foreign Address    State       PID /Program  name   
tcp        0      0 0.0.0.0:111        0.0.0.0:*          LISTEN      2820 /portmap        
tcp        0      0 0.0.0.0:80         0.0.0.0:*          LISTEN      30414 /nginx         
tcp        0      0 0.0.0.0:22         0.0.0.0:*          LISTEN      25126 /sshd          
tcp        0      0 0.0.0.0:922        0.0.0.0:*          LISTEN      2860 /rpc .statd      
tcp        0      0 127.0.0.1:6011     0.0.0.0:*          LISTEN      24814 /sshd          
tcp        0      0 :::22              :::*               LISTEN      25126 /sshd          
tcp        0      0 ::1:6011           :::*               LISTEN      24814 /sshd

6、测试访问

wKiom1ae8TPSLd3uAAOnKmz9hgc096.jpg

三、Nginx反向代理

1、首先准备一个web服务器,这里以web1演示

1
2
首先安装web服务,这里使用yum安装httpd,以httpd作为web服务器
[root@web1 ~] # yum install -y httpd

2、配置并启动httpd服务,测试能正常访问

1
2
3
4
5
6
7
8
9
10
11
创建目录,配置页面文件
[root@web1 ~] # mkdir /var/www/html/bbs
[root@web1 ~] # echo "<h1>Forum On Apache Server</h1>" > var/www/html/bbs/index.html 
 
启动httpd服务
[root@web1 ~] # service httpd start
Starting httpd:                                            [  OK  ]
 
测试自己能否访问,当前web1的ip地址就是172.16.1.102
[root@web1 ~] # curl http://172.16.1.102/bbs/
<h1>Forum On Apache Server< /h1 >

3、配置Nginx作为反向代理

1
2
3
4
5
6
7
8
9
这是切换到nginx主机,配置其作为反向代理服务器
[root@nginx ~] # hostname 
nginx
 
编辑配置文件,加入下面三行至server段中
[root@nginx ~] # vim /etc/nginx/nginx.conf
location  /forum  {
      proxy_pass http: //172 .16.1.102 /bbs ;
}

4、用浏览器测试访问

wKiom1afIxKwcVsVAAGvETV8jrE506.jpg

1
2
3
4
5
6
7
8
9
10
11
12
13
再来看web1上的访问日志
[root@web1 ~] # tail /var/log/httpd/access_log
172.16.1.101 - - [20 /Jan/2016 :13:57:21 +0800]  "GET /bbs/ HTTP/1.0"  200 32  "-"  "Mozilla /5 .0 
(Windows NT 6.1; WOW64) AppleWebKit /537 .36 (KHTML, like Gecko) Chrome /47 .0.2526.106 Safari /537 .36"
 
可以看到源ip是nginx反向代理并不是我们真正的客户端,但是有时候我们需要记录真正的client便于做日志分析
此时我们只需要添加proxy模块的proxy_set_header指令即可实现,此指令的语法格式如下
 
Syntax: proxy_set_header field value;
Default:   
proxy_set_header Host $proxy_host;
proxy_set_header Connection close;
Context:    http, server, location

5、配置Nginx反向代理和web服务器,使web服务器能够记录真实客户端ip地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
编辑配置文件,修改反向代理location那一段如下
[root@nginx ~] # vim /etc/nginx/nginx.conf
location  /forum  {
        proxy_pass http: //172 .16.1.102 /forum/ ;
        proxy_set_header  X-Real-IP $remote_addr;         # 其实就是添加此行
}
 
而后重新载入Nginx代理服务器
[root@nginx nginx] # service nginx reload
nginx: the configuration  file  /etc/nginx/nginx .conf syntax is ok
nginx: configuration  file  /etc/nginx/nginx .conf  test  is successful
Reloading nginx:                                           [  OK  ]
 
再来用浏览器访问一下,可以看到仍然没有记录真实客户端的ip地址
[root@web1 ~] # tail /var/log/httpd/access_log
172.16.1.101 - - [20 /Jan/2016 :13:57:21 +0800]  "GET /bbs/ HTTP/1.0"  200 32  "-"  "Mozilla /5 .0 
(Windows NT 6.1; WOW64) AppleWebKit /537 .36 (KHTML, like Gecko) Chrome /47 .0.2526.106 Safari /537 .36"
172.16.1.101 - - [20 /Jan/2016 :13:58:03 +0800]  "GET /bbs/ HTTP/1.0"  200 32  "-"  "Mozilla /5 .0 
(Windows NT 6.1; WOW64) AppleWebKit /537 .36 (KHTML, like Gecko) Chrome /47 .0.2526.106 Safari /537 .36"
因为我们web服务器访问日志记录格式中第一项记录的请求客户端的地址,也就是我们的Nginx反向代理服务器地址
 
修改web服务器端的访问日志格式,修改之前先备份原有的combined模式并注释,将第一个%h修改为%{X-Real-IP}i即可
[root@web1 ~] # vim /etc/httpd/conf/httpd.conf
#LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat  "%{X-Real-IP}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""  combined
 
然后重启httpd服务或是重新载入都可以
[root@web1 ~] # service httpd restart
Stopping httpd:                                            [  OK  ]
Starting httpd:                                            [  OK  ]
 
再用浏览器访问一下然后看httpd服务器的访问日志
[root@web1 ~] # tail /var/log/httpd/access_log
172.16.1.101 - - [20 /Jan/2016 :13:57:21 +0800]  "GET /bbs/ HTTP/1.0"  200 32  "-"  "Mozilla /5 .0 
(Windows NT 6.1; WOW64) AppleWebKit /537 .36 (KHTML, like Gecko) Chrome /47 .0.2526.106 Safari /537 .36"
172.16.1.101 - - [20 /Jan/2016 :13:58:03 +0800]  "GET /bbs/ HTTP/1.0"  200 32  "-"  "Mozilla /5 .0 
(Windows NT 6.1; WOW64) AppleWebKit /537 .36 (KHTML, like Gecko) Chrome /47 .0.2526.106 Safari /537 .36"
172.16.1.100 - - [20 /Jan/2016 :14:09:28 +0800]  "GET /bbs/ HTTP/1.0"  200 32  "-"  "Mozilla /5 .0 
(Windows NT 6.1; WOW64) AppleWebKit /537 .36 (KHTML, like Gecko) Chrome /47 .0.2526.106 Safari /537 .36"
可以看到客户端真实ip已经记录,这个172.16.1.100就是我自己物理主机的地址


四、Nginx负载均衡

1、准备两台web服务器,配置好页面并进行本地测试。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
web1在上面反向代理的示例中已经安装了httpd,这里不需要再安装,只是配置好主页并测试即可
[root@web1 ~] # echo "<h1>web1</h1>" > /var/www/html/index.html
[root@web1 ~] # service httpd restart
Stopping httpd:                                            [  OK  ]
Starting httpd:                                            [  OK  ]
[root@web1 ~] # curl localhost
<h1>web1< /h1 >
 
web2
[root@web2 ~] # yum install -y httpd 
[root@web2 ~] # echo "<h1>web2</h1>" > /var/www/html/index.html
[root@web2 ~] # service httpd start
Starting httpd:                                            [  OK  ]
[root@web2 ~] # curl localhost
<h1>web2< /h1 >

2、配置Nginx提供负载均衡功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
首先定义一个upstream组,注意,此upstream需定义在server段之外
[root@nginx nginx] # pwd
/etc/nginx
[root@nginx nginx] # vim nginx.conf
upstream webservers {
         server 172.16.1.102 weight=1;
         server 172.16.1.103 weight=1;
     
然后再修改location段为如下所示
location / {
         proxy_pass http: //webservers ;
         proxy_set_header  X-Real-IP $remote_addr;
 
重新载入nginx
[root@nginx nginx] # service nginx reload
nginx: the configuration  file  /etc/nginx/nginx .conf syntax is ok
nginx: configuration  file  /etc/nginx/nginx .conf  test  is successful
Reloading nginx:                                           [  OK  ]

用浏览器访问一下

wKiom1afLq2TWefzAAFOuG03aWc963.jpg


再刷新一下

wKiom1afLq7jgbn7AAFRfsE81eI677.jpg

可以看到,已经实现了简单的负载均衡效果


3、为Nginx增加上游服务器的健康状态监测功能

1
2
3
4
5
6
7
8
9
10
11
12
修改配置文件中upstream段为如下所示
[root@nginx nginx] # vim nginx.conf    
upstream webservers {
         server 172.16.1.102 weight=1 max_fails=2 fail_timeout=2s;
         server 172.16.1.103 weight=1 max_fails=2 fail_timeout=2s;
}
 
然后重新载入nginx
[root@nginx nginx] # service nginx reload
nginx: the configuration  file  /etc/nginx/nginx .conf syntax is ok
nginx: configuration  file  /etc/nginx/nginx .conf  test  is successful
Reloading nginx:                                           [  OK  ]

用浏览器访问一下

wKiom1afLq2TWefzAAFOuG03aWc963.jpg

再刷新一下

wKiom1afLq7jgbn7AAFRfsE81eI677.jpg

此时停止web1上的httpd服务,一直刷新,显示的一直都是web2

1
2
[root@web1 ~] # service httpd stop
Stopping httpd:                                            [  OK  ]

wKiom1afLq7jgbn7AAFRfsE81eI677.jpg

再让web1上的httpd服务启动起来,可以看到,web1重新被加入进来了

1
2
[root@web1 ~] # service httpd start
Starting httpd:                                            [  OK  ]

wKiom1afLq2TWefzAAFOuG03aWc963.jpg

再刷新一下

wKiom1afLq7jgbn7AAFRfsE81eI677.jpg

4、为Nginx增加sorry_server

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
修改配置文件中upstream段为如下所示
[root@nginx nginx] # vim nginx.conf    
upstream webservers {
         server 172.16.1.102 weight=1 max_fails=2 fail_timeout=2s;
         server 172.16.1.103 weight=1 max_fails=2 fail_timeout=2s;
         server 127.0.0.1:8080 backup;
}
 
再在配置文件中定义一个server
server {
         listen 8080;
         server_name localhost;
         root  /var/www/mantainance ;
         index index.html;
}
 
接着创建维护页面目录及文件
[root@nginx nginx] # mkdir /var/www/mantainance
[root@nginx nginx] # echo "<h1>Mantainance Time</h1>" > /var/www/mantainance/index.html
 
然后重新载入nginx
[root@nginx nginx] # nginx -t
nginx: the configuration  file  /etc/nginx/nginx .conf syntax is ok
nginx: configuration  file  /etc/nginx/nginx .conf  test  is successful
[root@nginx nginx] # service nginx reload
nginx: the configuration  file  /etc/nginx/nginx .conf syntax is ok
nginx: configuration  file  /etc/nginx/nginx .conf  test  is successful
Reloading nginx:                                           [  OK  ]
 
此时停掉web1和web2上的httpd服务
[root@web1 ~] # service httpd stop
Stopping httpd:                                            [  OK  ]
[root@node2 ~] # service httpd stop
Stopping httpd:                                            [  OK  ]
 
再使用浏览器访问一下

wKioL1afOHLS78YGAAFtvlm_suM136.jpg

1
2
3
4
5
此时再上线web1
[root@web1 ~] # service httpd start
Starting httpd:                                            [  OK  ]
 
浏览器刷新

wKioL1afN5TgPG0BAAFOuG03aWc914.jpg

1
2
3
4
5
再上线web2
[root@web2 ~] # service httpd start
Starting httpd:                                            [  OK  ]
 
浏览器刷新

wKiom1afN1rydqd_AAFRfsE81eI007.jpg

可以看到,当所有的web服务器都宕机时,Nginx自身会加入sorry_server

1
2
3
4
5
6
7
补充知识1
nginx支持三种调度算法:ip_hash(相当于LVS的sh),round_robin(相当于LVS的rr和wrr),least_conn(相当于LVS的lc)
要想使用ip_hash算法,直接在upstream段中定义ip_hash即可,但是用ip_hash时,不能定义sorry_server
 
补充知识2
统计80端口服务的每种连接状态数目
[root@nginx nginx] # netstat -tan | awk '/:80\>/{S[$NF]++}END{for(A in S) {print A,S[A]}}'


五、Nginx缓存功能

1、缓存功能模块相关指令介绍

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Nginx的缓存功能也是跟反向代理功能使用的是同一个模块:ngx_http_proxy_module
Nginx的缓存由两个部分组成
     共享内存:存储键和缓存对象元数据
     磁盘空间:缓存数据
 
缓存功能所用到的几个常用指令语法如下
1、proxy_cache
Syntax: proxy_cache zone | off;
Default:   
proxy_cache off;
Context:    http, server, location
zone指的是启用某个共享内存区域的缓存功能
 
2、proxy_cache_path
Syntax: proxy_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size 
[inactive= time ] [max_size=size] [loader_files=number] [loader_sleep= time ] [loader_threshold= time
[purger=on|off] [purger_files=number] [purger_sleep= time ] [purger_threshold= time ];
Default:    —
Context:    http
path指的是缓存数据的存储路径
levels指的是nginx的缓存目录层次级别,最多有3级,并且每级最多用2个字符定义
keys_zone指的是缓存的共享内存名称,也是proxy_cache后面所引用的名称,size指明这段共享内存区域大小
max_size指的是缓存数据的磁盘空间大小
 
3、proxy_cache_valid
Syntax: proxy_cache_valid [code ...]  time ;
Default:    —
Context:    http, server, location
code指的是http响应报文的状态码
time 指的是对于某种code所缓存的时长

2、为Nginx增加缓存功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
首先编辑配置文件,定义proxy_cache_path,此指令跟upstream指令一样需定义在server段之外
[root@nginx nginx] # vim nginx.conf
proxy_cache_path  /nginx/cache/first  levels=1:2 keys_zone=first:20m max_size=1g;
 
上面只是定义缓存功能,但是还没有启用,所以我们需要在某个location中定义明确启用哪个缓存
[root@nginx nginx] # vim nginx.conf
location / {
             proxy_pass http: //webservers ;
             proxy_set_header  X-Real-IP $remote_addr;
             proxy_cache first;             # proxy_cache后面跟的是keys_zone中所定义的名称 
             proxy_cache_valid 200 10m;     # 表示响应报文状态码为200的缓存10分钟      
}
 
检查是否有语法错误
[root@nginx nginx] # nginx -t
nginx: the configuration  file  /etc/nginx/nginx .conf syntax is ok
nginx: [emerg]  mkdir ()  "/nginx/cache/first"  failed (2: No such  file  or directory)
nginx: configuration  file  /etc/nginx/nginx .conf  test  failed
 
创建缓存目录
[root@nginx nginx] # mkdir -pv /nginx/cache/first
mkdir : created directory ` /nginx '
mkdir : created directory ` /nginx/cache '
mkdir : created directory ` /nginx/cache/first '
 
检查是否有语法错误
[root@nginx nginx] # nginx -t
nginx: the configuration  file  /etc/nginx/nginx .conf syntax is ok
nginx: configuration  file  /etc/nginx/nginx .conf  test  is successful
 
重新载入nginx
[root@nginx nginx] # service nginx reload
nginx: the configuration  file  /etc/nginx/nginx .conf syntax is ok
nginx: configuration  file  /etc/nginx/nginx .conf  test  is successful
Reloading nginx:                                           [  OK  ]

3、测试Nginx的缓存功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
为了方便测试是否命中缓存,在配置文件中的server段中定义一个指令
[root@nginx nginx] # vim nginx.conf
         add_header X-Cache  "$upstream_cache_status from $server_addr" ;
 
检查是否有语法错误
[root@nginx nginx] # nginx -t
nginx: the configuration  file  /etc/nginx/nginx .conf syntax is ok
nginx: configuration  file  /etc/nginx/nginx .conf  test  is successful
 
重新载入nginx
[root@nginx nginx] # service nginx reload
nginx: the configuration  file  /etc/nginx/nginx .conf syntax is ok
nginx: configuration  file  /etc/nginx/nginx .conf  test  is successful
Reloading nginx:                                           [  OK  ]        
         
首先查看我们的缓存目录,可以看到此时是空的,里面并没有缓存任何内容
[root@nginx nginx] # ls /nginx/cache/first/f/63/
 
接着用浏览器访问看看,此时是第一次访问,所以是X-Cache为MISS

wKioL1afmBHDJzlCAAPNkE_1Rbw689.jpg

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
此时再次查看缓存目录,可以看到缓存已经有了
[root@nginx nginx] # cat /nginx/cache/first/f/63/681ad4c77694b65d61c9985553a2763f 
aVn.VRVh3 "c04fd-e-529be6a44b2a8"
KEY: http: //webservers/
HTTP /1 .1 200 OK
Date: Wed, 20 Jan 2016 13:53:22 GMT
Server: Apache /2 .2.15 (CentOS)
Last-Modified: Wed, 20 Jan 2016 06:51:26 GMT
ETag:  "c04fd-e-529be6a44b2a8"
Accept-Ranges: bytes
Content-Length: 14
Connection: close
Content-Type: text /html ; charset=UTF-8
 
<h1>web1< /h1 >
 
再刷新一下浏览器,可以看到我们始终是被定向至web2
因为我们在配置文件中定义了对于状态码为200的缓存10m,并且此时X-Cache显示为命中

wKioL1afmGCD_WehAAOwiqkk9ys039.jpg

1
2
3
4
5
补充知识:
Nginx常用的三种缓存
     open_log_cache:日志缓存,可以降低磁盘io
     open_file_cache:文件缓存,加速nginx响应过程
     fastcgi_cache:后端应用程序服务器生成的结果缓存,这个要慎用


六、Nginx之URL重写

1、编辑配置文件,定义rewrite规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
这里为了不受上面负载均衡的示例,恢复配置文件到最初安装nginx时候的状态
[root@nginx ~] # cd /etc/nginx/
[root@nginx nginx] # mv nginx.conf{,.back}
[root@nginx nginx] # cp nginx.conf.default nginx.conf
 
编辑配置文件,在location段中增加如下rewrite一行
[root@nginx nginx] # vim nginx.conf    
location / {
             root   html;
             index  index.html index.htm;
             rewrite ^ /bbs/ (.*)$ http: //172 .16.1.102 /forum/ $1;
}
 
测试是否有语法错误
[root@nginx nginx] # nginx -t
nginx: the configuration  file  /etc/nginx/nginx .conf syntax is ok
nginx: configuration  file  /etc/nginx/nginx .conf  test  is successful
 
重新载入nginx
[root@nginx nginx] # service nginx reload
nginx: the configuration  file  /etc/nginx/nginx .conf syntax is ok
nginx: configuration  file  /etc/nginx/nginx .conf  test  is successful
Reloading nginx:                                           [  OK  ]

2、在web服务器上配置好相应的目录及页面文件

1
2
3
4
5
6
7
8
9
[root@web1 ~] # cd /var/www/html/
[root@web1 html] # ls
index.html
[root@web1 html] # mkdir forum
[root@web1 html] # echo "<h1>Forum On Apache Server</h1>" > forum/index.html
 
本地测试访问一下
[root@web1 html] # curl http://172.16.1.102/forum/
<h1>Forum On Apache Server< /h1 >

3、浏览器访问测试

在浏览器地址栏中输入http://172.16.1.101/bbs,页面直接被重定向至172.16.1.102/forum

wKiom1afsivjqj-GAARh_oE-UMI348.jpg

4、配置永久重定向

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Nginx编辑配置文件,将rewrite一行修改为如下所示
[root@nginx nginx] # vim nginx.conf
             rewrite ^ /bbs (.*)$  /forum/ $1;
 
本地配置好forum目录及页面文件           
[root@nginx ~] # cd /usr/html/
[root@nginx html] # ls
50x.html  index.html
[root@nginx html] # mkdir forum
[root@nginx html] # echo "<h1>Forum On Nginx Server</h1>" > forum/index.html
 
测试是否有语法错误
[root@nginx nginx] # nginx -t
nginx: the configuration  file  /etc/nginx/nginx .conf syntax is ok
nginx: configuration  file  /etc/nginx/nginx .conf  test  is successful
 
重新载入nginx
[root@nginx nginx] # service nginx reload
nginx: the configuration  file  /etc/nginx/nginx .conf syntax is ok
nginx: configuration  file  /etc/nginx/nginx .conf  test  is successful
Reloading nginx:                                           [  OK  ]

5、浏览器访问测试

在浏览器地址栏中输入http://172.16.1.101/bbs,可以看到Status code为200,这种也叫隐形重定向一般跨服务器的是临时重定向,服务器内部的则是永久重定向。

wKioL1aftHKwfto7AAROHHVJmsw851.jpg


七、Nginx读写分离

1、需求分析及拓扑图

需求分析

构建一个论坛,前端是个Nginx,实现读写分离,将用户的写请求(上传附件之类的操作)定向至web1,读请求定向至web2。web1和web2之间使用rsync+inotify或者sersync同步用户上传的文件,从而实现用户不管被定向至哪个web服务器,都能访问到自己之前上传的文件

拓扑图

wKioL1agWBCxZO_EAAIzVE4BaBY329.jpg

2、WebDAV概念介绍

WebDAV (Web-based Distributed Authoring and Versioning) 一种基于 HTTP 1.1协议的通信协议。它扩展了HTTP 1.1,在GET、POST、HEAD等几个HTTP标准方法以外添加了一些新的方法,使应用程序可直接对Web Server直接读写,并支持写文件锁定(Locking)及解锁(Unlock),还可以支持文件的版本控制。


3、修改web1的配置文件,使其支持put方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
修改配置文件,启用如下两个模块
[root@web1 ~] # vim /etc/httpd/conf/httpd.conf 
LoadModule dav_module modules /mod_dav .so
LoadModule dav_fs_module modules /mod_dav_fs .so
 
再在网页的根目录即Directory段中定义一个Dav指令
<Directory  "/var/www/html" >
Dav on
     Options Indexes FollowSymLinks
     AllowOverride None
     Order allow,deny
     Allow from all
< /Directory >
 
测试语法是否有错误
[root@web1 ~] # httpd -t
Syntax OK
 
重新启动httpd服务
[root@web1 ~] # service httpd restart
Stopping httpd:                                            [  OK  ]
Starting httpd:                                            [  OK  ]

4、测试两个web是否支持读和写请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
测试两个web的读请求是否正常
[root@web1 ~] # curl http://172.16.1.102
<h1>web1< /h1 >
[root@web1 ~] # curl http://172.16.1.103
<h1>web2< /h1 >
 
测试web1是否能够支持写请求,也就是上传操作
[root@web1 ~] # curl -T /etc/fstab http://172.16.1.102
<!DOCTYPE HTML PUBLIC  "-//IETF//DTD HTML 2.0//EN" >
<html>< head >
<title>403 Forbidden< /title >
< /head ><body>
<h1>Forbidden< /h1 >
<p>You don't have permission to access  /fstab
on this server.< /p >
<hr>
<address>Apache /2 .2.15 (CentOS) Server at 172.16.1.102 Port 80< /address >
< /body >< /html >
 
提示403 Forbidden,没有权限
因为 /var/www/html 的属主属组是root,而运行httpd服务的是apache用户,加上写权限即可
[root@web1 ~] # setfacl -m u:apache:rwx /var/www/html/
 
可以看到状态码为201,并且文件已经上传到了172.16.1.102上,也就是我们定义的那个能写的web服务器
[root@web1 ~] # curl  -T /etc/issue http://172.16.1.102
<!DOCTYPE HTML PUBLIC  "-//IETF//DTD HTML 2.0//EN" >
<html>< head >
<title>201 Created< /title >
< /head ><body>
<h1>Created< /h1 >
<p>Resource  /issue  has been created.< /p >
<hr />
<address>Apache /2 .2.15 (CentOS) Server at 172.16.1.102 Port 80< /address >
< /body >< /html >
 
测试是否成功上传
[root@web1 ~] # curl http://172.16.1.102/issue
CentOS release 6.5 (Final)
Kernel \r on an \m
 
再来测试web2是否能够支持写请求,我们的目的是web1能上传,web2不能上传,只能读
[root@web1 ~] # curl -T /etc/fstab http://172.16.1.103
<!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  /fstab .< /p >
<hr>
<address>Apache /2 .2.15 (CentOS) Server at 172.16.1.103 Port 80< /address >
< /body >< /html >
可以看到状态码为405而不是403,说不支持这种方法,因为我们在httpd的配置文件并没有定义它可以上传

5、修改前端Nginx配置,使其实现读写分离功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
编辑配置文件,在location段中定义
[root@nginx ~] # vim /etc/nginx/nginx.conf
location / {
             proxy_pass http: //172 .16.1.103;
             if  ($request_method =  "PUT" ) {
                 proxy_pass http: //172 .16.1.102;
             }
}
 
测试是否有语法错误
[root@nginx ~] # nginx -t
nginx: the configuration  file  /etc/nginx/nginx .conf syntax is ok
nginx: configuration  file  /etc/nginx/nginx .conf  test  is successful
 
重新载入nginx
[root@nginx ~] # service nginx reload
nginx: the configuration  file  /etc/nginx/nginx .conf syntax is ok
nginx: configuration  file  /etc/nginx/nginx .conf  test  is successful
Reloading nginx:                                           [  OK  ]

6、测试Nginx的读写分离功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
首先测试读请求,可以看到我们的读请求被定向至web2上
[root@nginx nginx] # curl http://172.16.1.101
<h1>web2< /h1 >
[root@nginx nginx] # curl http://172.16.1.101
<h1>web2< /h1 >
[root@nginx nginx] # curl http://172.16.1.101
<h1>web2< /h1 >
[root@nginx nginx] # curl http://172.16.1.101
<h1>web2< /h1 >
[root@nginx nginx] # curl http://172.16.1.101
<h1>web2< /h1 >
 
再来测试写请求
[root@nginx ~] # curl -T /etc/fstab http://172.16.1.101
<!DOCTYPE HTML PUBLIC  "-//IETF//DTD HTML 2.0//EN" >
<html>< head >
<title>201 Created< /title >
< /head ><body>
<h1>Created< /h1 >
<p>Resource  /fstab  has been created.< /p >
<hr />
<address>Apache /2 .2.15 (CentOS) Server at 172.16.1.102 Port 80< /address >
< /body >< /html >
 
访问测试一下
[root@nginx ~] # curl http://172.16.1.102/fstab
 
#
# /etc/fstab
# Created by anaconda on Fri Aug 28 10:30:25 2015
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/vg_centos6-lv_root  /                       ext4    defaults        1 1
UUID=7a79d653-e9b7-43f2-a2c1-e41af29b3f5d  /boot                    ext4    defaults        1 2
/dev/mapper/vg_centos6-lv_swap  swap                    swap    defaults        0 0
tmpfs                    /dev/shm                 tmpfs   defaults        0 0
devpts                   /dev/pts                 devpts  gid=5,mode=620  0 0
sysfs                    /sys                     sysfs   defaults        0 0
proc                     /proc                    proc    defaults        0 0
/dev/myvg/mydata    /mydata         ext4    defaults    0 0
可以看到已经成功上传到了web1上,此时就实现了读写分离功能
我这里只使用了一个读服务器,其实可以定义一组服务器用作读,Nginx同时实现读写分离和负载均衡

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值