nginx反向代理
一、代理基本概念
1.1 什么是代理
日常生活中,代理这个概念我们并不陌生,代为办理,比如代理理财、代理租房、代理收货等等。

1.2 无代理场景
在没有使用代理的场景下,客户端都是直接请求服务端,服务端直接响应客户端。比如:抖音在初创阶段时没太多人关注,单台服务器足以支撑业务运行。但随着事件推移,市场认可后用户大增,抖音迅速蹿红,那么此时单台服务器难以支撑海量的用户请求,甚至一度造成服务瘫痪。

1.3 有代理场景
- 在使用代理的场景下,客户端无法直接向服务端发起请求,需要先请求代理服务,由代理服务代为请求后端节点,以实现客户端与后端通信;
- 使用代理会增加网络延迟,但能提高系统整体的响应,以此承担海量的并发请求;

二、正向代理和反向代理
2.1 正向代理。客户机请求代理服务器,代理服务器转发请求到对应的目标服务器。主动方是用户

1.(kexueshangw)访问某狗狗

2.客户端提速
游戏加速器

3.客户端缓存
比如:下载资源时,可以先查看代理服务是否有,如果有直接通过代理获取。

4.客户端授权
很多公司为了安全,连接外网需要通过防火墙,防火墙可以配置规则,允许谁可以上外网,谁不可以上外网。

2.2 反向代理
反向代理,部署在Web服务器上,用于公司集群架构,代理所有外部网络对内部网络的访问。浏览器访问服务器,必须经过这个代理,是被动的。正向代理的主动方是客户端,反向代理的主动方是Web服务器。

2.2.1 路由功能
根据用户请求的URI调度到不同功能的集群服务器进行处理(或者基于设备的调度)。

2.2.2 负载均衡
将用户发送的请求,通过负载均衡调度算法挑选一台合适的节点进行请求处理。

2.2.3 动静分离
根据用户请求的URI进行区分,将动态资源调度至应用服务器处理,将静态资源调度至静态资源服务器处理。

2.2.4 数据缓存

2.3反向代理的作用:
- 安全,客户端对Web服务器的访问需要先经过反向代理服务器。这样可以防止外部程序对Web服务器的直接攻击。
- 负载均衡,反向代理服务器可以根据Web服务器的负载情况,动态地把HTTP请求交给不同的Web服务器来处理,前提是要有多个Web服务器。
- 提升Web服务器的IO性能。一个HTTP请求的数据,从客户端传输给服务器,是需要时间的,例如N秒,如果直接传给Web服务器,Web服务器就需要让一个进程阻塞N秒,来接收IO,这样会降低Web服务器的性能。如果使用反向代理服务器,先让反向代理服务器接收完整个HTTP请求,再把请求发给Web服务器,就能提升Web服务器的性能。还有一些静态文件的请求,可以直接交给反向代理来处理,不需要经过Web服务器。
2.4 正向代理与反向代理的区别
服务的对象不同,部署的位置点也不同。
向代理代理的对象是【客户端】,为客户端服务
反向代理代理的对象是【服务端】,为服务端服务
三、nginx可代理的协议
Nginx作为代理服务,支持的代理协议非常的多,如下图所示

Nginx常用的代理协议
通常情况下,我们将Nginx作为反向代理,常常会用到如下几种代理协议,如下图所示
fa
四、nginx反向代理实践
4.1 配置语法指令
Syntax: proxy_pass URL;
Default: —
Context: location, if in location, limit_except
proxy_pass http://localhost:8000/uri/http://10.0.0.7:8000/uri/
4.2 代理配置场景

4.2.1 环境准备
| 角色 | 外网IP(NAT) | 内网IP(LAN) | 主机名 |
|---|---|---|---|
| Proxy | eth0:10.0.0.5 | eth1:172.16.1.5 | proxy01 |
| web01 | eth1:172.16.1.7 | web01 |
4.2.2 web01节点配置
[root@web01 conf.d]# cat web01.conf
server {
listen 8080; # 监听在8080,随便指定
server_name web.bertwu.net;
root /code/web;
location / {
index index.html;
}
}
[root@web01 conf.d]# mkdir /code/web
[root@web01 conf.d]# echo 'web01' > /code/web/index.html
[root@web01 conf.d]# systemctl reload nginx
[root@web01 conf.d]# chown -R www.www /code/web/
4.2.3 proxy节点配置
1.安装nginx并加入开机自启 (略)
2. proxy代理服务配置,让客户端能够通过代理服务器(10.0.0.5)访问到后端的172.16.1.7的8080端口站点内容。
[root@proxy01 conf.d]# cat proxy_web01.conf
server {
listen 80;
server_name web.bertwu.net;
location / {
# proxy_pass http://172.16.1.7:8080;
proxy_pass http://10.0.0.7:8080; # 此处写公网ip是便于10.0.0.0网段wireshark抓包分析
}
}
3.修改hosts,文件,并启动wireshark抓包分析http请求过程。
10.0.0.5 web.bertwu.net
抓包分析Nginx代理处理整个请求的过程

可以看到整个过程:
请求路径:10.0.0.1–>10.0.0.5 10.0.0.5–>10.0.0.7
响应路径:10.0.0.7–>10.0.0.5 10.0.0.5–>10.0.0.1
4.3 代理相关配置参数
4.3.1 proxy_set_header
如果将web01(10.0.0.7)的8080端口改为80,那么再次访问时候会报502错误,代理请求后端未找到。这是因为代理要去找10.0.0.7:8080,而172.16.1.7未开放8080。

然后我们将代理的proxy_pass http://10.0.0.7:8080 改为proxy_pass http://10.0.0.7:80再次访问,我们的预期还是要返回web01的界面,结果返回如下:

这是为什么呢?抓包分析请求过程如下:
ho
这是因为代理访问web后端时候Host字段只是web后端的ip而不是域名。于是后端会随机访问一个80上开启的服务。所以我们应该让代理请求后端时候带上请求的域名。
# 添加发往后端服务器的请求头信息,
Syntax: proxy_set_header field value;
Default: proxy_set_header Host $proxy_host;
proxy_set_header Connection close;
Context: http, server, location
# 客户端请求Host的值是web.bertwu.net, 那么代理服务会像后端请求时携带Host变量为web.bertwu.net
proxy_set_header Host $http_host;
# 将$remote_addr的值放进变量X-Real-IP中,$remote_addr的值为客户端的ip
proxy_set_header X-Real-IP $remote_addr;
# 客户端通过代理服务访问后端服务,后端服务会通过该变量会记录真实客户端地址
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
修改proxy端配置文件
server {
listen 80;
server_name web.bertwu.net;
location / {
proxy_pass http://10.0.0.7:80;
proxy_set_header Host $http_host;
}
}

还可以设置X-Forwarded-For字段,让代理服务器把客户端真实ip一同带到服务端
[root@proxy01 conf.d]# cat proxy_web01.conf
server {
listen 80;
server_name web.bertwu.net;
location / {
proxy_pass http://10.0.0.7:80;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

4.3.2 proxy_http_version
当代理服务器向后端请求时候,默认是http1.0协议,它是短连接 Connection:close状态,一次请求后立马会断开连接,如果有多个请求,这样会导致代理服务器大量处于time_wait状态,长时间占用随机端口。而,代理的端口是有限的。所以长连接更合适。
# 浏览器多请求几次 web.bertwu.net,然后查看网络状态
[root@web01 conf.d]# netstat -nt
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 10.0.0.7:80 10.0.0.5:54130 TIME_WAIT
tcp 0 0 10.0.0.7:80 10.0.0.5:54128 TIME_WAIT
tcp 0 0 172.16.1.7:719 172.16.1.32:2049 ESTABLISHED
tcp 0 0 10.0.0.7:80 10.0.0.5:54124 TIME_WAIT
tcp 0 0 10.0.0.7:80 10.0.0.5:54122 TIME_WAIT
tcp 0 0 10.0.0.7:80 10.0.0.5:54132 TIME_WAIT
tcp 0 0 10.0.0.7:80 10.0.0.5:54120 TIME_WAIT
tcp 0 0 10.0.0.7:80 10.0.0.5:54138 TIME_WAIT
tcp 0 0 10.0.0.7:80 10.0.0.5:54126 TIME_WAIT
tcp 0 0 10.0.0.7:80 10.0.0.5:54134 TIME_WAIT
tcp 0 0 10.0.0.7:80 10.0.0.5:54136 TIME_WAIT
tcp 0 52 10.0.0.7:22 10.0.0.1:64782 ESTABLISHED
可以看到,10.0.0.5(代理端)有大量处于TIME_WAIT的状态。

# 代理的向后端请求时使用的HTTP协议版本。默认1.0版本
Syntax: proxy_http_version 1.0 | 1.1;
Default: proxy_http_version 1.0;
Context: http, server, location
This directive appeared in version 1.1.4
[root@proxy01 conf.d]# cat proxy_web01.conf
server {
listen 80;
server_name web.bertwu.net;
location / {
proxy_pass http://10.0.0.7:80;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1; # 设置版本号
proxy_set_header Connection ""; # 还需要写这个字段,置空,否则它还是close状态
}
}
4.3.3 proxy_connect_timeout
nginx代理与后端服务器 “连接超时” 时间(代理连接超时)
Syntax: proxy_connect_timeout time;
Default: proxy_connect_timeout 60s;
Context: http, server, location
4.3.4 proxy_read_timeout
nginx代理等待后端服务器 “响应(Header)超时” 时间
Syntax: proxy_read_timeout time;
Default: proxy_read_timeout 60s;
Context: http, server, location
4.3.5 proxy_send_timeout
后端服务器 “数据(Data)回传给nginx代理超时” 时间,如果没有设置任何超时时间,默认与内核的超时时间一致127s
Syntax: proxy_send_timeout time;
Default: proxy_send_timeout 60s;
Context: http, server, location
配置示例:
[root@proxy01 conf.d]# cat proxy_web01.conf
server {
listen 80;
server_name web.bertwu.net;
location / {
proxy_pass http://10.0.0.7:80;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_connect_timeout 120s;
proxy_read_timeout 120s;
proxy_send_timeout 120s;
}
}
4.3.6 proxy_buffer(缓冲区)
-
启用缓冲时,nginx代理服务器将尽快的接收响应Header以及响应报文,并将其保存到
proxy_buffer_size(Headers)和proxy_buffers(data)设置的缓冲区中。# proxy_buffer代理缓冲区 Syntax: proxy_buffering on | off; Default: proxy_buffering on; Context: http, server, location -
如果响应报文过大无法存储至内存,则会将其中部分保存到磁盘上的临时文件中。写入临时文件由
proxy_temp_path(控制临时存储目录)proxy_max_temp_file_size(控制临时存储目录大小) 和proxy_temp_file_write_size(控制一次写入临时文件的数据大小),临时文件最大大小由proxy_buffer_size和proxy_buffers限制。但当禁用缓冲时,nginx代理服务器会在接收到响应时立即同步传递给客户端,nginx代理服务器不会读取整个响应。这对于代理服务器来说是一种损耗。 -
proxy_buffer_size用于控制代理服务读取后端第一部分响应Header的缓冲区大小。Syntax: proxy_buffer_size size; Default: proxy_buffer_size 4k|8k; Context: http, server, location # proxy_buffer_size 64k; -
proxy_buffers是代理服务器为单个连接设置响应缓冲区 “数量” 和 “大小” 。如果一个后端服务所返回的页面大小为256KB,那么会为其分配4个64KB的缓冲区来缓存,如果页面大小大于256KB,那么大于256KB的部分会缓存到proxy_temp_path指定的路径中。但是这并不是好方法,因为内存中的数据处理速度要快于硬盘。所以这个值一般建议设置为站点响应所产生的页面大小中间值,如果站点大部分脚本所产生的页面大小为256KB,那么可以把这个值设置为 “16 x 16k”、“4 x 64k” 等。Syntax: proxy_buffers number size; Default: proxy_buffers 8 4k|8k; Context: http, server, location #proxy_buffers 4 64k;配置示例:
[root@proxy01 conf.d]# cat proxy_web01.conf
server {
listen 80;
server_name web.bertwu.net;
location / {
proxy_pass http://10.0.0.7:80;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_connect_timeout 120s;
proxy_read_timeout 120s;
proxy_send_timeout 120s;
proxy_buffering on;
proxy_buffer_size 8k;
proxy_buffers 8 8k;
}
}
4.3.7 代理参数总结与优化
代理网站常用优化配置如下,将配置写入一个新文件放在/etc/nginx/下,调用时使用include即可,这样,代理多个站点,只需要 include 加载配置,减少代码冗余。
参数配置文件如下:
[root@proxy01 nginx]# cat proxy_params
# ip
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# http version
proxy_http_version 1.1;
proxy_set_header Connection "";
# timeout
proxy_connect_timeout 120s;
proxy_read_timeout 120s;
proxy_send_timeout 120s;
# buffer
proxy_buffering on;
proxy_buffer_size 8k;
proxy_buffers 8 8k;
主配置文件如下:
[root@proxy01 conf.d]# cat proxy_web01.conf
server {
listen 80;
server_name web.bertwu.net;
location / {
proxy_pass http://10.0.0.7:80;
include /etc/nginx/proxy_params; # 导入参数配置文件
}
location /admin {
proxy_pass http://10.0.0.8:80; # 代理另一台服务器
include /etc/nginx/proxy_params;
}
}
更多推荐


所有评论(0)