一、代理基本概念

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)主机名
Proxyeth0:10.0.0.5eth1:172.16.1.5proxy01
web01eth1:172.16.1.7web01

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;
	}
	
}

更多推荐