一、代理
正向代理
-
定义:代理服务器代理客户端(C 端),服务端(S 端)无法知道客户端的 IP
-
工作流程
- 客户端向代理服务器发送请求
- 代理服务器转发请求至服务端
- 服务端将响应发送给代理服务器
- 代理服务器再将响应传递给客户端
-
例子:科学上网
反向代理
-
定义:代理服务器代理服务端(S 端),客户端(C 端)无法知道服务端的 IP
-
工作流程
- 客户端向代理服务器发送请求
- 代理服务器将请求转发给多台服务器中的一台
- 服务器处理请求并将响应发送给代理服务器
- 代理服务器将响应传递给客户端
-
例子:Nginx 的负载均衡
优缺点
-
优点
- 隐藏真实 IP,隐私
- 在代理服务器上设置缓存可以加快访问
- 突破地域限制,绕过特定地区的 IP 访问限制(科学上网)
-
缺点
- 虽然客户端和服务端的 IP 对彼此隐藏,但都会暴露给代理服务器
- 网络链路多了代理服务器的节点,降低访问速度
二、概述
⭐ 官方文档:[Module ngx_http_proxy_module (nginx.org)](http://nginx.org/en/docs/http/ngx_http_proxy_module.html)-
定义
:统一接收客户端请求,但是 nginx 自己不处理,而是转发给上游服务器(upstream server)处理 -
工作流程
- 接收:代理服务器接收 internet 上的连接请求 (request)
- 路由:代理服务器判断向何处(原始服务器)转交请求
- 转发:代理服务器转发 request 给内部网络上的服务器
- 返回:代理服务器接收服务器的返回结果,并将结果返回给客户端
-
实现流程
- 在 nginx 配置文件中,声明一个新的 server ,用于指定上游服务器
- 在 nginx 配置文件中,指定上游服务器的完整 “地址+端口号”(http.server.location.proxy_pass)
- 在 nginx 配置文件中,声明客户端获取资源的路径(http.server.location)
-
功能
- 安全防护:将防火墙后面的服务器提供给 Internet 用户访问
- 负载均衡:平衡多台原始服务器的负载
- 缓冲服务:为后端较慢的服务器提供缓冲
- HTTP 反向代理
-
⭐ 注意
路径结尾不带 “/”
⇒ Nginx 会保留 location 中匹配到的路径前缀,并将其添加到上游服务器的地址后面proxy_pass 结尾带 “/”
⇒ Nginx 会删除 location 中匹配的路径前缀,只保留剩下的路径部分,并将其直接添加到上游服务器的地址后面
Quick Start
- 功能:将请求转发给 github 处理
http {
include mime.types;
server_tokens off;
# 下面配置反向代理的参数
server {
listen 8866;
# 1. 用户访问 <http://ip>:port,则反向代理到 <https://github.com>
location / {
proxy_pass <https://github.com>; # 将请求转发到指定的上游服务器
proxy_redirect off; # 将响应从上游服务器传递给客户端时是否修改Location响应头中的URI
proxy_set_header Host $host; # 设置向上游服务器发送的HTTP请求头
proxy_set_header X-Real-IP $remote_addr; # 设置发送给上游服务器的客户端的真实IP地址
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 记录从客户端到最后一个代理服务器之间所有节点的IP地址
}
# 2.用户访问 <http://ip>:port/README.md,则反向代理到https://github.com/.../README.md
location /README.md {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass <https://github.com/moonbingbing/openresty-best-practices/blob/master/README.md>;
}
}
}
三、示例
技术方案
-
全局配置
- 并发能力:3 个工作进程,每个进程最多 3000 个连接(可以处理 3×3000=9000 个并发连接)
- 日志记录:日志记录路径为 logs/error.log,只记录 warn 级别以上的日志
-
本地服务器
-
端口:80
-
功能
- 处理所有默认到达此服务器的请求
- 转发 /remote_upstream/ 的请求到 “远程服务器”
- 转发 /local_upstream/ 的请求到本地的 8082 端口服务
-
-
本地服务
- 地址:localhost:8082
- 功能:处理本地服务器转发到 8082 的请求,保护本地服务(无法从外部访问)
-
远程服务器
- 地址:localhost:8080
- 根目录:/data/remote_upstream
- 功能:作为一个上游服务器,配置中有其他路径会将请求转发到这里(
proxy_pass
)
工作流程
-
/remote_upstream/
- 用户访问 http://localhost/remote_upstream/my_resource.html
- 本地服务器接收默认请求(80 端口)
- 本地服务器识别 URL,将请求转发到 “远程服务器”
- “远程服务器”接收请求并从 root 路径获取 my_resource.html 资源
-
用户访问 localhost/xxx.gif ,则由第二个 server 从服务器的 /data/images/ 地址获取 /data/images/xxx.gif 资源
代码实现
-
配置文件(nginx/conf/nginx.conf)
worker_processes 3; pid logs/nginx.pid; error_log logs/error.log warn; events { worker_connections 3000; } http { # 本地服务器 server { listen 80 default_server; # 监听 80 端口,并设置为默认服务器 location /remote_upstream/ { # 代理 /remote_upstream/ 路径的请求到 localhost:8080 proxy_pass <http://localhost:8080/>; } location ~ \.(gif|jpg|png)$ { # 匹配 .gif, .jpg, .png 结尾的请求,并从 /data/images 目录中提供这些文件 root /data/images; } # 反向代理 /local_upstream/ 路径的请求到 localhost 的 8082 端口 location /local_upstream/ { proxy_pass <http://localhost:8082/>; # local_upstream 服务所在地址 proxy_set_header Host $host; # 传递客户端原始的域名 proxy_set_header X-Real-IP $remote_addr; # 传递客户端的真实 IP 地址 # 传递 "原始客户端的 IP 地址" 和 "可能由其他代理服务器添加的 X-Forwarded-For 头部信息" proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # 传递客户端请求使用的协议(http || https) proxy_http_version 1.1; # 此协议可以支持长连接(keep-alive) proxy_set_header Connection "keep-alive"; # 保持后端连接 keepalive_timeout 3600s; # 保持连接时间为 3600 秒(1h) # 设置超时时间 proxy_connect_timeout 90s; # 连接到后端服务器的超时时间为 90 秒 proxy_send_timeout 90s; # 发送请求到后端服务器的超时时间为 90 秒 proxy_read_timeout 90s; # 从后端服务器读取响应的超时时间为 90 秒 client_max_body_size 100m; # 限制上传到后端服务器的请求体最大为 100MB } } # 模拟的一个远程服务器 server { listen 8080; root /data/remote_upstream; location / { } } }
四、location 正则匹配
⭐ 参考资料:[location 匹配规则 · OpenResty最佳实践 (gitbooks.io)](https://moonbingbing.gitbooks.io/openresty-best-practices/content/ngx/nginx_local_pcre.html)-
实现方式:location 的正则匹配功能
-
匹配规则
模式 含义 location =
/uri= 表示精确匹配,只有完全匹配上才能生效 location ^~
/uri^~ 开头对URL路径进行前缀匹配,并且在正则之前。 location ~
pattern开头表示区分大小写的正则匹配 location ~*
pattern开头表示不区分大小写的正则匹配 location /uri
不带任何修饰符,也表示前缀匹配,但是在正则匹配之后 location /
通用匹配,任何未匹配到其它location的请求都会匹配到,相当于switch中的default -
最大匹配原则:前缀匹配,如果有包含关系时,按最大匹配原则进行匹配
- 示例:存在前缀匹配
location /dir01
与location /dir01/dir02
,客户端请求http://localhost/dir01/dir02/file
将最终匹配到location /dir01/dir02
- 示例:存在前缀匹配