Linux架构12 Nginx代理, nginx反向代理(代理配置), 代理服务器实现数据缓存
Nginx反向代理
什么是代理
正向代理:网络代理(代理客户端访问外网)
反向代理:用于公司集群架构,代理服务端
正向代理和反向代理的区别
1.区别在于形式上服务的”对象”不一样
2.正向代理代理的对象是客户端,为客户端服务
3.反向代理代理的对象是服务端,为服务端服务
为什么学代理
nginx代理PHP服务(fastcgi_pass:127.0.0.1:9000)
1.代理后端语言的服务(PHP、JAVA、Python...)
2.国外服务器代理国内服务器,方便国外用户上网
反向代理使用的模块
反向代理模式 | Nginx配置模块 |
---|---|
http、websocket、https、tomcat、Java程序 | ngx_http_proxy_module |
fastcgi(php程序) | ngx_http_fastcgi_module |
uwsgi(python程序) | ngx_http_uwsgi_module |
grpc(golang程序) | ngx_http_v2_module |
Syntax: proxy_pass URL; Default: — Context: location, if in location, limit_except
外网 | 内网 | |
---|---|---|
lb01 | 10.0.0.4 | 172.16.1.4 |
web01 | 10.0.0.7 | 172.16.1.7 |
[root@web01 conf.d]# vim proxy.conf ------------------------------------ server { listen 80; server_name proxy.linux.com; location / { root /code/proxy; index index.html; } } ------------------------------------ [root@web01 proxy]# systemctl restart nginx
[root@web01 ~]# cd /code [root@web01 code]# mkdir proxy [root@web01 proxy]# vim index.html web01.............
# lb01机器做代理 # 安装nginx # 配置nginx # 创建用户 [root@lb01 ~]# vim /etc/nginx/conf.d/daili.conf ------------------------------------ server { listen 80; server_name proxy.linux.com; location / { proxy_pass http://10.0.0.7; } } ------------------------------------ # 启动nginx
10.0.0.4 proxy.linux.com
访问页面不是域名对应的页面,是web01上面nginx第一个配置文件(当conf配置文件的ip没有一个能匹配地址,就返回nginx配置文件第一个) 使用wireshark抓包分析 可以看出,当我们只用proxy_pass代理的时候,会发现如下问题: 10.0.0.1请求10.0.0.4的时候使用的是域名 10.0.0.1请求10.0.0.7的时候使用的是IP:port 之前课程中讲到,当访问80端口的时候,没有域名的情况下,默认会去找排在最上面的那个配置文件 所以我们需要解决这个问题,保留住最开始的请求头部信息 proxy_set_header,这个模块可以帮我们解决这个问题
优化如下
server { listen 80; server_name proxy.linux.com; location / { proxy_pass http://10.0.0.7; # 前面要加http协议名称,因为支持多协议,需要区分,如果是80端口可以不写 proxy_set_header Host $http_host; # 带着域名一起过去 } }
proxy_pass 后面加斜线和不加斜线的区别
#没有斜线是追加 # http://www.m99-magedu.com/api/index.html ----> http://api.m99-magedu.com/api/index.html location /api{ proxy_pass http://10.0.0.159; #相当于http://10.0.0.159/api/index.html proxy_set_header Host "api.m99-magedu.com"; } #有斜线是替换 # http://www.m99-magedu.com/api/index.html -----> http://api.m99-magedu.com/index.html location /api{ proxy_pass http://10.0.0.159/; proxy_set_header Host "api.m99-magedu.com"; } # location ~ \.(jpe?g|png|bmp|gif)$ { proxy_pass http://10.0.0.159; #这里不能//10.0.0.159/,正则匹配无法处理 proxy_set_header Host "api.m99-magedu.com"; }
Syntax: proxy_set_header field value; Default: proxy_set_header Host $proxy_host; proxy_set_header Connection close; Context: http, server, location # 用户请求的时候HOST的值是www.oldboy.com, 那么代理服务会像后端传递请求的还是www.oldboy.com proxy_set_header Host $proxy_host; # 这里的Host可以大写,也可以小写或者部分小写 # 将$remote_addr的值放进变量X-Real-IP中,$remote_addr的值为客户端的ip
($remote_addr其实是请求段的ip地址,如果多个代理且要访问ip,后面可以写成X-Real-IP $X-Real-IP) proxy_set_header X-Real-IP $remote_addr; # 客户端通过代理服务访问后端服务,后端服务通过该变量会记录真实客户端地址 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 日志里面还可以配置 "$httpd_x_real_ip" #注:如果经过多次代理,$httpd_x_real_ip只记录最初的用户ip(如多个加最后一个),$proxy_add_x_forwarded_for会记录最初的用户ip和所有经过的代理地址
例:
# 后端服务通过该变量会记录真实客户端地址 # /etc/nginx/conf.d/daili.conf配置文件追加 server { listen 80; server_name proxy.linux.com; location / { proxy_pass http://10.0.0.7; proxy_set_header Host $http_host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;# 追加 } } ----------------------------------------- # lb01代理服务器日志(最后的$proxy_add_x_forwarded_for为"-",因无代理,它就是$remote_addr,故不再记录) 10.0.0.1 - - [26/Aug/2023:23:06:27 +0800] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36" "-" # web01服务器日志最后开始记录$proxy_add_x_forwarded_for为"10.0.0.1",$remote_addr是代理的ip 10.0.0.4 - - [26/Aug/2023:23:06:26 +0800] "GET / HTTP/1.0" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36" "10.0.0.1"
#nginx代理与后端服务器连接超时时间(代理超时时间) Syntax: proxy_connect_timeout time; Default: proxy_connect_timeout 60s; Context: http, server, location #nginx代理等待后端服务器的响应时间 Syntax: proxy_read_timeout time; Default: proxy_read_timeout 60s; Context: http, server, location #后端服务器数据回传给nginx代理超时时间 Syntax: proxy_send_timeout time; Default: proxy_send_timeout 60s; Context: http, server, location
#代理缓冲区:先把后端返回的数据存缓存区,当缓冲区满了,把里面数据发给客户端,后面的数据继续存在缓冲区 #nginx会把后端返回的内容先放到缓冲区当中,然后再返回给客户端,边收边传,不是全部接收完再传给客户端 Syntax: proxy_buffering on | off; Default: proxy_buffering on; # 开启代理缓冲区 Context: http, server, location #设置nginx代理保存用户头信息的缓冲区大小 Syntax: proxy_buffer_size size; Default: proxy_buffer_size 4k|8k; # 保存请求头信息,这里写4k或者8k,不加| Context: http, server, location #proxy_buffers缓冲区 Syntax: proxy_buffers number size; Default: proxy_buffers 8 4k|8k; # 请求体内容(这里指给8个缓冲区,每个4k/8k,写一个) Context: http, server, location
loation / { proxy_pass http://127.0.0.1:8080; include proxy_params; # 直接include调用,简洁方便 } [root@lb01 nginx]# vim /etc/nginx/proxy_params # 要放在nginx的安装目录下 proxy_set_header Host $proxy_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_connect_timeout 30; proxy_send_timeout 60; proxy_read_timeout 60; proxy_buffering on; proxy_buffer_size 32k; proxy_buffers 4 128k;
proxy_next_upstream error timeout http_500 http_502 http_503 http_504; # 如果访问一台机器返回500时,分配到下一台机器继续处理
反向代理常见错误状态码
#如果后端服务不可用,从客户端访问会返回502 #停止后端nginx [root@ubuntu ~]# systemctl stop nginx.service
#如果连接后端服务器超时,会报504 #启动Nginx 服务,并设置防火墙规则,如果是中间服务器的请求就DROP [root@ubuntu ~]# systemctl start nginx.service [root@ubuntu ~]# iptables -A INPUT -s 10.0.0.206 -j DROP #修改超时时长为10S server{ listen 80; server_name www.m99-magedu.com; location /{ proxy_pass http://10.0.0.210; proxy_set_header Host $http_host; proxy_connect_timeout 10s; #修改超时时间 } }
代理服务器实现数据缓存
前置条件:各服务器时间和时区先统一,方便测试
#相当于第一次请求后,图片放在代理服务器里,代理服务器不再去后端要,直接从缓存中拿然后返回 #定义缓存 #缓存目录/tmp/proxycache levels为16进制,表示在目录要创建16个dir,每个里创建16*16个dir(算hash) #缓存zone为proxycache,20m,放缓存文件的hash值 inactive缓存数据生命周期,默认10分钟,超过时间数据没变(没人访问)就会消失 proxy_cache_path /tmp/proxycache levels=1:2 keys_zone=proxycache:20m inactive=60s max_size=1g; server{ listen 80; server_name www.m99-magedu.com; location /static{ proxy_pass http://10.0.0.210; proxy_set_header Host "static.m99-magedu.com"; proxy_cache proxycache; #使用缓存,调用定义的zone proxy_cache_key $request_uri; #用什么来标识资源 #为不同的状态码设置不同的缓存时长(可以多条),超过90秒访问后端 proxy_cache_valid 200 302 301 90s; proxy_cache_valid any 2m; #此处一定要写,否则缓存不生效(其他状态码缓存2分钟) } } #重载,生成缓存目录 [root@ubuntu ~]# nginx -s reload [root@ubuntu ~]# ll /tmp/proxycache/ #Static Server 配置 server { listen 80; root /var/www/html/static.m99-magedu.com; server_name static.m99-magedu.com; } [root@ubuntu ~]# ls -lh /var/www/html/static.m99-magedu.com/static/ total 8.0K -rw-r--r-- 1 root root 657 Feb 12 15:14 fstab -rw-r--r-- 1 root root 7 Feb 12 04:42 index.html #客户端测试 [root@ubuntu ~]# curl http://www.m99-magedu.com/static/fstab #只要访问一次,里面就会生成缓存 #查看 Proxy Server 上的缓存数据,文件名就是key 的 hash 值 [root@ubuntu ~]# tree /tmp/proxycache/ /tmp/proxycache/ └── 3 └── ab └── 2d291e4d45687e428f0215bec190aab3 #这里可以手动清理缓存 #清理缓存 [root@ubuntu ~]# rm -rf /tmp/proxycache/* #在Proxy Server 中添加响应头字段,可以查看是否命中缓存 proxy_cache_path /tmp/proxycache levels=1:2 keys_zone=proxycache:20m inactive=60s max_size=1g; server{ listen 80; server_name www.m99-magedu.com; location /static{ proxy_pass http://10.0.0.210; proxy_set_header Host "static.m99-magedu.com"; proxy_cache proxycache; proxy_cache_key $request_uri; proxy_cache_valid 200 302 301 90s; proxy_cache_valid any 2m; add_header X-Cache $upstream_cache_status; #添加响应头,可以用来查看是否命中缓存 } } #客户端测试 [root@ubuntu ~]# curl -I http://www.m99-magedu.com/static/fstab X-Cache: MISS #首次访问,没有命中缓存,MISS 或者 X-Cache: HIT #缓存数据在生命周期内,被命中