ngx_http_proxy_module反向代理

nginx反向代理:reverse proxy,可代理外网用户的请求到内部的指定web服务器,并将数据返回给用户
nginx除了可以在企业提供高性能的web服务之外,另外还可以将本身不具备的请求通过某种预定义的协议转发至其它服务器处理,不同的协议就是nginx服务器与其他服务器进行通信的一种规范
主要在不同的场景使用以下模块实现不同的功能:
ngx_http_proxy_module: 将客户端请求以http协议转发至后端服务器
ngx_http_fastcgi_module:将客户端对php请求以fastcgi协议转发至后端
ngx_http_uwsgi_module: 将客户端对Python请求以uwsgi协议转发至后端
ngx_stream_proxy_module:将客户端请求以tcp协议转发至后端服务器

同构代理: 用户 --nginx--- apache tomcat mysql redis 用户到nginx走http,TCP ,nginx到后端也是http,TCP 。
异构代理: 用户 --nginx--- php python 用户到nginx走http,TCP ,nginx到后端也是fastcgi。

ngx_http_proxy_module模块:
proxy_pass; #用来设置转发客户端请求转发给的后端服务器的主机,可以是主机名、IP地址:端口,也可以代理到预先设置的主机群组,需要模块gx_http_upstream_module支持。
proxy_hide_header field; #用于nginx作为反向代理的时候,隐藏后端服务器特定的响应首部,默认nginx在响应报文中不传递后端服务器的首部字段Date, Server, X-Pad, X-Accel等 示例:proxy_hide_header Etag; 
proxy_pass_header field; #与 proxy_hide_header相反,如果要传递的话则要使用 proxy_pass_header field声明将后端服务器返回的值传递给客户端
proxy_set_header field value; #自定义设定nginx转发往后端主机的"请求报文的请求首部的值";
add_header name value [always]; #向代理服务器给客户端的响应报文添加自定义首部,或修改指定首部的值
add_trailer name value [always]; #添加自定义响应信息的尾部, 1.13.2版后支持
proxy_pass_request_body; #是否向后端服务器发送HTTP包体部分,可以设置在http/server或location块,默认即为开启
proxy_pass_request_headers; #是否将客户端的请求头部转发给后端服务器,可以设置在http/server或location块,默认即为开启
proxy_cache_path: #定义可用于proxy功能的缓存;Context:http
proxy_connect_timeout time; #定义与后端服务器建立连接的超时时长,如超时会出现502错误,默认为60s,一般不建议超出75s
proxy_send_timeout time; #对后端服务器发起write请求后,将请求发送给后端服务器的超时时长;默认为60s
proxy_read_timeout time; #从后端服务器发起read请求后,等待后端服务器发送响应报文的超时时长,默认为60s
proxy_ignore_client_abort off; #当客户端网络中断请求时,nginx服务器中断其对后端服务器的请求。即如果此项设置为on开启,则服务器会忽略客户端中断并一直等着代理服务执行返回,如果设置为off,则客户端中断后nginx也会中断客户端请求并立即记录499日志,默认为off
proxy_http_version 1.0; #用于设置nginx提供代理服务的HTTP协议的版本,默认http 1.0
proxy_headers_hash_bucket_size 128;#当配置了 proxy_hide_header和proxy_set_header的时候,用于设置nginx保 存HTTP报文头的hash表的上限
proxy_headers_hash_max_size 512; #设置proxy_headers_hash_bucket_size的最大可用空间
server_namse_hash_bucket_size 512; #server_name hash表申请空间大小
server_names_hash_max_size 512; #设置服务器名称hash表的上限大小

一.proxy_pass; #用来设置转发客户端请求转发给的后端服务器的主机,可以是主机名、IP地址:端口,也可以代理到预先设置的主机群组,需要模块gx_http_upstream_module支持。

1.proxy_pass
总结:
  建议curl和浏览器访问是时,文件夹后都带/
  建议proxy_pass最后面不要有/
  建议proxy_pass后不在有url


proxy_pass URL; 注意:proxy_pass后面路径不带uri时,会将location的uri传递(附加)给后端主机,功能类似 root
server {
  server_name HOSTNAME;
  location /uri/ {
  proxy_pass http://host[:port]; 注意:最后没有/
}...}
上面示例:http://HOSTNAME/uri --> http://host/uri ,功能类似 root
如果上面示例中有 /,即:http://host[:port]/ 此方式较少使用 意味着:http://HOSTNAME/uri --> http://host/ 即置换,功能类似 alias


2.proxy_pass后面的路径是一个uri时,其会将location的uri替换为proxy_pass的uri,后端服务器要有这个文件存在。
server {
  server_name HOSTNAME;
  location /uri/ {
  proxy_pass http://host/new_uri/;}...}

http://HOSTNAME/uri/ --> http://host/new_uri/

3.如果location定义其uri时使用了正则表达式的模式,则proxy_pass之后必须不能使用uri; 用户请求时传递的uri将直接附加至后端服务器之后
server {
  server_name HOSTNAME;
  location ~|~* /uri/ {
  proxy_pass http://host; 注意:不能加/ 也不能有uri, 如果有 /,就是置换,不规范。
 }...}
http://HOSTNAME/uri/ --> http://host/uri/


实例:
server {
  listen 80;
  server_name proxypass.zjol.com.cn;
  charset utf-8;

location / {
  #proxy_pass http://192.168.80.120;
  proxy_pass http://192.168.80.120/;
}
location /web {
  #proxy_pass http://192.168.80.120;
  proxy_pass http://192.168.80.120/;
}
location /web1 {
  #proxy_pass http://192.168.80.120/web1;
  proxy_pass http://192.168.80.120/web1/;
}}

测试准备文件
[root@localhost7D ]# tree html/
html/
├── index.html
├── web
│ └── index.html
├── web1
│ └── index.html


[root@localhost7D ]# cat html/index.html
192.168.80.130
[root@localhost7D ]# cat html/web/index.html
web 130
[root@localhost7D ]# cat html/web1/index.html
web1 130


测试结果演示和说明:第一个loation 测试,说明,当location 直接为 /,带不带 url 和 / 效果都一样。
[root@localhost7e ]# curl http://proxypass.zjol.com.cn
192.168.80.130
[root@localhost7e ]# curl http://proxypass.zjol.com.cn/
192.168.80.130

[root@localhost7e ]# curl http://proxypass.zjol.com.cn
192.168.80.130
[root@localhost7e ]# curl http://proxypass.zjol.com.cn/
192.168.80.130


第二个loation 测试,说明
当proxy_pass无/
[root@localhost7e ]# curl http://proxypass.zjol.com.cn/web #把web当成文件了。
HTTP状态 301 Moved Permanently
[root@localhost7e ]# curl http://proxypass.zjol.com.cn/web/ #找到web下index.html
web 130

访问日志
192.168.80.110 - - [19/Jul/2022:11:35:38 +0800] "GET /web HTTP/1.0" 301 169 "-" "curl/7.29.0"
192.168.80.110 - - [19/Jul/2022:11:36:08 +0800] "GET /web/ HTTP/1.0" 200 8 "-" "curl/7.29.0"

当proxy_pass有/
[root@localhost7e ]# curl http://proxypass.zjol.com.cn/web # 说明找的不是html/web/下的文件,html下的index.html,变成置换
192.168.80.130
[root@localhost7e ]# curl http://proxypass.zjol.com.cn/web/
192.168.80.130

访问日志
192.168.80.110 - - [19/Jul/2022:11:36:31 +0800] "GET / HTTP/1.0" 200 15 "-" "curl/7.29.0"
192.168.80.110 - - [19/Jul/2022:11:36:42 +0800] "GET // HTTP/1.0" 200 15 "-" "curl/7.29.0"


[root@localhost7e ]# curl http://proxypass.zjol.com.cn/web/index.html
192.168.80.130
[root@localhost7e ]# curl http://proxypass.zjol.com.cn/web/index.aaa
HTTP状态 404 - Not Found

访问日志
192.168.80.110 - - [19/Jul/2022:11:46:14 +0800] "GET //index.html HTTP/1.0" 200 15 "-" "curl/7.29.0"
192.168.80.110 - - [19/Jul/2022:11:46:23 +0800] "GET //index.aaa HTTP/1.0" 404 153 "-" "curl/7.29.0"

 

第三个loation 测试
当proxy_pass无/
[root@localhost7e ]# curl http://proxypass.zjol.com.cn/web1
HTTP状态 301 Moved Permanently
[root@localhost7e ]# curl http://proxypass.zjol.com.cn/web1/
web1 130

访问日志
192.168.80.110 - - [19/Jul/2022:11:49:23 +0800] "GET /web1 HTTP/1.0" 301 169 "-" "curl/7.29.0"
192.168.80.110 - - [19/Jul/2022:11:49:51 +0800] "GET /web1/ HTTP/1.0" 200 9 "-" "curl/7.29.0"

当proxy_pass有/
[root@localhost7e ]# curl http://proxypass.zjol.com.cn/web1
web1 130
[root@localhost7e ]# curl http://proxypass.zjol.com.cn/web1/
web1 130
访问日志
192.168.80.110 - - [19/Jul/2022:11:51:25 +0800] "GET /web1/ HTTP/1.0" 200 9 "-" "curl/7.29.0"
192.168.80.110 - - [19/Jul/2022:11:51:44 +0800] "GET /web1// HTTP/1.0" 200 9 "-" "curl/7.29.0"

 

二. 隐藏或显示 后端服务器的请求报文头信息
proxy_hide_header field; #用于nginx作为反向代理的时候,隐藏后端服务器特定的响应首部,默认nginx在响应报文中不传递后端服务器的首部字段Date, Server, X-Pad, X-Accel等 示例:proxy_hide_header Etag; 
proxy_pass_header field; #与 proxy_hide_header相反,如果要传递的话则要使用 proxy_pass_header field声明将后端服务器返回的值传递给客户端

 

location /web2 {
  proxy_pass http://192.168.80.120;
  index index.html;

  proxy_hide_header ETag;
  proxy_pass_header Server;

}


[root@localhost7e ]# curl -I http://proxypass.zjol.com.cn/web2/index.html HTTP/1.1 200 OK Date: Tue, 19 Jul 2022 08:24:52 GMT Content-Type: text/html; charset=utf-8 Content-Length: 5 Connection: keep-alive Last-Modified: Tue, 19 Jul 2022 05:54:46 GMT ETag: "62d64726-5" #隐藏 Accept-Ranges: bytes [root@localhost7e ]# curl -I http://proxypass.zjol.com.cn/web2/index.html HTTP/1.1 200 OK Date: Tue, 19 Jul 2022 08:27:54 GMT Content-Type: text/html; charset=utf-8 Content-Length: 5 Connection: keep-alive Server: nginx/1.17.1 #显示 Last-Modified: Tue, 19 Jul 2022 05:54:46 GMT Accept-Ranges: bytes

三.proxy_set_header field value; 自定义设定nginx转发往后端主机的"请求报文的请求首部的值";


proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;#键自定义变量名。值为nginx变量,客户端IP地址。(适合客户端到nginx一个代理,记录一个IP地址。)
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;(适合客户端到nginx多个代理,会记录多个IP地址。所有的proxy服务器都要添加这行,后端引用这个变量),请求报文的标准格式如下: X-Forwarded-For: client1, proxy_IP1, proxy_IP2

后端服务器nginx或tomcat两者传递参数的说明: tomcat传递的参数是”用户定义的变量“如Host 。nginx传递的参数是”nginx自己的变量,跟定义的变量没有关系 如remote_addr“
如apache日志格式:LogFormat "\"%{Host}i\" \"%{X-Real-IP}i\" \"%{}i\" \"%{X-Forwarded-For}i\" %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
如nginx 日志格式:log_format main '$remote_addr "$http_x_real_ip" - $remote_user [$time_local] "$request" $http_host $proxy_host '' "$http_referer" ' ' "$http_x_forwarded_for" $proxy_add_x_forwarded_for';

  

location /web2 {
  proxy_pass http://192.168.80.120;
  index index.html;

  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

}

前后端一样的nginx 日志格式对比:log_format main '$remote_addr "$http_x_real_ip" - $remote_user [$time_local] "$request" $http_host $proxy_host '' "$http_referer" ' ' "$http_x_forwarded_for" $proxy_add_x_forwarded_for';

客户端,192.168.80.140 nginx作为前端服务器:192.168.80.110 nginx作为后端web服务器:192.168.80.120 前端日志 192.168.80.140 "-" - - [19/Jul/2022:14:55:12 +0800] "GET /web2/index.html HTTP/1.1" proxypass.zjol.com.cn 192.168.80.120 "-" "-" 192.168.80.140 后端日志 192.168.80.110 "192.168.80.140" - - [19/Jul/2022:14:55:12 +0800] "GET /web2/index.html HTTP/1.0" proxypass.zjol.com.cn - "-" "192.168.80.140" 192.168.80.140, 192.168.80.110(这里IP透传了)

四.ngx_http_headers_module模块:
add_header name value [always];向代理服务器给客户端的响应报文添加自定义首部,或修改指定首部的值
添加自定义首部
add_header X-Via $server_addr;
add_header X-Cache $upstream_cache_status; #是否命中缓存,HIT为中,MISS为不中。要开启proxy_cache
add_header X-Accel $server_name;

location /web2 {
  proxy_pass http://192.168.80.120;
  index index.html;

  add_header X-Via $server_addr;
   add_header X-Cache $upstream_cache_status; #是否命中缓存,HIT为中,MISS为不中。要开启proxy_cache
   add_header X-Accel $server_name;

}

[root@localhost7e tomcat]# curl -I http://proxypass.zjol.com.cn/web2/index.html
HTTP/1.1 200 OK
Date: Tue, 19 Jul 2022 11:26:40 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 5
Connection: keep-alive
Server: nginx/1.17.1
Last-Modified: Tue, 19 Jul 2022 05:54:46 GMT
Accept-Ranges: bytes
X-Via: 192.168.80.110
X-Accel: proxypass.zjol.com.cn

五.proxy_cache_path: 定义可用于proxy功能的缓存;Context:http
proxy_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time] [max_size=size] [manager_files=number] [manager_sleep=time]
[manager_threshold=time] [loader_files=number] [loader_sleep=time] [loader_threshold=time] [purger=on|off] [purger_files=number] [purger_sleep=time] [purger_threshold=time];

注意: 如果是针对URL($request_uri;)缓存时,那么在缓存时郊内,改变其内容,访问时还是原来的数据。
proxy_cache_path /var/cache/nginx/proxy_cache #定义缓存保存路径,需要人工创建路径。
levels=1:2:2                  #定义缓存目录结构层次,1:2:2 可以生成2^4x2^8x2^8=1048576个目录
keys_zone=proxycache:20m         #指内存中缓存名字和大小,主要用于存放key和metadata(如:使用次数)
inactive=120s;         #缓存有效时间
max_size=1g;             #最大磁盘占用空间,磁盘存入文件内容的缓存空间最大值
proxy_cache zone | off;              默认off 指明调用的缓存,或关闭缓存机制,与kesy_zone名称对应 ;Context:http, server, location
proxy_cache_key string;             缓存中用于“键”的内容,默认值:proxy_cache_key $scheme $proxy_host $request_uri; 
proxy_cache_valid [code ...] time;    定义对特定响应码的响应内容的缓存时长,定义在http{...}中

proxy_cache_use_stale error | timeout | invalid_header | http_500 | http_404 | off ... #在被代理的后端服务器出现哪种情况下,可直接使用过期的缓存响应客户端,默认为off.
proxy_cache_methods GET | HEAD | POST ...; 对哪些客户端请求方法对应的响应进行缓存,GET和HEAD方法总是被缓存

示例:
在http配置定义缓存信息
proxy_cache_path /var/cache/nginx/proxy_cache levels=1:2:2 keys_zone=proxycache:20m inactive=120s max_size=1g;
调用缓存功能,需要定义在相应的配置段,如server{...};
proxy_cache proxycache; #在server{}调用缓存,名称与kesy_zone名称对应。
proxy_cache_key $request_uri;
proxy_cache_valid 200 302 301 1h;
proxy_cache_valid any 1m;

http{
  proxy_cache_path /var/cache/nginx/proxy_cache levels=1:2:2 keys_zone=proxycache:20m inactive=120s max_size=1g;
}

location /web2 {
  proxy_pass http://192.168.80.120;
  index index.html;

  add_header X-Via $server_addr;
       add_header X-Cache $upstream_cache_status; #是否命中缓存,HIT为中,MISS为不中。要开启proxy_cache
       add_header X-Accel $server_name;

  proxy_cache proxycache; 
proxy_cache_key $request_uri; proxy_cache_valid 200 302 301 1h; proxy_cache_valid any 1m;

}

[root@localhost7e tomcat]# curl -I http://proxypass.zjol.com.cn/web2/index.html
HTTP/1.1 200 OK
X-Cache: MISS
X-Accel: proxypass.zjol.com.cn
Accept-Ranges: bytes

[root@localhost7e tomcat]# curl -I http://proxypass.zjol.com.cn/web2/index.html
HTTP/1.1 200 OK
X-Via: 192.168.80.110
X-Cache: HIT       #是否命中缓存,HIT为中,MISS为不中。
X-Accel: proxypass.zjol.com.cn
Accept-Ranges: bytes

 

posted @ 2022-07-19 12:03  yuanbangchen  阅读(295)  评论(0编辑  收藏  举报