Nginx(三) 深入解析Nginx反向代理的应用场景与实现
反向代理
浏览器客户端
发送请求到反向代理服务器
(⽐如Nginx),由反向代理服务器选择原始服务器提供服务获取结果响应,最终再返回给客户端浏览器。
应用场景
需求一:隐藏目标服务器细节
浏览器
请求nginx
(43.143.176.14:80),nginx将请求转发给了目标服务器
(127.0.0.1:8752),我们看到的是目标服务器的响应页面,在整个过程中目标服务器相当于对客户端是不可见的
,服务端向外暴露的就是nginx的地址。这在安全性上有一定优势,可以保护目标服务器的真实地址和架构。
需求一实现
步骤一:创建后端服务器
创建一个springboot项目,打成jar,上传到服务器,启动。这里用现成的接口随便写了一下,主要为了看下ip地址和端口:name("http://"+localAddr +":"+ serverPort)
,下面是接口代码
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping(value = "/{user_id}")
public UserResponse getUserInfo() {
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = requestAttributes.getRequest();
String localAddr = request.getLocalAddr();
int serverPort = request.getServerPort();
return UserResponse.builder()
.id("1")
.name("http://"+localAddr +":"+ serverPort)
.address("shanxi")
.age(20)
.build();
}
}
步骤二:配置Nginx
配置Nginx的location
块,进入到./nginx/conf/nginx.conf,修改 Nginx 配置,proxy_pass http://127.0.0.1:7903/;
详细如下:
详细代码:
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
#这里配置被代理的服务器
proxy_pass http://127.0.0.1:7903/;
#root html; #默认的网站根目录位置
#index index.html index.htm; #索引页,欢迎页
}
}
步骤三:重新加载Nginx配置:
./nginix -s reload
步骤四:测试
访问http://43.143.176.14:80/user/1
注意:对于HTTP请求,如果没有指定端口号,例如
http://43.143.176.14/user/1
,那么浏览器会默认使用80端口。同样,如果指定了80端口,例如http://43.143.176.14:80/user/1
,由于80端口是HTTP的默认端口,浏览器也会将其视为等价于不带端口号的情况。如果配置的是其他端口号,那么访问时要加端口号例如http://43.143.176.14:8080/user/1
需求二:多个反向代理路径匹配
这次目标服务器有两个,分别是 127.0.0.1:8752,127.0.0.1:7903,当访问http://43.143.176.14/abc/user/1
时,实际访问127.0.0.1:7903/user/1,当访问http://43.143.176.14/def/user/1
时,实际访问127.0.0.1:8752/user/1。
需求二实现
步骤一:创建后端服务器
同样的项目,修改端口,一个8752,一个7903,打成jar包,上传到服务器,分别启动。
步骤二:修改Nginx
修改 Nginx 配置:增加一份location配置,如下:
详细代码:
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location /abc {
#这里配置被代理的服务器
proxy_pass http://127.0.0.1:7903/;
#root html; #默认的网站根目录位置
#index index.html index.htm; #索引页,欢迎页
}
location /def {
#这里配置被代理的服务器
proxy_pass http://127.0.0.1:8752/;
#root html; #默认的网站根目录位置
#index index.html index.htm; #索引页,欢迎页
}
}
步骤三:重新加载Nginx配置
./nginix -s reload
步骤四:测试
分别访问http://43.143.176.14/abc/user/1
和http://43.143.176.14/def/user/1
,测试结果如下
location 语法
location [=|~|~*|^~] /uri/ { … }
代码示例:
location /abc {
#这里配置被代理的服务器
proxy_pass http://127.0.0.1:7903/;
#root html; #默认的网站根目录位置
#index index.html index.htm; #索引页,欢迎页
}
location /def {
#这里配置被代理的服务器
proxy_pass http://127.0.0.1:8752/;
#root html; #默认的网站根目录位置
#index index.html index.htm; #索引页,欢迎页
}
语法示例:
在nginx配置⽂件中,location主要有这⼏种形式:
-
正则匹配
location ~ /aaa { }
: 区分大小写。例如:location ~ /user/\d+ { proxy_pass http://backend_server; #proxy_pass 将请求代理到另一个服务器 }
这会将以
/user/
开头,后跟数字的请求转发到backend_server
。 -
不区分大小写的正则匹配
location ~* /aaa{ }
: 不区分大小写。例如:location ~* /images { root /data; #root 指定根目录,在该根目录下寻找文件。 }
这会将以
/images
开头的请求从/data
目录中获取对应的文件。 -
匹配路径的前缀
location ^~ /aaa{ }
: 此形式匹配请求路径的前缀,不再继续查找其他匹配项。例如:location ^~ /static { alias /data/static; #alias 指定文件在服务器文件系统中的路径,将请求映射到指定文件 }
这会将以
/static
开头的请求从/data/static
目录中获取对应的文件。 -
精确匹配
location = /aaa{ }
: 此形式精确匹配请求路径。例如:location = /favicon.ico { return 200 "Hello, favicon!"; #return 在 Nginx 中生成响应,可以用来返回指定的 HTTP 状态码和消息。 }
这会返回自定义的响应内容,只有在请求路径为
/favicon.ico
时才会触发。 -
普通路径前缀匹配
location /aaa{ }
: 此形式是最常见的路径前缀匹配。例如:location /api { proxy_pass http://api_server; }
这会将以
/api
开头的请求转发到api_server
。
总的来说,不同形式的location
配置可以让你根据请求的不同特点来精确地指定Nginx的处理逻辑。优先级从高到低分别是精确匹配、匹配路径的前缀、不区分大小写的正则匹配、正则匹配和普通路径前缀匹配。也就是优先级:4>3>2>1>5
proxy_pass http://api_server;
}
这会将以`/api`开头的请求转发到`api_server`。
总的来说,不同形式的`location`配置可以让你根据请求的不同特点来精确地指定Nginx的处理逻辑。优先级从高到低分别是精确匹配、匹配路径的前缀、不区分大小写的正则匹配、正则匹配和普通路径前缀匹配。也就是`优先级:4>3>2>1>5`