Nginx反向代理和缓存服务功能说明和简单实现 - 运维笔记

 

一、Nginx反向代理功能
Nginx不仅能作为Web Server,还具有反向代理、负载均衡和缓存的功能。下面就简单说下这些功能:

1、proxy模块
nginx通过proxy模块实现将客户端的请求代理至上游服务器,此时nginx与上游服务器的连接是通过http协议进行的。nginx在实现反向代理功能时的最重要指令为 proxy_pass,它能够并能够根据URI、客户端参数或其它的处理逻辑将用户请求调度至上游服务器上(upstream server)。

1.1  proxy_pass URL;
设置后端服务器的协议和地址;这条指令可以设置的协议是“http”或者“https”,而地址既可以使用域名或者IP地址加端口(可选)的形式来定义:

1
proxy_pass http://localhost:8000/uri/;

如果解析一个域名得到多个地址,所有的地址都会以轮转的方式被使用。当然也可以使用服务器组来定义多个地址。

如果proxy_pass没有使用URI,传送到后端服务器的请求URI一般是客户端发起的原始URI,如果nginx改变了请求URI,则请求路径与配置中的路径的匹配部分将被替换为指令中定义的URI:若nginx接到的请求的uri是/name/a.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#传送到后端服务器的URI是/remote/a.html
 location /name/ {
      proxy_pass http://172.16.60.20/remote/;
  }                  
========================================================
 
#传送到后端服务器的URI是/name/a.html
location /name/ {
      proxy_pass http://172.16.60.20;
  }
 
========================================================
#注意与上面用法的区别,这里地址末尾带有斜线,实际上被认为定义了URI,该“/”会替换“/name/",传送到后端服务器的URI是/a.html。
location /name/ {
 
      proxy_pass http://172.16.60.20/;
 
   }             

如果使用正则表达式定义路径,则proxy_pass指令不应使用URI。例如:

1
2
3
location ~ ^/mmb {
  proxy_pass http://www.kevin.com;
    }

 在需要代理的路径中,使用rewrite指令改变了URI,那么nginx将使用重写后的URI处理请求,而忽略proxy_pass指令设置的URI。如下面所示的例子中,传送给上游服务器的URI为/index.php?page=<match>。

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

1.2  proxy模块的其它指令
① proxy_connect_timeout time;
与后端服务器建立连接的超时时间。一般不可能大于75秒;

② proxy_cookie_domain off;
取消当前配置级别的所有proxy_cookie_domain指令;
如果配置,则格式为:proxy_cookie_domain domain replacement(替代),即设置"Set-Cookie"响应头中的domain属性的替换文本,其值可以为一个字符串、正则表达式的模式或一个引用的变量;例如:

1
proxy_cookie_domain localhost example.org;

浏览器对 Cookie 有很多限制,如果 Cookie 的 Domain 部分与当前页面的 Domain 不匹配就无法写入。所以如果请求 A 域名,服务器 proxy_pass 到 B 域名,然后 B 服务器输出 Domian=B 的 Cookie,前端的页面依然停留在 A 域名上,于是浏览器就无法将 Cookie 写入。

不仅是域名,浏览器对 Path 也有限制。我们经常会 proxy_pass 到目标服务器的某个 Path 下,不把这个 Path 暴露给浏览器。这时候如果目标服务器的 Cookie 写死了 Path 也会出现 Cookie 无法写入的问题。

③ proxy_cookie_path off;
格式"proxy_cookie_path path replacement;",即设置"Set-Cookie"响应头中的path属性的替换文本,其值可以为一个字符串、正则表达式的模式或一个引用的变量;例如:

1
proxy_cookie_path /two/ /;          

若“Set-Cookie”响应头含有属性“path=/two/some/uri/”,那么该指令会将这个属性改写为“path=/some/uri/”。

④ proxy_hide_header field;
nginx默认不会将"Date"、"Server"、"X-Pad",和"X-Accel-..."响应头发送给客户端。该指令则可以设置额外隐藏的响应头,这些响应头也不会发送给客户端。相反的,如果希望允许传递某些响应头给客户端,可以使用proxy_pass_header指令。

⑤ proxy_set_header field value;
重新定义或者添加发往后端服务器的请求头。value可以包含文本、变量或者它们的组合。例如:

1
2
3
4
5
6
7
8
9
proxy_set_header X-Real-IP $remote_addr;   #给请求头中添加客户端IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  
 
默认情况下,只有两个请求头会被重新定义:
proxy_set_header Host $proxy_host;
proxy_set_header Connection close;
 
如果某个请求头的值为空,那么这个请求头将不会传送给后端服务器:
proxy_set_header Accept-Encoding "";

⑥ proxy_pass_request_headers on|off;
是否将http首部发往上游服务器

⑦ proxy_pass_request_body on|off;
是否将http请求报文的包体部分发往上游服务器

⑧ proxy_redirect [default|off|redirect replacement];
修改上游服务器传来的响应头中的"Location"和"Refresh"字段。例如:

1
2
3
4
5
proxy_redirect http://localhost:8000/two/ http://frontend/one/;      
 
replacement字符串可以省略服务器名:
proxy_redirect http://localhost:8000/two/ /;
此时将使用代理服务器的主域名和端口号来替换。如果端口是80,可以不加。

⑨ proxy_send_timeout time;
在连接断开之前两次发送至upstream server的写操作的最大间隔时长;

⑩ proxy_read_timeout time;
在连接断开之前两次从接收upstream server接收读操作的最大间隔时长;

1.3  proxy模块的内置变量
① $proxy_host:
后端服务器的主机名和端口;

② $proxy_port:
后端服务器的端口;

③ $proxy_add_x_forwarded_for
将$remote_addr变量值添加在客户端“X-Forwarded-For”请求头的后面,并以逗号分隔。 如果客户端请求未携带“X-Forwarded-For”请求头,$proxy_add_x_forwarded_for变量值将与$remote_addr变量相同

2、upstream模块
如果有多个上游服务器,我们可以把它们放到一个组中,并且给它们赋予不同的权重和类型,进行负载均衡等,这些功能是由upstream模块实现的。

2.1  配置语法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
upstream name {
      server address [parameters];
      ...
  }
 
示例:
upstream web {
    server web1.kevin.com       weight=5;
    server web2.kevin.com:8080;
    server unix:/tmp/web3;
    server backup1.kevin.com:8080   backup;
  }
 
    server {
    location / {
    proxy_pass http://web;
     }
    }

2.2  uptream使用注意:
① 只能用于http上下文

② 各server只能直接使用IP或主机名,不要加协议

2.3  默认情况下,nginx按加权轮转的方式将请求代理到各上游服务器。与上游服务器通信的时候,如果出现错误,请求会被传给下一个服务器,直到所有可用的服务器都被尝试过。如果所有服务器都返回失败,客户端将会得到最后通信的那个服务器的(失败)响应结果。

2.4  地址可以是域名或者IP地址,端口是可选的(默认是80),或者是指定“unix:”前缀的UNIX域套接字的路径。如果一个域名解析到多个IP,本质上是定义了多个server。

2.5  server后可定义的参数:
① weight=number
设定服务器的权重,默认是1。

② max_fails=number
设定Nginx与服务器通信的尝试失败的次数。在fail_timeout参数定义的时间段内,如果失败的次数达到此值,Nginx就认为服务器不可用。在下一个fail_timeout时间段,服务器不会再被尝试。失败的尝试次数默认是1。设为0就会停止统计尝试次数,认为服务器是一直可用的。

③ fail_timeout=time
默认是10秒,设定统计失败尝试次数的时间段。在这段时间中,服务器失败次数达到指定的尝试次数,服务器就被认为不可用。服务器被认为不可用的时间段。

④ backup
标记为备用服务器。当主服务器不可用以后,请求会被传给这些服务器。

⑤ down
标记服务器永久不可用,可以跟ip_hash指令一起使用

2.6  upstream模块的其它负载均衡算法(用于upstream上下文):
① ip_hash;
作用同lvs中的sh调度算法,将来自于同一个客户端的请求始终调度至同一台后端服务器(除了当服务器不可用的时候)

② least_conn;
将请求发送到活动连接数最少的那台服务器。如果这样的服务器有多台,就尝试按加权轮循来调度

③ sticky cookie name [expires=time] [domain=domain] [httponly] [secure] [path=path];
session绑定,将来自于同一个客户端的请求始终调度至同一台后端服务器,从而实现客户端与后端服务器的session保持。

ip_hash指令无法实现对内网NAT用户的均衡,而sticky指令可以做到;

◆     sticky工作原理
1. 浏览器首次发起请求,请求头未带cookie。nginx接收请求,发现请求头没有cookie,则以轮询方式将请求代理给后端服务器。
2. 后端服务器处理完请求,将响应头和内容返回给nginx。
3. nginx生成cookie,返回给客户端浏览器。cookie的值与后端服务器对应,可能是明文,也可能是md5、sha1等Hash值。
4. 浏览器接收请求,并创建cookie。
5. 浏览器再次发送请求时,带上cookie。
6. nginx接收到cookie,直接转给对应的后端服务器

参数说明:
domain:cookie作用的域名
path:cookie作用的路径
expires:cookie的过期时长

示例如下:

1
2
3
4
5
upstream web {
      server web1.kevin.com;
      server web2.kevin.com;
      sticky cookie srv_id expires=1h domain=.kevin.com path=/;
      }

2.7  health_check [interval=time] [fails=number] [passes=number] [uri=uri] [match=name];
对上游服务器组进行健康状态检测,用于location中;

参数说明:
interval=time       #检测的间隔时长,默认为5秒
fails=number       #连续检测失败多少次即认为上游服务器不可用,默认为1次
passes=number  #上游服务器从不可用到可用状态时需要连续检测的次数,默认为1次
uri=uri                 #定义用于健康检测的URI,默认为“/”,即默认检测目标服务器的主页
match=name      #指定一段配置来当作检测条件,默认当响应码为2XX或3XX时认为上游服务器是可用的

示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
http {
      server {
        ...
        location / {
            proxy_pass http://backend;
            health_check uri=/.health.html match=welcome;
             }
      }
 
   match welcome {      #match配置段要位于http上下文
      status 200;
      header Content-Type = text/html;
      body ~ "Welcome to nginx!";
      }
}

3、fastcgi模块
nginx能够通过fastcgi模块实现将客户端的动态文件请求代理至fastcgi server,此时nginx与fastcgi server的通信是通过fastcgi协议进行的

3.1   fastcgi模块的常用指令
①fastcgi_pass address;
指定fastcgi server的地址和端口,也支持使用unix sock;例如:

1
2
3
fastcgi_pass localhost:9000;
fastcgi_pass 192.168.30.20:9000;
fastcgi_pass unix:/tmp/fastcgi.socket;

②fastcgi_bind address | off;
指定联系fpm服务器时使用的地址;

③fastcgi_param parameter value [if_not_empty];
定义传递给fastcgi server的参数;参数值可以是文本、变量或它们的组合,if_not_empty表示不为空时才传递。例如:

1
fastcgi_param SCRIPT_FILENAME /web/scripts$fastcgi_script_name;

④fastcgi_index name;
默认主页名;就是当URI中的文件名缺省时,使用此文件名

⑤fastcgi_connect_timeout time;
连接fastcgi服务器的超时时长;

⑥fastcgi_send_timeout time;
向fastcgi服务传输数据的超时时长;

3.2  通常建议nginx和fastcgi server(如php-fpm)部署在同一台服务器上,因为二者如果通过网络通信的话会造成额外的性能开销。

3.3   配置示例

1
2
3
4
5
6
location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9001;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME /web/scripts$fastcgi_script_name;
        include fastcgi_params;
     }

说明:
①参数SCRIPT_FILENAME保存是的脚本文件的绝对路径;例如,若请求的URI是/test/status.php,那么向fastcgi server传递的脚本文件路径就是/web/scripts/test/status.php
②nginx有两个文件fastcgi_params和fastcgi.conf,它们存放着nginx向fastcgi server传递的参数,二者唯一的区别是后者比前者多了一行 SCRIPT_FILENAME 的定义:
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

3.4  通过nginx查看后端php-fpm的运行状态

1
2
3
4
5
6
7
8
9
10
11
12
# vim /etc/php-fpm.d/www.conf(若php-fpm是编译安装,则为主配置文件)
pm.status_path = fpm_status
ping.path = fpm_ping
 
# vim /etc/nginx/nginx.conf          
location ~* /(fpm_status|fpm_ping) {
    root           /www/a.com;
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_param  SCRIPT_FILENAME  $fastcgi_script_name;
    include      fastcgi_params;
 
  }

二、nginx的缓存功能
nginx做为反向代理时,能够将来自上游服务器的响应缓存至本地,并在后续的客户端请求同样内容时直接从本地构造响应报文。nginx使用磁盘做缓存;

缓存将遵从上游服务器的响应报文首部中关于缓存的设定,如 "Expires"、"Cache-Control: no-cache"、 "Cache-Control: max-age=XXX"、"private"和"no-store" 等,但nginx在缓存时不会考虑响应报文的"Vary"首部。为了确保私有信息不被缓存,所有关于用户的私有信息可以在上游服务器上通过"no-cache" or "max-age=0"来实现,也可在nginx设定proxy_cache_key必须包含用户特有数据如$cookie_xxx的方式实现,但最后这种方式在公共缓存上使用可能会有风险。因此,在响应报文中含有以下首部或指定标志的报文将不会被缓存。

1
2
3
4
5
Set-Cookie
Cache-Control containing "no-cache", "no-store", "private", or a "max-age" with a non-numeric or 0 value
 
Expires with a time in the past
X-Accel-Expires: 0

与缓存有关的指令:
① proxy_cache zone | off;
定义一个用于缓存的共享内存区域,其可被多个地方调用;

② proxy_cache_key string;
设定在存储及检索缓存时用于“键”的字符串,可以使用变量为$uri其值,但使用不当时有可能会为同一个内容缓存多次;另外,将用户私有信息用于键可以避免将用户的私有信息返回给其它用户;

1
例如:proxy_cache_key "$host$request_uri;

③ proxy_cache_lock on | off;
启用此项,可在缓存未命令中阻止多个相同的请求同时发往upstream,其生效范围为worker级别;

④ proxy_cache_lock_timeout time;
proxy_cache_lock功能的锁定时长;

⑤ proxy_cache_min_uses number;
某响应报文被缓存之前至少应该被请求的次数;

⑥ proxy_cache_path path [levels=levels] keys_zone=name:size [inactive=time] [max_size=size] [loader_files=number] [loader_sleep=time] [loader_threshold=time] ;
定义一个用记保存缓存响应报文的目录,及一个保存缓存对象的键及响应元数据的共享内存区域(keys_zone=name:size),其可选参数有:
levels:   每级子目录名称的长度,有效值为1或2,每级之间使用冒号分隔,最多为3级;
inactive:非活动缓存项从缓存中剔除之前的最大缓存时长;
max_size:   缓存空间大小的上限,当需要缓存的对象超出此空间限定时,缓存管理器将基于LRU算法对其进行清理;
loader_files:缓存加载器的每次工作过程最多为多少个文件加载元数据;
loader_sleep:  缓存加载器的每次迭代工作之后的睡眠时长;
loader_threashold:  缓存加载器的最大睡眠时长;

1
2
3
示例:
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_use_stale error | timeout | invalid_header | updating | http_500 | http_502 | http_503 |http_504 | http_403 | http_404 | off ...;
在无法联系到upstream服务器时的哪种情形下(如error、timeout或http_500等)让nginx使用本地缓存的过期的缓存对象直接响应客户端请求;

⑧ proxy_cache_valid [code ...] time;
用于为不同的响应设定不同时长的有效缓存时长

1
2
例如:
proxy_cache_valid  200 302  10m;

⑨ proxy_cache_methods GET | HEAD | POST ...;
为哪些请求方法启用缓存功能;

⑩ proxy_cache_bypass string;
设定在哪种情形下,nginx将不从缓存中取数据。

1
2
proxy_cache_bypass $cookie_nocache $arg_nocache $arg_comment;
proxy_cache_bypass $http_pragma $http_authorization;

nginx也可将后端fastcgi server的响应结果缓存:

1
2
3
4
fastcgi_cache
fastcgi_cache_path
fastcgi_cache_valid
...

三、Nginx反向代理简单实现
负载机:A机器:103.110.186.8/192.168.1.8
后端机器1:B机器:192.168.1.102
后端机器2:C机器:192.168.1.103

需求:
->  访问A机器的8080端口,反向代理到B机器的8080端口;
->  访问A机器的8088端口,反向代理到C机器的8088端口;
->  访问http://103.110.86.8:8090/ios,反向代理到B机器http://192.168.1.102:8090/ios/
->  访问A机器的80端口,负载均衡到后端的两台机器B和C的80端口

操作记录如下:

=========================================================================================
负载机:A机器上的操作记录:

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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
1)编译安装nginx
[root@opd ~]# yum install -y pcre* openssl* gcc gcc+
[root@opd ~]# cd /opt/src
[root@src ~]# wget http://nginx.org/download/nginx-1.8.0.tar.gz
[root@src ~]# tar -zxvf nginx-1.8.0.tar.gz
[root@src ~]# cd nginx-1.8.0
#添加www用户,其中-M参数表示不添加用户家目录,-s参数表示指定shell类型
 
[root@nginx-1.8.0 ~]#useradd www -M -s /sbin/nologin
[root@nginx-1.8.0 ~]#vim auto/cc/gcc
#将这句注释掉 取消Debug编译模式 大概在179行
#CFLAGS="$CFLAGS -g"
 
#我们再配置下nginx编译参数
[root@nginx-1.8.0 ~]# ./configure --prefix=/opt/nginx --user=www --group=www --with-http_stub_status_module --with-http_ssl_module
[root@nginx-1.8.0 ~]#make
[root@nginx-1.8.0 ~]#make install clean
 
2)配置nginx
[root@nginx-1.8.0 ~]# cd /opt/nginx/conf
[root@nginx-1.8.0 conf]# vim nginx.conf         //这个可以作为nginx安装后的配置规范
http {
    include       mime.types;
    default_type  application/octet-stream;
    charset utf-8;
   
    log_format  main  '$http_x_forwarded_for $remote_addr $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_cookie" $host $request_time';
    sendfile       on;
    tcp_nopush     on;
    tcp_nodelay    on;
    keepalive_timeout  65;
   
   
    fastcgi_connect_timeout 3000;
    fastcgi_send_timeout 3000;
    fastcgi_read_timeout 3000;
    fastcgi_buffer_size 256k;
    fastcgi_buffers 8 256k;
    fastcgi_busy_buffers_size 256k;
    fastcgi_temp_file_write_size 256k;
    fastcgi_intercept_errors on;
    
       
    client_header_timeout 600s;
    client_body_timeout 600s;
    
    client_max_body_size 100m;           
    client_body_buffer_size 256k;         
    
    gzip  on;
    gzip_min_length  1k;
    gzip_buffers     4 16k;
    gzip_http_version 1.1;
    gzip_comp_level 9;
    gzip_types       text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php;
    gzip_vary on;
    
   
    include vhosts/*.conf;
}
 
[root@nginx-1.8.0 conf]# ulimit -n 65535
[root@nginx-1.8.0 conf]# mkdir vhosts
[root@nginx-1.8.0 conf]# cd vhosts
 
配置反向代理和负载均衡
[root@nginx-1.8.0 vhosts]# vim 8080.conf
server {
    listen 8080;
    server_name localhost;
    index index.html index.php index.htm;
    root /var/www/html;
   
    access_log  /usr/local/nginx/logs/8080-access.log main;
    error_log  /usr/local/nginx/logs/8080-error.log;
  
location / {
    proxy_pass http://192.168.1.102:8080;
    proxy_redirect off ;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header REMOTE-HOST $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_connect_timeout 300;             #跟后端服务器连接超时时间,发起握手等候响应时间
    proxy_send_timeout 300;                #后端服务器回传时间,就是在规定时间内后端服务器必须传完所有数据
    proxy_read_timeout 600;                #连接成功后等待后端服务器的响应时间,已经进入后端的排队之中等候处理
    proxy_buffer_size 256k;                #代理请求缓冲区,会保存用户的头信息以供nginx进行处理
    proxy_buffers 4 256k;                  #同上,告诉nginx保存单个用几个buffer最大用多少空间
    proxy_busy_buffers_size 256k;          #如果系统很忙时候可以申请最大的proxy_buffers
    proxy_temp_file_write_size 256k;       #proxy缓存临时文件的大小
    proxy_next_upstream error timeout invalid_header http_500 http_503 http_404;
    proxy_max_temp_file_size 128m;
}
}
 
[root@nginx-1.8.0 vhosts]# cat 8088.conf
server {
    listen 8088;
    server_name localhost;
    index index.html index.php index.htm;
    root /var/www/html;
   
    access_log  /usr/local/nginx/logs/8088-access.log main;
    error_log  /usr/local/nginx/logs/8088-error.log;
  
location / {
    proxy_pass http://192.168.1.103:8088;
    proxy_redirect off ;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header REMOTE-HOST $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_connect_timeout 300;           
    proxy_send_timeout 300;             
    proxy_read_timeout 600;             
    proxy_buffer_size 256k;              
    proxy_buffers 4 256k;                
    proxy_busy_buffers_size 256k;       
    proxy_temp_file_write_size 256k;     
    proxy_next_upstream error timeout invalid_header http_500 http_503 http_404;
    proxy_max_temp_file_size 128m;
}
}
 
 
》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
下面这个匹配path的代理设置需要注意几点:
首先一定要保证目标B机器,也就是192.168.1.102的8090端口站点目录下有这个匹配path的目录ios存在!!
也就是要保证A机器本机能顺利访问到目标B机器的8090端口的ios路径,即:
[root@nginx-1.8.0 vhosts]# curl http://192.168.1.102:8090/ios/ #一定要保证这个能从A机器访问成功!
 
下面几种配置都是可以的:
 
第一种:
[root@nginx-1.8.0 vhosts]# cat 8090.conf
server {
    listen 8090;
    server_name localhost;
    index index.html index.php index.htm;
    root /var/www/html;
   
    access_log  /usr/local/nginx/logs/8090-access.log main;
    error_log  /usr/local/nginx/logs/8090-error.log;
  
    location /ios/ {                            #这种情况,这里一定要匹配的是/ios/,不能是/ios
    proxy_pass http://192.168.1.102:8090;       #一定要保证192.168.1.102机器8090端口站点目录下有ios目录!否则访问会报错404!
    proxy_redirect off ;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header REMOTE-HOST $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_connect_timeout 300;           
    proxy_send_timeout 300;             
    proxy_read_timeout 600;             
    proxy_buffer_size 256k;              
    proxy_buffers 4 256k;                
    proxy_busy_buffers_size 256k;       
    proxy_temp_file_write_size 256k;     
    proxy_next_upstream error timeout invalid_header http_500 http_503 http_404;
    proxy_max_temp_file_size 128m;
}
}
 
第二种:
[root@nginx-1.8.0 vhosts]# cat 8090.conf
server {
    listen 8090;
    server_name localhost;
    index index.html index.php index.htm;
    root /var/www/html;
   
    access_log  /usr/local/nginx/logs/8090-access.log main;
    error_log  /usr/local/nginx/logs/8090-error.log;
  
    location /ios/ {
    proxy_pass http://192.168.1.102:8090/ios/;
    proxy_redirect off ;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header REMOTE-HOST $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_connect_timeout 300;           
    proxy_send_timeout 300;             
    proxy_read_timeout 600;             
    proxy_buffer_size 256k;              
    proxy_buffers 4 256k;                
    proxy_busy_buffers_size 256k;       
    proxy_temp_file_write_size 256k;     
    proxy_next_upstream error timeout invalid_header http_500 http_503 http_404;
    proxy_max_temp_file_size 128m;
}
}
 
第三种:
[root@nginx-1.8.0 vhosts]# cat 8090.conf
server {
    listen 8090;
    server_name localhost;
    index index.html index.php index.htm;
    root /var/www/html;
   
    access_log  /usr/local/nginx/logs/8090-access.log main;
    error_log  /usr/local/nginx/logs/8090-error.log;
  
    location /ios {
    proxy_pass http://192.168.1.102:8090/ios/;         这种情况,这里一定要匹配的是/ios/,不能是/ios
    proxy_redirect off ;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header REMOTE-HOST $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_connect_timeout 300;           
    proxy_send_timeout 300;             
    proxy_read_timeout 600;             
    proxy_buffer_size 256k;              
    proxy_buffers 4 256k;                
    proxy_busy_buffers_size 256k;       
    proxy_temp_file_write_size 256k;     
    proxy_next_upstream error timeout invalid_header http_500 http_503 http_404;
    proxy_max_temp_file_size 128m;
}
}
 
以上三种配置方法都保证了访问http://103.110.86.8:8090/ios会自动变为http://103.10.86.8:8090/ios/,并代理到http://192.168.1.102:8090/ios/的结果
 
[root@nginx-1.8.0 vhosts]# cat LB.conf
upstream lb {
    server 192.168.1.102:80 max_fails=3 fail_timeout=30s;   #max_fails = 3 为允许失败的次数,默认值为1
    server 192.168.1.103:80 max_fails=3 fail_timeout=30s;   #fail_timeout = 30s 当max_fails次失败后,暂停将请求分发到该后端服务器的时间
}
  
server {
    listen 80;
    server_name localhost;
    index index.html index.php index.htm;
    root /var/www/html;
   
    access_log  /usr/local/nginx/logs/80-access.log main;
    error_log  /usr/local/nginx/logs/80-error.log;
  
    location / {
    proxy_pass http://lb;
    proxy_redirect off ;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header REMOTE-HOST $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_connect_timeout 300;           
    proxy_send_timeout 300;             
    proxy_read_timeout 600;             
    proxy_buffer_size 256k;              
    proxy_buffers 4 256k;                
    proxy_busy_buffers_size 256k;       
    proxy_temp_file_write_size 256k;     
    proxy_next_upstream error timeout invalid_header http_500 http_503 http_404;
    proxy_max_temp_file_size 128m;
}
}
 
启动nginx
[root@nginx-1.8.0 vhosts]# /opt/nginx/sbin/nginx -t
nginx: the configuration file /opt/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /opt/nginx/conf/nginx.conf test is successful
 
[root@host-192-168-1-102 vhosts]# /opt/nginx/sbin/nginx

=====================================================================================
后端机:B机器上的操作记录:

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
1)编译安装nginx
[root@B ~]# yum install -y pcre* openssl* gcc gcc+
[root@B ~]# cd /opt/src
[root@B ~]# wget http://nginx.org/download/nginx-1.8.0.tar.gz
[root@B ~]# tar -zxvf nginx-1.8.0.tar.gz
[root@B ~]# cd nginx-1.8.0
#添加www用户,其中-M参数表示不添加用户家目录,-s参数表示指定shell类型
 
[root@nginx-1.8.0 ~]#useradd www -M -s /sbin/nologin
[root@nginx-1.8.0 ~]##vim auto/cc/gcc
#将这句注释掉 取消Debug编译模式 大概在179行
#CFLAGS="$CFLAGS -g"
 
#我们再配置下nginx编译参数
[root@nginx-1.8.0 ~]# ./configure --prefix=/opt/nginx --user=www --group=www --with-http_stub_status_module --with-http_ssl_module
[root@nginx-1.8.0 ~]#make
[root@nginx-1.8.0 ~]#make install clean
 
2)配置nginx
[root@nginx-1.8.0 ~]# cd /opt/nginx/conf
注意,把默认的nginx.conf文件中的server区域配置注释掉,设置vhosts虚拟主机的配置,如下:
[root@nginx-1.8.0 conf]# vim nginx.conf
user  www;
worker_processes  8;
    
events {
    worker_connections  65535;
}
    
http {
    include       mime.types;
    default_type  application/octet-stream;
    charset utf-8;
   
    log_format  main  '$http_x_forwarded_for $remote_addr $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_cookie" $host $request_time';
    sendfile       on;
    tcp_nopush     on;
    tcp_nodelay    on;
    keepalive_timeout  65;
   
   
    fastcgi_connect_timeout 3000;
    fastcgi_send_timeout 3000;
    fastcgi_read_timeout 3000;
    fastcgi_buffer_size 256k;
    fastcgi_buffers 8 256k;
    fastcgi_busy_buffers_size 256k;
    fastcgi_temp_file_write_size 256k;
    fastcgi_intercept_errors on;
    
       
    client_header_timeout 600s;
    client_body_timeout 600s;
    
    client_max_body_size 100m;           
    client_body_buffer_size 256k;         
    
    gzip  on;
    gzip_min_length  1k;
    gzip_buffers     4 16k;
    gzip_http_version 1.1;
    gzip_comp_level 9;
    gzip_types       text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php;
    gzip_vary on;
    
   
    include vhosts/*.conf;
}
 
[root@nginx-1.8.0 conf]# ulimit -n 65535
[root@nginx-1.8.0 conf]# mkdir vhosts
[root@nginx-1.8.0 conf]# cd vhosts
 
[root@nginx-1.8.0 conf]# vim 8080.conf
server {
    listen 8080;
    server_name localhost;
    index index.html index.php index.htm;
   
    access_log  /usr/local/nginx/logs/8080-access.log main;
    error_log  /usr/local/nginx/logs/8080-error.log;
  
location ~ / {
    root /var/www/html/8080;
    index index.html index.php index.htm;
}
}
 
[root@nginx-1.8.0 conf]# vim 8090.conf
server {
    listen 8090;
    server_name localhost;
    index index.html index.php index.htm;
   
    access_log  /usr/local/nginx/logs/8090-access.log main;
    error_log  /usr/local/nginx/logs/8090-error.log;
  
location ~ / {
    root /var/www/html/8090;        #针对上面匹配ios的path代理,要保证站点目录/var/www/html/8080下有ios目录存在
    index index.html index.php index.htm;
}
}
 
[root@nginx-1.8.0 conf]# vim 80.conf
server {
   listen 80;
   server_name localhost;
   index index.html index.php index.htm;
   
   access_log  /usr/local/nginx/logs/80-access.log main;
   error_log  /usr/local/nginx/logs/80-error.log;
  
location ~ / {
   root /var/www/html;
   index index.html index.php index.htm;
}
}
 
启动nginx
[root@nginx-1.8.0 vhosts]# /opt/nginx/sbin/nginx -t
nginx: the configuration file /opt/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /opt/nginx/conf/nginx.conf test is successful
 
[root@host-192-168-1-102 vhosts]# /opt/nginx/sbin/nginx

==========================================================================================
后端机:C机器上的操作记录

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
1)编译安装nginx
[root@C ~]# yum install -y pcre* openssl* gcc gcc+
[root@C ~]# cd /opt/src
[root@C ~]# wget http://nginx.org/download/nginx-1.8.0.tar.gz
[root@C ~]# tar -zxvf nginx-1.8.0.tar.gz
[root@C ~]# cd nginx-1.8.0
#添加www用户,其中-M参数表示不添加用户家目录,-s参数表示指定shell类型
 
[root@nginx-1.8.0 ~]#useradd www -M -s /sbin/nologin
[root@nginx-1.8.0 ~]##vim auto/cc/gcc
#将这句注释掉 取消Debug编译模式 大概在179行
#CFLAGS="$CFLAGS -g"
 
#我们再配置下nginx编译参数
[root@nginx-1.8.0 ~]# ./configure --prefix=/opt/nginx --user=www --group=www --with-http_stub_status_module --with-http_ssl_module
[root@nginx-1.8.0 ~]#make
[root@nginx-1.8.0 ~]#make install clean
 
2)配置nginx
[root@nginx-1.8.0 ~]# cd /opt/nginx/conf
注意,把默认的nginx.conf文件中的server区域配置注释掉,设置vhosts虚拟主机的配置,如下:
[root@nginx-1.8.0 conf]# vim nginx.conf
 
user  www;
worker_processes  8;
    
events {
    worker_connections  65535;
}
    
http {
    include       mime.types;
    default_type  application/octet-stream;
    charset utf-8;
   
    log_format  main  '$http_x_forwarded_for $remote_addr $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_cookie" $host $request_time';
    sendfile       on;
    tcp_nopush     on;
    tcp_nodelay    on;
    keepalive_timeout  65;
   
   
    fastcgi_connect_timeout 3000;
    fastcgi_send_timeout 3000;
    fastcgi_read_timeout 3000;
    fastcgi_buffer_size 256k;
    fastcgi_buffers 8 256k;
    fastcgi_busy_buffers_size 256k;
    fastcgi_temp_file_write_size 256k;
    fastcgi_intercept_errors on;
    
       
    client_header_timeout 600s;
    client_body_timeout 600s;
    
    client_max_body_size 100m;           
    client_body_buffer_size 256k;         
    
    gzip  on;
    gzip_min_length  1k;
    gzip_buffers     4 16k;
    gzip_http_version 1.1;
    gzip_comp_level 9;
    gzip_types       text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php;
    gzip_vary on;
    
   
    include vhosts/*.conf;
}
 
[root@nginx-1.8.0 conf]# vim 80.conf
server {
    listen 80;
    server_name localhost;
    index index.html index.php index.htm;
   
    access_log  /usr/local/nginx/logs/80-access.log main;
    error_log  /usr/local/nginx/logs/80-error.log;
  
location ~ / {
    root /var/www/html/;
    index index.html index.php index.htm;
}
}
 
启动nginx
[root@nginx-1.8.0 vhosts]# /opt/nginx/sbin/nginx -t
nginx: the configuration file /opt/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /opt/nginx/conf/nginx.conf test is successful
 
[root@host-192-168-1-102 vhosts]# /opt/nginx/sbin/nginx
 
 
到此,上面需求中的nginx反向代理和负载均衡就已经配置完成了!
访问http://103.110.86.8:8080的结果显示的就是B机器,即http://192.168.1.102:8080的结果
访问http://103.110.86.8:8088的结果显示的就是C机器,即http://192.168.1.108:8088的结果
访问http://103.110.86.8:8090/ios的结果显示的就是B机器,即http://192.168.1.102:8090/ios/的结果
 
访问http://103.110.86.8的请求就会被负载给到后端两台机器http://192.168.1.102和http://192.168.1.103
 
可以在103.110.86.8本机可以使用curl和telnet测试到目标机器是否通顺~
[root@nginx-1.8.0 vhosts]# curl http://192.168.1.102:8080
[root@nginx-1.8.0 vhosts]# telnet 192.168.1.102 8080

                                                                                                                                                      
说明一下:上面的nginx反向代理的需求,除了nginx反代配置之外,也可以使用iptables的nat转发实现。
比如:访问A机器的8080端口,反向代理到B机器的80端口;iptables的nat转发规则设置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@opd ~]# iptables -t nat -A PREROUTING -p tcp -m tcp --dport 8080 -j DNAT --to-destination 192.168.1.102:80
[root@opd ~]# iptables -t nat -A POSTROUTING -d 192.168.1.102 -p tcp -m tcp --sport 80 -j SNAT --to-source 192.168.1.8
[root@opd ~]# iptables -t filter -A INPUT -p tcp -m state --state NEW -m tcp --dport 8080 -j ACCEPT
 
[root@opd ~]# service iptables save
 
**************************************
需要注意的是:
要打开A机器的ip转发功能:
[root@opd ~]# echo 1 > /proc/sys/net/ipv4/ip_forward
然后后端机器B的route路由最好也设置成192.168.1.8
**************************************
 
这样,访问http://103.110.86.8:8080的结果就是http://192.168.1.102的结果

                                                                                                                                                   
nginx反向代理一例:访问 http://testwx3.wangshibo.com/apiwx3   反向代理到    https://testwww.wangshibo.com

1
2
3
4
5
6
7
8
9
10
11
[root@dev-new-test vhosts]# cat testwx3.wangshibo.com.conf
server {
        listen       80;
  
        server_name  testwx3.wangshibo.com;
        root  /Data/app/xqsj_wx3/dist;
        index index.html;
  
    location /apiwx3/ {
        proxy_pass https://testwww.wangshibo.com/;
    }

如上配置后:
访问 http://testwx3.wangshibo.com/apiwx3  自动跳转到  http://testwx3.wangshibo.com/apiwx3/
访问 http://testwx3.wangshibo.com/apiwx3/$1 的内容和 https://testwww.wangshibo.com/$1 内容一致
比如:
访问 http://testwx3.wangshibo.com/apiwx3/xqsj.php?r=HouseGroup/create  显示的内容既是  http://testwww.wangshibo.com/xqsj.php?r=HouseGroup/create 的内容

如果将上面的代理配置改为:

1
2
3
4
5
6
7
8
location /apiwx3 {
    proxy_pass https://testwww.wangshibo.com;
}
  
或者
    location /apiwx3/ {
    proxy_pass https://testwww.wangshibo.com/;
}

那么只能实现:访问 http://testwx3.wangshibo.com/apiwx3 的结果和 https://testwww.wangshibo.com 一致
不能实现:访问http://testwx3.wangshibo.com/apiwx3/$1的内容和https://testwww.wangshibo.com/$1内容一致

posted @   散尽浮华  阅读(9050)  评论(1编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
点击右上角即可分享
微信分享提示