在Web开发中,前后端分离架构已经成为主流。前端负责页面展示,后端专注于业务逻辑和数据处理,两者通过API接口通信。但如何让前端页面和后端服务和谐工作,避免复杂的跨域问题,并且让用户访问更便捷?这时,Nginx的反向代理功能就能派上大用场。
一、什么是反向代理?¶
先从基础概念说起。我们先回忆一下正向代理:比如你需要访问国外网站,直接访问不了,于是通过VPN(虚拟专用网络)代理你的请求,这就是正向代理。此时VPN代理的是客户端,你不知道目标服务器的真实地址。
而反向代理则相反,它代理的是服务器。用户访问的是反向代理服务器(比如Nginx),但反向代理服务器会根据请求内容,将请求转发到后端真实的服务器上。对用户来说,反向代理服务器就像后端服务器本身,用户不需要知道后端服务的具体地址。
二、为什么前后端分离需要反向代理?¶
假设你有一个前端项目(比如Vue或React)和一个后端API服务(比如Node.js或Java),它们可能运行在不同的服务器或端口上。没有反向代理时,用户需要分别访问前端和后端地址(例如http://frontend.com和http://backend.com/api),这样会带来几个问题:
- 域名管理复杂:用户需要记住多个域名。
- 跨域问题:前端直接调用不同域名的后端接口会触发浏览器的跨域限制。
- 安全隐患:直接暴露后端服务地址,增加被攻击风险。
而反向代理可以解决这些问题:
- 统一域名:用户只需要访问一个域名(例如https://example.com)。
- 隐藏后端:用户请求被Nginx拦截后转发到后端,后端地址对用户透明。
- 路径代理:不同路径请求(如/对应前端,/api对应后端)由Nginx自动分配。
三、Nginx安装与基本配置¶
1. 安装Nginx¶
以Ubuntu为例,安装命令:
sudo apt update
sudo apt install nginx
CentOS用户:
sudo yum install nginx
Windows用户可从Nginx官网下载安装包,按提示安装。
2. 启动与验证¶
安装完成后,启动Nginx:
sudo systemctl start nginx
检查状态:
sudo systemctl status nginx
此时访问服务器IP或域名(如http://localhost),能看到Nginx的默认欢迎页面,说明安装成功。
四、反向代理实战:前端+后端分离配置¶
假设我们有两个服务:
- 前端服务:静态HTML文件(放在Nginx的/usr/share/nginx/html目录下)。
- 后端服务:一个简单的Node.js API服务,运行在本地3000端口(返回{"message": "Hello from backend"})。
1. 准备前端静态文件¶
在Nginx的默认网站目录(Ubuntu/CentOS通常是/usr/share/nginx/html)下创建前端页面:
sudo nano /usr/share/nginx/html/index.html
写入简单内容:
<!DOCTYPE html>
<html>
<body>
<h1>前端页面</h1>
<p>点击按钮调用后端接口:</p>
<button onclick="callBackend()">调用API</button>
<script>
function callBackend() {
fetch('/api/user')
.then(res => res.json())
.then(data => alert(data.message));
}
</script>
</body>
</html>
2. 启动后端服务¶
用Node.js创建一个简单的后端服务(需先安装Node.js):
# 创建项目目录
mkdir backend && cd backend
# 初始化项目
npm init -y
# 安装Express
npm install express
创建app.js:
const express = require('express');
const app = express();
const port = 3000;
app.get('/user', (req, res) => {
res.json({ message: 'Hello from backend!' });
});
app.listen(port, () => {
console.log(`后端服务运行在 http://localhost:${port}`);
});
启动后端:
node app.js
3. 配置Nginx反向代理¶
编辑Nginx配置文件,将请求转发到前端或后端:
sudo nano /etc/nginx/sites-available/default
在server块中添加以下配置(完整配置参考下方示例):
server {
listen 80;
server_name localhost; # 替换为你的域名或服务器IP
# 前端静态资源:所有路径(除/api外)都指向前端页面
location / {
root /usr/share/nginx/html; # 前端文件目录
index index.html; # 默认首页
try_files $uri $uri/ /index.html; # 支持前端路由(如/#/about)
}
# 后端API:所有以/api开头的请求转发到后端服务
location /api {
proxy_pass http://localhost:3000; # 后端服务地址
proxy_set_header Host $host; # 传递Host头,让后端知道请求来源
proxy_set_header X-Real-IP $remote_addr; # 传递真实IP
}
}
4. 验证配置并重启Nginx¶
测试配置是否有误:
sudo nginx -t
若提示test is successful,则重启Nginx:
sudo systemctl restart nginx
5. 测试效果¶
- 访问
http://localhost(或你的域名),能看到前端页面。 - 点击页面上的“调用API”按钮,会触发
fetch('/api/user'),此时Nginx会将请求转发到后端服务http://localhost:3000/user,并返回数据。
五、核心配置解析¶
1. location块¶
Nginx通过location定义不同路径的处理规则。常用匹配方式:
- location /:匹配所有路径(需放在其他location前面)。
- location /api:匹配以/api开头的路径。
2. proxy_pass¶
proxy_pass用于指定转发的目标地址,格式为http://目标IP:端口。例如:
location /api {
proxy_pass http://127.0.0.1:3000; # 也可写localhost:3000
}
3. proxy_set_header¶
传递HTTP头信息给后端,常见场景:
- Host $host:后端获取真实请求域名。
- X-Real-IP $remote_addr:后端获取用户真实IP(避免后端日志显示Nginx的IP)。
六、常见问题与解决¶
-
Nginx启动失败:
用nginx -t检查配置语法,错误信息通常会指出问题行。 -
前端资源404:
确保root路径和index文件存在,例如:
location / {
root /usr/share/nginx/html; # 路径必须正确
index index.html; # 文件必须存在
}
- 后端接口无法访问:
检查后端服务是否启动,端口是否被占用,proxy_pass是否写对地址(如http://localhost:3000而非localhost:3000)。
七、总结¶
反向代理是Nginx的核心功能之一,尤其在前后端分离架构中,它能帮我们:
- 隐藏后端服务地址,提升安全性。
- 统一域名和路径,简化用户访问。
- 集中管理请求转发,便于后续扩展(如负载均衡、缓存)。
通过本文的示例,你已经可以快速上手配置反向代理,让前端和后端服务无缝协作。接下来可以尝试将后端服务换成Java、Python等其他技术栈,或进一步学习Nginx的缓存、SSL配置等高级功能。