032_Nginx 学习笔记(前后端分离架构核心应用)

一、Nginx 安装(以 Ubuntu 为主,兼容主流系统)

1.1 Ubuntu 系统安装(推荐 APT 方式,稳定易维护)

1.1.1 基础安装(官方稳定版)

bash

运行

# 1. 更新软件源
sudo apt update

# 2. 安装 Nginx(Ubuntu 默认源为稳定版)
sudo apt install nginx -y

# 3. 验证安装(可选,安装后自动启动)
nginx -v # 输出版本号即安装成功,如 nginx/1.18.0 (Ubuntu)

1.1.2 编译安装(自定义功能,进阶场景)

适用于需要自定义模块(如 SSL、缓存)的场景:

bash

运行

# 1. 安装编译依赖
sudo apt install gcc make libpcre3 libpcre3-dev zlib1g zlib1g-dev libssl-dev -y

# 2. 下载源码(替换为最新版本)
wget http://nginx.org/download/nginx-1.24.0.tar.gz
tar -zxvf nginx-1.24.0.tar.gz
cd nginx-1.24.0

# 3. 配置编译参数(自定义安装路径+模块)
./configure --prefix=/usr/local/nginx 
            --with-http_ssl_module 
            --with-http_gzip_static_module 
            --with-http_stub_status_module

# 4. 编译并安装
make && sudo make install

# 5. 创建软链接(方便全局调用)
sudo ln -s /usr/local/nginx/sbin/nginx /usr/bin/nginx

1.2 其他系统安装(简要补充)

系统

安装命令

CentOS 7/8

sudo yum install nginx -y(需先配置 EPEL 源)

Windows

下载官网 zip 包(
https://nginx.org/en/download.html),解压后直接运行 nginx.exe

Docker

docker run -d –name nginx -p 80:80 nginx:latest

1.3 安装验证

bash

运行

# 1. 检查版本
nginx -v

# 2. 检查配置语法(核心!避免安装后配置错误)
nginx -t

# 3. 访问默认页面(Ubuntu)
curl http://localhost # 输出 Nginx 默认欢迎页 HTML 即成功

二、使用 systemctl 管理 Nginx 服务(Ubuntu 16.04+ 主流方案)

2.1 核心前提:systemd 服务文件

  • APT 安装的 Nginx 自动生成服务文件:/lib/systemd/system/nginx.service
  • 编译安装的 Nginx 需手动创建服务文件(见 2.5 节)

2.2 常用 systemctl 命令(高频操作)

操作目标

命令

说明

启动服务

sudo systemctl start nginx

启动 Nginx 服务

停止服务

sudo systemctl stop nginx

停止 Nginx 服务(会中断现有连接)

重启服务

sudo systemctl restart nginx

重启服务(配置修改涉及核心参数时用,如 worker_processes)

重载配置

sudo systemctl reload nginx

重载配置(不中断现有连接,修改 server/location 后优先用)

查看服务状态

sudo systemctl status nginx

查看运行状态(Active: active (running) 为正常)

开机自启

sudo systemctl enable nginx

配置开机自动运行

关闭开机自启

sudo systemctl disable nginx

撤销开机自动运行

查看自启状态

sudo systemctl is-enabled nginx

输出 enabled/disabled 表明是否自启

刷新服务配置

sudo systemctl daemon-reload

修改 service 文件后需执行,让 systemd 识别修改

2.3 开机自启配置(关键!生产环境必配)

bash

运行

# 1. 开启开机自启
sudo systemctl enable nginx
# 成功输出:Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /lib/systemd/system/nginx.service.

# 2. 验证自启状态
sudo systemctl is-enabled nginx # 输出 enabled

# 3. 重启系统验证(可选)
sudo reboot
sudo systemctl status nginx # 显示 active (running) 即自启成功

2.4 服务日志查看(排查问题核心)

bash

运行

# 1. 查看 Nginx 系统日志(systemd 管理日志)
journalctl -u nginx -xe # -xe 显示详细错误信息

# 2. 查看 Nginx 访问/错误日志(默认路径)
tail -f /var/log/nginx/access.log # 实时查看访问日志
tail -f /var/log/nginx/error.log  # 实时查看错误日志

2.5 手动编译安装 Nginx 的 systemd 服务配置

编译安装的 Nginx 无默认 service 文件,需手动创建:

bash

运行

# 1. 创建服务文件
sudo vim /etc/systemd/system/nginx.service

写入以下内容(根据编译安装路径调整):

ini

[Unit]
Description=nginx - High Performance Web Server
Documentation=http://nginx.org/en/docs/
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
# 编译安装的 Nginx 可执行文件路径
ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
# 停止命令
ExecStop=/usr/local/nginx/sbin/nginx -s stop
# 重载配置
ExecReload=/usr/local/nginx/sbin/nginx -s reload
# 强制停止
ExecStop=/bin/kill -s QUIT $MAINPID
# PID 文件路径(编译安装默认路径)
PIDFile=/usr/local/nginx/logs/nginx.pid
PrivateTmp=true
# 服务失败时自动重启
Restart=on-failure

[Install]
WantedBy=multi-user.target

生效配置:

bash

运行

sudo systemctl daemon-reload # 刷新配置
sudo systemctl enable nginx  # 开启自启
sudo systemctl start nginx   # 启动服务

三、Nginx 解决前后端分离跨域问题

3.1 跨域本质:浏览器同源策略

浏览器要求请求的「协议、域名、端口」三者完全一致(同源),否则拦截响应。例如:

  • 前端:http://localhost:8080 → 后端:http://localhost:3000/api(端口不同)→ 跨域报错。

3.2 核心方案 1:反向代理(生产最优解,无侵入后端)

3.2.1 配置原理

前端请求「同域的 Nginx」(如 http://localhost/api),Nginx 转发请求到后端服务;对浏览器而言是同域请求,无跨域问题。

3.2.2 完整配置示例(托管前端 + 代理 API)

nginx

# 全局配置(Ubuntu 路径:/etc/nginx/nginx.conf 或 /etc/nginx/conf.d/cors.conf)
http {
    # 定义后端服务集群(单实例也可配置)
    upstream backend_api {
        server 192.168.1.100:8080; # 后端 API 地址
        # 多实例:server 192.168.1.101:8080;
    }

    server {
        listen 80;
        server_name localhost; # 前端访问的域名/IP

        # 1. 托管前端静态资源(Vue/React 打包后的 dist 目录)
        root /usr/share/nginx/html;
        index index.html;

        # 2. 反向代理后端 API(核心:解决跨域)
        location /api/ {
            proxy_pass http://backend_api/; # 转发到后端服务(末尾/关键!)
            # 传递客户端真实信息给后端
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            # 超时配置
            proxy_connect_timeout 60s;
            proxy_read_timeout 60s;
        }

        # 3. 解决 SPA 前端路由刷新 404(Vue/React Router history 模式)
        location / {
            try_files $uri $uri/ /index.html;
        }
    }
}

3.2.3 关键配置项解释

配置项

作用

root /usr/share/nginx/html

指定前端静态资源目录,Nginx 自动托管 HTML/CSS/JS

location /api/

匹配所有 /api 开头的请求(前端 API 路径)

proxy_pass http://backend_api/

转发请求到后端;末尾 / 需加:前端 /api/user → 后端 /user(否则为 /api/user)

try_files

SPA 刷新时优先找静态文件,找不到返回 index.html,避免 404

3.3 核心方案 2:CORS 响应头配置(备选,后端无法修改时)

3.3.1 配置原理

Nginx 在转发响应时添加 CORS 头,告知浏览器 “允许该源跨域访问”,需处理「简单请求」和「预检请求(OPTIONS)」。

3.3.2 完整配置示例

nginx

server {
    listen 80;
    server_name api.example.com; # 后端 API 域名(前端直接请求该域名)

    location / {
        # 允许的跨域源(生产环境指定具体域名,如 http://www.example.com)
        add_header Access-Control-Allow-Origin *;
        # 允许的请求方法
        add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';
        # 允许的请求头(含自定义头,如 token)
        add_header Access-Control-Allow-Headers 'Content-Type, Authorization, Token';
        # 预检请求缓存时间(避免频繁发 OPTIONS)
        add_header Access-Control-Max-Age 3600;

        # 处理预检请求(OPTIONS)
        if ($request_method = 'OPTIONS') {
            return 204; # 无需返回内容,204 即可
        }

        # 转发到后端服务
        proxy_pass http://192.168.1.100:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

3.3.3 跨域携带 Cookie 配置(需前后端配合)

  1. Nginx 配置(Origin 必须指定具体域名,不能用 *):
  2. nginx
  3. location /api/ { add_header Access-Control-Allow-Origin http://www.example.com; # 前端域名 add_header Access-Control-Allow-Credentials true; # 允许携带 Cookie proxy_pass http://backend_api/; }
  4. 前端配置(Axios 示例):
  5. javascript
  6. 运行
  7. axios({ url: '/api/user', method: 'GET', withCredentials: true // 开启携带 Cookie })

3.3.4 允许多域名跨域

nginx

# 定义允许的域名列表
map $http_origin $allow_origin {
    ~^http://www.example.com$ http://www.example.com;
    ~^http://m.example.com$ http://m.example.com;
    default ""; # 其他域名拒绝
}

server {
    listen 80;
    server_name api.example.com;

    location /api/ {
        add_header Access-Control-Allow-Origin $allow_origin;
        add_header Access-Control-Allow-Credentials true;
        add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';
        if ($request_method = 'OPTIONS') {
            return 204;
        }
        proxy_pass http://backend_api/;
    }
}

3.4 开发环境 vs 生产环境跨域方案对比

场景

推荐方案

缘由

开发环境

前端脚手架代理(Vue/Vite/React)

无需部署 Nginx,配置简单(devServer.proxy),调试高效

生产环境

Nginx 反向代理

无侵入后端、兼顾静态资源托管 / 负载均衡,安全稳定

3.5 跨域配置避坑指南

  1. proxy_pass 末尾 / 易错:location /api/ + proxy_pass http://backend/ → 转发 /api/user 为 /user;无 / 则为 /api/user。
  2. 预检请求未处理:非简单请求(PUT/DELETE)先发 OPTIONS,需配置 if ($request_method = 'OPTIONS') { return 204; }。
  3. Cookie 跨域报错:Access-Control-Allow-Origin 用 * 且开启 withCredentials,需改为具体域名。
  4. 配置不生效:先执行 nginx -t 检查语法,再 systemctl reload nginx 重载,最后清浏览器缓存。

四、Nginx 实现后端服务负载均衡

4.1 负载均衡核心原理

通过 upstream 模块定义后端服务集群,Nginx 将前端请求分发到不同后端实例,提升吞吐量和可用性。

4.2 upstream 模块基础配置

nginx

http {
    # 定义后端集群(名称自定义,如 backend_server)
    upstream backend_server {
        # 后端实例配置(IP:端口)
        server 192.168.1.10:8080 weight=1; # weight=权重,默认1
        server 192.168.1.11:8080 weight=2; # 权重2,接收2/3的请求
        server 192.168.1.12:8080 backup;   # 备用节点,主节点故障时启用
        server 192.168.1.13:8080 down;     # 下线节点,不接收请求
    }

    server {
        listen 80;
        server_name localhost;

        # 代理到后端集群
        location /api/ {
            proxy_pass http://backend_server/;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }
}

4.3 常用负载均衡策略

策略

配置方式

适用场景

轮询(默认)

upstream { server A; server B; }

后端实例性能一致

权重(weight)

server A weight=2; server B weight=1;

后端实例性能不同(高性能节点权重高)

IP 哈希(ip_hash)

upstream { ip_hash; server A; server B; }

需会话粘滞(同一客户端请求同一实例)

最少连接(least_conn)

upstream { least_conn; server A; server B; }

后端请求处理时间差异大

4.4 完整配置示例(负载均衡 + 健康检查)

Nginx 原生无主动健康检查,可通过 max_fails/fail_timeout 实现被动健康检查:

nginx

upstream backend_server {
    ip_hash; # 会话粘滞
    server 192.168.1.10:8080 weight=2 max_fails=3 fail_timeout=30s;
    server 192.168.1.11:8080 weight=1 max_fails=3 fail_timeout=30s;
    # max_fails:失败次数阈值(默认1)
    # fail_timeout:失败后隔离时间(默认10s)
}

server {
    listen 80;
    server_name localhost;

    location /api/ {
        proxy_pass http://backend_server/;
        # 基础代理配置
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        # 超时配置
        proxy_connect_timeout 10s;
        proxy_read_timeout 30s;
        proxy_send_timeout 30s;
        # 重试配置
        proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
        proxy_next_upstream_tries 3; # 重试次数
    }
}

4.5 负载均衡进阶配置(超时 / 重试)

配置项

作用

proxy_connect_timeout 10s

连接后端超时时间

proxy_read_timeout 30s

读取后端响应超时时间

proxy_next_upstream

后端返回指定错误时,重试下一个实例(如 502/503)

proxy_next_upstream_tries 3

最大重试次数(避免无限重试)

五、FAQ(常见问题解答)

5.1 安装相关

Q1:Ubuntu 安装 Nginx 后启动失败,提示 80 端口被占用?

A1:执行 sudo lsof -i :80 查看占用进程(如 Apache、sshd),停止占用进程:sudo systemctl stop apache2,再启动 Nginx:sudo systemctl start nginx。

Q2:编译安装 Nginx 后,执行 nginx 命令提示 “command not found”?

A2:创建软链接:sudo ln -s
/usr/local/nginx/sbin/nginx /usr/bin/nginx,或直接执行
/usr/local/nginx/sbin/nginx。

5.2 systemctl 管理相关

Q1:执行 systemctl enable nginx 提示 “Unit nginx.service could not be found”?

A1:缘由是无 systemd 服务文件(编译安装未创建),按 2.5 节手动创建 nginx.service 文件,再执行 sudo systemctl daemon-reload。

Q2:Nginx 开机自启配置后,重启系统仍未启动?

A2:排查步骤:

  1. 查看启动日志:journalctl -u nginx -xe;
  2. 检查配置语法:nginx -t;
  3. 检查端口占用:sudo lsof -i :80;
  4. 检查权限:Nginx 托管目录需赋予 www-data 权限:sudo chown -R www-data:www-data /usr/share/nginx/html。

5.3 跨域相关

Q1:Nginx 反向代理配置后,前端仍报跨域错误?

A1:常见缘由:

  1. proxy_pass 末尾 / 未加,导致后端路径匹配失败;
  2. 前端请求地址错误(未请求 Nginx 域名,仍直接请求后端);
  3. 浏览器缓存了旧的预检请求,需清空缓存。

Q2:跨域携带 Cookie 时,浏览器提示 “The value of 'Access-Control-Allow-Origin' header must not be '*'”?

A2:
Access-Control-Allow-Origin 不能用 *,需指定具体前端域名(如 http://www.example.com),且前端需开启 withCredentials: true。

Q3:开发环境需要用 Nginx 解决跨域吗?

A3:不需要。前端脚手架(Vue/Vite/React)自带 devServer.proxy 代理功能,配置简单且调试高效,无需部署 Nginx。

5.4 负载均衡相关

Q1:IP 哈希策略下,新增后端实例后,会话是否会失效?

A1:会。IP 哈希基于客户端 IP 计算节点,新增 / 删除实例会改变哈希结果,可通过 weight 平滑过渡,或使用分布式会话(如 Redis)替代 IP 哈希。

Q2:Nginx 负载均衡如何实现健康检查?

A2:Nginx 原生仅支持被动健康检查(max_fails/fail_timeout),主动健康检查需安装第三方模块(如
nginx_upstream_check_module),或使用云厂商 SLB、专业网关(如 Kong)。

5.5 其他核心问题

Q1:Ubuntu 中 Nginx 有哪些配置方式?

A1:主流方式(按推荐度):

  1. sites-available/sites-enabled(Ubuntu 特有,多站点管理);
  2. conf.d 目录(通用,单站点 / 简单配置);
  3. 直接修改 nginx.conf(仅临时测试);
  4. include 引入自定义配置(复杂配置拆分);
  5. 命令行临时覆盖(仅测试,不持久化)。

Q2:Nginx 托管前端静态资源时,刷新页面报 404?

A2:SPA 应用(Vue/React)history 模式下,需配置 try_files $uri $uri/ /index.html;,让 Nginx 找不到静态文件时返回 index.html。

Q3:生产环境必须用 Nginx 吗?

A3:前后端分离架构中,Nginx 不是技术必需,但却是工程最优解。生产环境下,它能解决跨域、静态资源高性能托管、负载均衡、安全防护等核心问题,是企业级项目标配。

© 版权声明

相关文章

暂无评论

none
暂无评论...