背景
前面介绍了nginx中Server块和Location块的配置,说那些实际上就是为后面配置反向代理和负载均衡做铺垫的。接下来我们就说说nginx的反向代理功能。
反向代理
前面在第一章节介绍nginx的功能的时候提到过,nginx实际上也是可以做正向代理的,只是我们在生产环境中很少这么而已,所以我们就不在过多的介绍nginx的正向代理的功能了。
1. 什么是反向代理?
反向代理是指以代理服务器来接受Internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给Internet上请求连接的客户端。这个服务器所做的功能就是反向代理。
2. 常用代理协议
3. 反向代理
3.1 环境介绍
实际生产中,Client--nginx间是属于互联网,nginx代理---后端web是内网,在这里为了实验方便我们就同一在一个网段中,后续通过抓包等方式来验证结果。
3.2 配置代理
nginx代理端
server {
listen 80;
server_name proxy_web.com www.proxy_web.com;
location / {
proxy_pass http://192.168.65.130:8080;
}
}
## proxy_pass URL 解析
将请求转发到另一台服务器,在实际的反向代理工作中,会通过 location 功能匹配指定的 URI,然后把接收到的符合匹配 URI 的请求通过 proxy_pass 抛给定义好的upstream节点池(后端服务节点)。
proxy_pass转发的路径问题
第一种:proxy_pass后面的url加/,表示绝对根路径,不会代理location后的路径;
假设用URL:http://www.proxy_web.com/web/test.html 进行访问。
location /web/ {
proxy_pass http://192.168.65.130:8080/;
}
# 代理到URL:http://192.168.65.130:8080/test.html
第二种:相对于第一种,最后少一个 / ,则会把location后的路径代理进去
location /web/ {
proxy_pass http://192.168.65.130:8080;
}
# 代理到URL:http://192.168.65.130:8080/web/test.html
web服务端
server {
listen 8080;
server_name proxy_web.com www.proxy_web.com;
location / {
root /nginx/web;
index index.html;
}
}
Client端请求代理:
## 访问结果
C:\Users\xhz>curl www.proxy_web.com
web1
C:\Users\xhz>
## nginx代理端的访问日志
192.168.65.1 - - [19/Aug/2022:16:22:47 +0800] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36" "-"
192.168.65.1 - - [19/Aug/2022:16:22:48 +0800] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36" "-"
192.168.65.1 - - [19/Aug/2022:16:22:48 +0800] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36" "-"
192.168.65.1 - - [19/Aug/2022:16:27:39 +0800] "GET / HTTP/1.1" 200 5 "-" "curl/7.83.1" "-"
## web服务端的日志
192.168.65.129 - - [19/Aug/2022:16:22:47 +0800] "GET / HTTP/1.0" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36" "-"
192.168.65.129 - - [19/Aug/2022:16:22:48 +0800] "GET / HTTP/1.0" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36" "-"
192.168.65.129 - - [19/Aug/2022:16:22:48 +0800] "GET / HTTP/1.0" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36" "-"
192.168.65.129 - - [19/Aug/2022:16:27:39 +0800] "GET / HTTP/1.0" 200 5 "-" "curl/7.83.1" "-"
我们通过client端向代理发送请求,可以看到nginx代理端中的日志,请求ip是客户端的192.168.65.1;在web服务端的日志中可以看到请求ip是192.168.65.129的ip(nginx代理),此时说明代理功能已经实现。
我们在web后端是看不到前端client的ip的。我们可以优化下。通过设置proxy_set_header,来修改cline请求包中的头部信息,然后携带的传给后端web。
server {
listen 80;
server_name proxy_web.com www.proxy_web.com;
location / {
proxy_pass http://192.168.65.130:8080;
proxy_set_header Host $http_host;
##携带前端clien ip 发送到web端
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
此时web后端的日志为:(后端显示client端ip)
192.168.65.129 - - [19/Aug/2022:16:56:07 +0800] "GET / HTTP/1.0" 200 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36" "192.168.65.1"
192.168.65.129 - - [19/Aug/2022:16:56:32 +0800] "GET / HTTP/1.0" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36" "192.168.65.1"
192.168.65.129 - - [19/Aug/2022:16:56:32 +0800] "GET / HTTP/1.0" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36" "192.168.65.1"
192.168.65.129 - - [19/Aug/2022:16:56:32 +0800] "GET / HTTP/1.0" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36" "192.168.65.1"
至此最基础的nginx反向代理已经完成,至于复杂的无非就是添加更加复杂的参数,下面我们就说说相应模块中的参数。
3. ngx_http_proxy_module模块解析
3.1 proxy_set_header
用来设定被代理服务器接收到的header信息,如果不设置proxy_set_header,则默认host的值为proxy_pass后面跟的那个域名或者IP
##语法:
proxy_set_header field value
field :为要更改的项目,也可以理解为变量的名字,比如host;
value :为变量的值
作用域:http, server, location
## 当后端web服务器存在多个虚拟主机时,该模块是用来区分前端请求,是给反向代理的后端的哪个虚拟主机(即将代理的server_name传递到后端的域名为代理的server_name的虚拟主机上)
proxy_set_header Host $host;
## 用来设置被代理端接收到的远程客户端IP,如果不设置,则header信息中并不会透传远程真实客户端的IP地址。
proxy_set_header X-Real-IP $remote_addr;
和
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
## 此时后端服务器记录日志格式要添加:"$http_x_real_ip"和"$http_x_forwarded_for"变量,才能在访问日志中查看到效果
# 只有一级代理的情况下两者是等效的;如果有多级代理,X-Forwarded-For效果是大于X-Real-IP的,可以记录完整的代理链路
3.2 proxy_http_version
设置代理的HTTP协议版本。默认情况下,使用版本1.0。
作用域:http, server, location
proxy_http_version 1.0 | 1.1;
3.3 proxy_cache_path
定义可用于proxy功能的缓存;
作用域: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];
3.4 proxy_cache
proxy_cache zone | off;
默认off指明调用的缓存,或关闭缓存机制;
作用域:http, server, location
3.5 proxy_cache_key
proxy_cache_key string;
缓存中用于“键”的内容默认值:proxy_cache_key $scheme $proxy_host $request_uri;
作用域:http, server, location
3.6 proxy_cache_valid
proxy_cache_valid [code ...] time;
定义对特定响应码的响应内容的缓存时长
定义在http{...}中
作用域:http, server, location
示例:
proxy_cache_valid200 302 10m;
示例:在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;
proxy_cache_key $request_uri;
proxy_cache_valid 200 302 301 1h;
proxy_cache_valid any 1m;
3.7 proxy_cache_use_stale
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 ...
在被代理的后端服务器出现哪种情况下,可以真接使用过期的缓存响应客户端
作用域:http, server, location
3.8 proxy_cache_methods
proxy_cache_methods GET | HEAD | POST ...;
对哪些客户端请求方法对应的响应进行缓存,GET和HEAD方法总是被缓存
作用域:http, server, location
3.9 proxy_hide_header
proxy_hide_header field;
默认nginx在响应报文不传递后端服务器的首部字段Date, Server, X-Pad, X-Accel-等,用于隐藏后端服务器特定的响应首部
作用域:http, server, location
3.10 proxy_connect_timeout
proxy_connect_timeout time;
定义与后端服务器建立连接的超时时长,如超时会出现502错误,默认为60s,一般不建议超出75s,
作用域:http, server, location
3.11 proxy_send_timeout
proxy_send_timeout time;
将请求发送给后端服务器的超时时长;默认为60s
作用域:http, server, location
3.12 proxy_read_timeout
proxy_read_timeout time;
等待后端服务器发送响应报文的超时时长,默认为60s
作用域:http, server, location
3.13 proxy_buffering
proxy_buffering on | off;
代理会把后端返回的内容先放到缓冲区当中,然后再返回给客户端,边收边传, 不是全部接收完再传给客户端
Default: proxy_buffering on;
作用域: http, server, location
3.14 proxy_buffer_size
proxy_buffer_size size;
设置nginx代理保存用户头信息的缓冲区大小
Default: proxy_buffer_size 4k|8k;
作用域: http, server, location
3.15 proxy_buffers
proxy_buffers number size;
设置proxy_buffers缓冲区大小
Default: proxy_buffers 8 4k|8k; # 8*4=32k 8*8=64k
作用域: http, server, location
为了避免在配置代理的时候出现参数冗余,我们可以将常用参数配置在相应的文件中,文件名自定义。然后在location通过 include 来加载。
root@nginx-server:~# vim /etc/nginx/proxy_params
proxy_http_version 1.1; # 设置代理的HTTP协议版本
proxy_set_header Host $http_host; # 代理向后端主机请求时携带host域名
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 获取客户端真实IP以及全链路IP
proxy_connect_timeout 30; # 代理连接后端超时时间
proxy_send_timeout 60; # 后端传递数据至代理的超时时间
proxy_read_timeout 60; # 后端响应代理的超时时间
proxy_buffering on; # 代理会把后端返回的内容先放到缓冲区当中,然后再返回给客户端,边收边传
proxy_buffer_size 32k; # 代理保存用户头信息的缓冲区大小
proxy_buffers 4 128k; # 设置代理的缓冲区大小
# 重复使用配置
代理配置location时调用方便后续多个Location重复使用
location / {
proxy_pass http://IP:PORT;
include proxy_params; # 此文件为相对路径,默认会在/etc/nginx/目录下找对应文件
}
nginx的代理功能只能代理后端的某一台服务器,即proxy_pass 后面只能写一个后端服务器地址,这也是代理的局限性。要想代理多台就需要使用upstream创建代理池,这也是后面负载均衡我们所要说的内容。