Nginx 基于 upstream 实现动静分离

概述

1. 什么是动静分离

动静分离是指通过 Nginx 等中间件将网站的静态资源(如图片、CSS、JS、HTML 等)和动态资源(如 PHP、Java 等后端程序生成的内容)分开处理,分配到不同的服务器或服务节点上,实现请求的分流处理。

2. 为什么需要实现动静分离

  1. 减少请求消耗:静态资源无需经过后端程序框架的逻辑运算,直接由 Nginx 返回给客户端,缩短请求链路。

  2. 降低响应延时:Nginx 处理静态资源的性能远高于后端应用服务器,能快速响应客户端请求。

  3. 减轻后端压力:后端服务器仅处理动态请求(如数据查询、业务逻辑处理),避免被大量静态资源请求占用资源。

  4. 便于扩展维护:静态资源可部署在专用服务器或 CDN,动态服务可独立扩容,按需分配资源。

3. 未分离 vs 分离后的请求流程

未分离架构 分离后架构
1. 客户端发起请求 → 中间件(Nginx/Apache) 1. 客户端发起请求 → Nginx
2. 中间件转发请求 → 程序框架 2. Nginx 判断资源类型:
- 静态资源 → 直接返回客户端
- 动态资源 → 转发至后端服务器
3. 程序框架执行逻辑 → 请求数据 3. 后端服务器处理动态逻辑 → 返回结果给 Nginx
4. 数据经框架、中间件 → 客户端 4. Nginx 转发结果 → 客户端

可见,分离后静态资源请求仅需 2 步即可完成,大幅提升效率。

动静分离实现方案(基于 upstream)

Nginx 的 upstream 模块用于定义后端服务器组,支持负载均衡和请求转发,是实现动静分离的核心组件。以下提供两种实用配置方案,适用于不同场景。

方案一:单服务器动静分离(Nginx + 本地 Apache)

适用于小型项目,静态资源由 Nginx 本地处理,动态资源转发至本地 Apache 服务器(需修改 Apache 默认端口为 81,避免与 Nginx 80 端口冲突)。

1. 核心配置文件(子配置文件)

文件路径:/etc/nginx/conf.d/www.xiaobudiu.top.conf(子配置文件便于管理,通过主配置文件引入)

# 定义动态资源服务器组(Apache 服务器)
upstream php_api {
    server 127.0.0.1:81; # 本地 Apache 服务地址(端口 81)
}

server {
    listen       80; # Nginx 监听端口
    server_name  www.xiaobudiu.top; # 域名

    # 访问日志配置
    access_log  /etc/nginx/logs/access/www.xiabudiu.top.access.log  main;
    root /data/www; # 项目根目录(静态资源存放路径)

    # 动态资源处理:.php 后缀请求转发至 Apache
    location ~ \.php$ {
        proxy_pass http://php_api; # 转发至 upstream 定义的服务器组
        index  index.html index.htm;
    }

    # 静态资源处理:图片资源(jpg/png/gif)由 Nginx 直接处理
    location ~ \.(jpg|png|gif)$ {
        expires 1h; # 缓存 1 小时,减少重复请求
        gzip on; # 开启 gzip 压缩,减小传输体积
    }

    # 默认请求处理
    location / {
        index  index.html index.htm; # 默认首页
    }

    # 错误页面配置
    error_page   500 502 503 504 404 403  /404.html;
    location = /404.html {
        root   /data/errorPage; # 错误页面存放路径
    }

    # 禁止访问 .htaccess 文件(安全防护)
    location ~ /\.ht {
        deny  all;
    }
}

 

方案二:多服务器集群动静分离(负载均衡)

适用于中大型项目,将静态资源(图片)和动态资源(PHP)分别部署在不同服务器集群,通过 upstream 实现负载均衡。

1. 核心配置文件(子配置文件)

文件路径:/etc/nginx/conf.d/www.xiaobudiu.top.conf

# 定义静态资源(图片)服务器组
upstream image_server {
    server 192.168.0.3:80; # 图片服务器 1
    server 192.168.0.4:80; # 图片服务器 2(负载均衡自动轮询)
}

# 定义动态资源(PHP)服务器组
upstream php_server {
    server 192.168.0.5:80; # PHP 服务器 1
    server 192.168.0.6:80; # PHP 服务器 2(负载均衡自动轮询)
}

server {
    listen       80;
    server_name  www.xiaobudiu.top;

    access_log  /etc/nginx/logs/access/www.xiabudiu.top.access.log  main;

    # 默认请求处理:非动态/图片资源,由本地 Nginx 处理
    location / {
        root /data/www; # 本地静态资源目录(如 HTML、CSS、JS)
        index  index.php index.html; # 默认首页优先级
    }

    # 动态资源处理:.php 后缀请求转发至 PHP 服务器集群
    location ~* \.php$ {
        proxy_pass http://php_server; # 转发至 PHP 服务器组
    }

    # 静态图片处理:指定后缀请求转发至图片服务器集群
    location ~* \.(jpg|png|jpeg|gif)$ {
        proxy_pass http://image_server; # 转发至图片服务器组
    }

    # 错误页面配置
    error_page   500 502 503 504 404 403  /404.html;
    location = /404.html {
        root   /data/errorPage;
    }

    # 禁止访问 .htaccess 文件
    location ~ /\.ht {
        deny  all;
    }
}

Nginx 主配置文件(nginx.conf)

子配置文件需通过主配置文件引入,同时需配置 Nginx 基础参数以优化性能,主配置文件路径:/etc/nginx/nginx.conf

user  nginx; # 运行用户
worker_processes  1; # 工作进程数(建议与 CPU 核心数一致)
worker_rlimit_nofile 65536; # 每个工作进程最大文件打开数

# 错误日志配置
error_log  /etc/nginx/logs/error/error.log warn;
pid        /var/run/nginx.pid; # PID 文件路径

events {
    worker_connections  1024; # 每个工作进程最大连接数
    multi_accept on; # 允许同时接收多个连接
    use epoll; # 使用 epoll 事件模型(高性能,适用于 Linux 系统)
}

http {
    include       /etc/nginx/mime.types; # 引入 MIME 类型配置
    default_type  application/octet-stream; # 默认 MIME 类型

    # 日志格式定义
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /etc/nginx/logs/access/access.log  main; # 访问日志路径

    sendfile        on; # 开启高效文件传输模式
    # tcp_nopush     on; # 关闭 Nagle 算法,适用于大文件传输(可选)

    keepalive_timeout  65; # 长连接超时时间(秒)
    client_max_body_size 20m; # 客户端最大上传文件大小

    # gzip 压缩配置(优化传输性能)
    gzip  on;
    gzip_proxied any; # 对代理请求启用压缩
    gzip_comp_level 3; # 压缩级别(1-9,级别越高压缩率越高但消耗 CPU 越多)
    gzip_min_length 1k; # 最小压缩文件大小
    gzip_buffers 16 32k; # 压缩缓冲区大小
    gzip_http_version 1.0; # 支持的 HTTP 版本
    gzip_types text/plain text/css application/json application/xml+rss text/javascript image/jpeg image/gif image/png; # 需压缩的文件类型

    # FastCGI 相关优化(适用于 PHP 等动态资源)
    fastcgi_buffers 256 16k;
    fastcgi_buffer_size 128k;
    fastcgi_connect_timeout 3s; # 连接超时时间
    fastcgi_send_timeout 120s; # 发送超时时间
    fastcgi_read_timeout 120s; # 读取超时时间
    reset_timedout_connection on; # 重置超时连接
    server_names_hash_bucket_size 100; # 服务器名哈希表大小

    include /etc/nginx/conf.d/*.conf; # 引入所有子配置文件(核心)
}

关键配置说明

1. upstream 服务器组

  • 可定义多个服务器节点,默认采用轮询策略分发请求,实现负载均衡。

  • 支持配置权重(如 server 192.168.0.3:80 weight=5;),权重越高,分配到的请求越多。

2. location 匹配规则

  • ~:区分大小写的正则匹配(如 ~ \.PHP$ 仅匹配 .PHP,不匹配 .php)。

  • ~*:不区分大小写的正则匹配(推荐用于资源后缀匹配)。

  • 匹配优先级:精确匹配(=)> 正则匹配(~/~*)> 普通前缀匹配。

3. 静态资源优化

  • expires 1h:设置浏览器缓存时间,减少重复请求,可根据资源类型调整(如图片设为 7 天,CSS/JS 设为 12 小时)。

  • gzip on:开启压缩后,静态资源体积可减小 30%-70%,大幅提升传输速度。

集群数据同步方案

多服务器集群场景下,需保证各节点静态资源(如图片)一致性,推荐使用 rsync 工具实现文件同步,支持增量同步、定时同步,也可结合 inotify 实现实时同步。参考文档:https://www.cnblogs.com/miclesvic/p/6189540.html

注意事项

1. 端口冲突

确保 Nginx 与后端服务器(如 Apache)监听端口不同(如 Nginx 80 端口,Apache 81 端口)。

2. 权限配置

Nginx 运行用户(如 nginx)需拥有项目目录和日志目录的读写权限,避免权限不足导致的 403 错误。

3. 配置验证与重载

  • 修改配置后,先执行 nginx -t 验证配置语法正确性。

  • 验证通过后,执行 nginx -s reload 重载配置(无需重启 Nginx,不影响现有连接)。

4. 官方文档参考

Nginx proxy 模块详细参数可查阅官方文档:http://nginx.org/en/docs/http/ngx_http_proxy_module.html

适用场景

方案 适用场景 优势 不足
方案一(单服务器) 小型项目、个人博客、测试环境 配置简单、部署成本低 无负载均衡,性能上限低
方案二(多服务器集群) 中大型项目、高并发场景 负载均衡、可扩展性强、性能稳定 部署复杂,需数据同步机制

根据项目规模和并发需求选择合适方案,中小型项目推荐方案一,大型生产环境推荐方案二并结合 CDN 进一步优化静态资源访问速度。