Nginx详解:高性能Web服务器与反向代理技术

Nginx (engine x) 是一个高性能的 HTTP 和反向代理 Web 服务器,同时也提供了 IMAP/POP3/SMTP 服务。Nginx 是由伊戈尔·赛索耶夫为俄罗斯访问量第二的 Rambler.ru 站点开发的,公开版本 1.19.6 发布于 2020 年 12 月 15 日。

其将源代码以类 BSD 许可证的形式发布,因它的稳定性、丰富的功能集、简单的配置文件和低系统资源的消耗而闻名。Nginx 是一款轻量级的 Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在 BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上 Nginx 的并发能力在同类型的网页服务器中表现较好。

一、BSD 开源协议

BSD 是”Berkeley Software Distribution”的缩写,意思是”伯克利软件发行版”。BSD 这个名称并不是我们现在所理解的操作系统,而是一整套软件发行版的统称。

什么是许可协议呢?当你为你的产品签发许可,你是在让出自己的权利,不过,你仍然拥有版权和专利(如果申请了的话)。许可的目的是向使用你产品的人提供一定的权限。

不管产品是免费向公众分发,还是出售,制定一份许可协议非常有用。否则,对于前者,你相当于放弃了自己所有的权利,任何人都没有义务表明你的原始作者身份;对于后者,你将不得不花费比开发更多的精力用来逐个处理用户的授权问题。

而开源许可协议使这些事情变得简单,开发者很容易向一个项目贡献自己的代码,它还可以保护你原始作者的身份,使你至少获得认可。开源许可协议还可以阻止其它人将某个产品据为己有。以下是开源界的 5 大许可协议:GPL、LGPL、BSD、MIT 和 Apache。BSD 就是这五种开源协议之一。

二、代理模式

代理服务技术是一门很古老的技术,是在互联网早期出现就使用的技术。一般实现代理技术的方式就是在服务器上安装代理服务软件,让其成为一个代理服务器,从而实现代理技术。代理本质上是一个服务器,可以类比为一个中介。为了 A 访问到 B,中间插入一个 C,C 就是代理。

常用的代理技术分为:

  • 正向代理
  • 反向代理
  • 透明代理

2.1 正向代理

正向代理是一个位于客户端和目标服务器之间的代理服务器(中间服务器)。为了从目标服务器取得内容,客户端向代理服务器发送一个请求,并且指定目标服务器,之后代理向目标服务器转发请求,将获得的内容返回给客户端。正向代理的情况下,客户端必须要进行一些特殊的设置才能使用。

正向代理架构示意图:

┌──────────┐     请求      ┌──────────────┐     转发请求    ┌──────────────┐
│  客户端   │ ──────────▶  │  代理服务器   │ ──────────▶  │  目标服务器   │
│ Client   │              │  Proxy Server │              │ Target Server│
└──────────┘  ◀──────────  └──────────────┘  ◀──────────  └──────────────┘
              响应返回                响应返回

一般正向代理有如下使用场景:

  • 科学上网:突破网络访问限制
  • 加速访问服务器:通过代理服务器缓存和优化路由加速访问
  • Cache 缓存作用:会缓存请求信息,如果多次重复请求,不需要访问目标服务器
  • 客户端访问授权:代理服务器可以设置客户端不能对某些服务器进行访问
  • 隐藏访问者踪迹:目标服务器不知道真实客户端是谁,因为请求都是代理服务器发出的

2.2 反向代理

反向代理是指以代理服务器来接收客户端的请求,然后将请求转发给内部网络上的服务器,将从服务器上得到的结果返回给客户端,此时代理服务器对外表现为一个反向代理服务器。对于客户端来说,反向代理就相当于目标服务器,只需要将反向代理当作目标服务器一样发送请求就可以了,并且客户端不需要进行任何设置。

反向代理架构示意图:

┌──────────┐               ┌──────────────┐     转发     ┌──────────────┐
│  客户端   │ ─── 请求 ──▶  │ 反向代理服务器 │ ──────────▶  │  后端服务器A  │
│ Client   │               │  Reverse Proxy│              ├──────────────┤
└──────────┘  ◀── 响应 ──  └──────────────┘  ──────────▶  │  后端服务器B  │
                                              ──────────▶  │  后端服务器C  │
                                                            └──────────────┘

一般反向代理有如下应用场景:

  • 负载均衡:将请求分发到多台后端服务器
  • 隐藏服务器真实 IP 地址:客户端只能看到代理服务器的 IP
  • 提高访问速度:通过负载分担提升整体响应能力
  • 提高安全保障:可以将部分有害请求拦截

2.3 透明代理

透明代理(transparent proxy)的意思是客户端根本不需要知道有代理服务器的存在,它改变你的 request fields(报文),并会传送真实 IP,多用于路由器的 NAT 转发中。注意,加密的透明代理则是属于匿名代理,意思是不用设置使用代理了。

透明代理是一种拦截网络流量的代理方法,采用该方法可将用户所发出数据收集到代理服务器上进行处理,并向使用者发出相应的报文并将结果再发回去。透明代理也称为”隐式代理”(implicit proxy)。

  • 透明代理服务器主要用于网络防火墙保护,把真正的用户和客户端隐藏起来,隔绝外部网络和服务器之间只能通过代理进行访问。
  • 透明代理也可以用于安全性控制,能够阻止用户发起有恶意的网络访问,确保网络数据的安全传输。
  • 透明代理还用于数据流量控制,可以在下行方向上做限速,有效降低网络负载。
  • 透明代理也常用于内容过滤,根据网络安全政策过滤掉恶意或非法的数据。

三、安装 Nginx

3.1 安装前的准备

在安装 Nginx 之前我们需要准备好安装环境,下面的安装环境根据个人系统环境而定,没有安装的要进行安装。

1. 安装 gcc

首先,安装 Nginx 要有 gcc 的环境,先检查电脑是否安装了 gcc。

gcc -v

如果未安装可以使用以下命令进行安装:

yum install -y gcc

gcc 可以编译 C、C++、Ada、Object C 和 Java 等语言(安装 Nginx 需要先将官网下载的源码进行编译,编译依赖 gcc 环境)。

2. 安装 pcre-devel

安装第三方库 pcre-devel,首先检查是否安装了 pcre-devel。

rpm -qa pcre

如果未安装,使用命令安装:

yum install -y pcre pcre-devel

PCRE(Perl Compatible Regular Expressions)是一个 Perl 库,包括 perl 兼容的正则表达式库。Nginx 的 http 模块使用 pcre 来解析正则表达式,所以需要在 Linux 上安装 pcre 库。pcre-devel 是使用 pcre 开发的一个二次开发库,Nginx 也需要此库。

3. 安装 zlib

zlib 也是一个第三方库,这个库提供了很多种压缩和解压缩方式。Nginx 使用 zlib 对 http 包的内容进行 gzip,所以需要安装。

yum list installed | grep zlib*

如果没有安装,也需要进行安装:

yum install -y zlib zlib-devel

4. 安装 OpenSSL(补充)

Nginx 支持 HTTPS 需要 OpenSSL 库:

yum install -y openssl openssl-devel

安装好上面的环境我们就可以开始进行正式的 Nginx 安装了。

3.2 下载 Nginx

  • 可以在 Nginx 的官网下载,下载后上传到虚拟机
  • 也可以使用 wget 命令进行下载:
wget http://nginx.org/download/nginx-1.24.0.tar.gz

3.3 解压 Nginx

tar -zxvf nginx-1.24.0.tar.gz

3.4 编译安装 Nginx

进入到 Nginx 解压后的文件夹执行命令安装:

./configure --prefix=/opt/soft/nginx/  # /opt/soft/nginx/ 指定的安装目录

编译 Nginx:

make && make install

3.5 Nginx 相关命令

进入到安装目录的 sbin 文件夹下:

# 普通启动服务
./nginx

# 配置文件启动
./nginx -c ../conf/nginx.conf

# 暴力停止服务
./nginx -s stop

# 优雅停止服务
./nginx -s quit

# 检查配置文件
./nginx -t

# 重新加载配置(平滑重启,不中断服务)
./nginx -s reload

# 查看版本信息
./nginx -V

# 查看相关进程
ps -ef | grep nginx

3.6 如果启动后出现 403 页面?

修改 conf 文件夹下的 nginx.conf 文件,将使用用户的身份修改为 root 即可:

# 在 nginx.conf 第一行取消注释并修改
user root;

四、Nginx 配置文件结构(补充)

Nginx 的配置文件 nginx.conf 采用分层结构,从外到内依次为:main → events → http → server → location

# main 全局块:影响 Nginx 整体运行的配置
worker_processes  1;    # worker 进程数,建议设为 CPU 核心数

# events 块:影响 Nginx 服务器与用户的网络连接
events {
    worker_connections  1024;  # 每个 worker 进程的最大连接数
}

# http 块:Nginx Web 服务的核心配置
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile      on;
    keepalive_timeout  65;

    # server 块:每个 server 对应一个虚拟主机
    server {
        listen       80;
        server_name  localhost;

        # location 块:匹配不同的 URI 请求
        location / {
            root   html;
            index  index.html index.htm;
        }
    }
}
层级 作用域 常见指令
main 全局 worker_processes, pid, error_log
events 连接 worker_connections, use epoll
http HTTP 服务 include, sendfile, keepalive_timeout, gzip
server 虚拟主机 listen, server_name, ssl
location URL 匹配 root, alias, proxy_pass, rewrite

五、Nginx 进程模型(补充)

Nginx 采用 master-worker 架构,一个 master 进程管理多个 worker 进程。

┌───────────────────────────────────┐
│         Master Process            │  ← 管理进程:读取配置、管理 worker
│    (读取 nginx.conf,管理 worker)   │
└──────────┬───────────┬────────────┘
           │           │
     ┌─────▼───┐ ┌────▼────┐ ┌─────────┐
     │ Worker1 │ │ Worker2 │ │ WorkerN │  ← 工作进程:处理实际请求
     │ (独立)  │ │ (独立)  │ │ (独立)  │     每个 worker 互不干扰
     └─────────┘ └─────────┘ └─────────┘
  • Master 进程:管理 worker 进程,接收来自外界的信号,监控 worker 状态,当 worker 异常退出时自动启动新的 worker。
  • Worker 进程:实际处理请求的进程,多个 worker 之间是对等的,各自独立竞争客户端请求。一个请求只会被一个 worker 处理。
  • worker_processes:建议设为 auto(自动匹配 CPU 核心数)或手动指定 CPU 核心数。
  • worker_connections:每个 worker 的最大连接数,总最大连接数 = worker_processes × worker_connections。

这种架构的优势:worker 进程相互独立,一个 worker 异常崩溃不会影响其他 worker,master 会立即拉起新进程,实现高可用。

六、location 匹配规则(补充)

location 是 Nginx 配置中最核心的指令之一,用于匹配不同的 URL 请求。

6.1 匹配优先级

符号 匹配类型 优先级 说明
= 精确匹配 1(最高) 完全匹配 URI,匹配到立即处理
^~ 前缀匹配 2 匹配前缀后不再进行正则匹配
~ / ~* 正则匹配 3 ~区分大小写,~*不区分
/ 通用匹配 4(最低) 所有请求都会匹配到

6.2 配置示例

server {
    listen 80;
    server_name localhost;

    # 1. 精确匹配:访问 / 时
    location = / {
        proxy_pass http://tomcat:8080;
    }

    # 2. 前缀匹配:以 /static/ 开头的请求
    location ^~ /static/ {
        root /data/web;
        # 请求 /static/css/style.css → /data/web/static/css/style.css
    }

    # 3. 正则匹配:以 .gif/.jpg/.png 结尾的请求
    location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ {
        root /data/web/images;
        expires 30d;  # 缓存 30 天
    }

    # 4. 通用匹配:所有其他请求
    location / {
        proxy_pass http://tomcat:8080;
    }
}

6.3 root 与 alias 的区别

指令 说明 示例
root 将完整的 URI 拼接到 root 路径后面 location /img/ { root /data; } → /data/img/test.jpg
alias 将 location 匹配的部分替换为 alias 路径 location /img/ { alias /data/images/; } → /data/images/test.jpg

七、Nginx 反向代理实战

7.1 基本代理

步骤一:修改 Windows 中的 hosts 域名映射

复制”C:\Windows\System32\drivers\etc\hosts”到桌面,右键记事本打开,在里边加上以下代码保存,然后再复制回去,不要直接修改,会不让保存!

192.168.160.128  dailyblue.com

步骤二:修改 Nginx 中的配置文件

server {
    listen 80;
    server_name dailyblue.com;

    location / {
        proxy_pass http://192.168.160.1:8080;
    }
}

7.2 条件跳转

使用 Nginx 反向代理,根据访问的路径跳转到不同端口的服务中。

配置文件:

location /eat/ {
    proxy_pass   http://192.168.160.1:8083/;  # 必须以 / 结尾
}

location /sleep/ {
    proxy_pass   http://192.168.160.1:8082/;
}

项目启动:把一个 SpringBoot 项目分别启动两次,端口号分别是 8083 和 8082。访问 dailyblue.com/eat/ 走 8083 服务,访问 dailyblue.com/sleep/ 走 8082 服务。

八、Nginx 负载均衡

早期的网站流量和业务功能都比较简单,单台服务器足以满足基本的需求,但是随着互联网的发展,业务流量越来越大并且业务逻辑也跟着越来越复杂,单台服务器的性能及单点故障问题就凸显出来了,因此需要多台服务器进行性能的水平扩展及避免单点故障出现,那么如何将不同用户的请求流量分发到不同的服务器上呢?

这时候我们就要使用到负载均衡,负载均衡(Load Balance)其意思就是分摊到多个操作单元上进行执行,例如 Web 服务器、FTP 服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。

这里面涉及到两个重要的角色分别是”应用集群”和”负载均衡器”。

  • 应用集群:将同一应用部署到多台机器上,组成处理集群,接收负载均衡设备分发的请求,进行处理并返回响应的数据。
  • 负载均衡器:将用户访问的请求根据对应的负载均衡算法,分发到集群中的一台服务器进行处理。

8.1 负载均衡的实现

# 代理服务器
# 设置服务器组
upstream loadBalancing {
    server localhost:8001;
    server localhost:8002;
    server localhost:8003;
}

server {
    listen 80;
    server_name dailyblue.com;

    location / {
        # loadBalancing 就是服务器组的名称
        proxy_pass http://loadBalancing/;
    }
}
  • upstream:该指令是用来定义一组服务器,它们可以是监听不同端口的服务器,并且也可以是同时监听 TCP 和 Unix socket 的服务器。服务器可以指定不同的权重,默认为 1。
  • server:该指令用来指定后端服务器的名称和一些参数,可以使用域名、IP、端口或者 unix socket。

8.2 负载均衡的作用

  • 解决服务器的高并发压力,提高应用程序的处理性能。
  • 提供故障转移,实现高可用。
  • 通过添加或减少服务器数量,增强网站的可扩展性。
  • 在负载均衡器上进行过滤,可以提高系统的安全性。

8.3 负载均衡的状态

状态 概述
down 当前的 server 暂时不参与负载均衡
backup 预留的备份服务器,当主服务器不可用时启用
max_fails 允许请求失败的次数
fail_timeout 经过 max_fails 次失败后,服务暂停的时间
max_conns 限制最大的接收连接数

down 状态:将该服务器标记为永久不可用,那么该代理服务器将不参与负载均衡。该状态一般会对需要停机维护的服务器进行设置。

upstream loadBalance {
    server localhost:8001 down;
    server localhost:8002;
    server localhost:8003;
}

backup 状态:将该服务器标记为备份服务器,当主服务器不可用时,将用来传递请求。

upstream loadBalance {
    server localhost:8001;
    server localhost:8002;
    server localhost:8003 backup;  # 8003 作为 8001、8002 的备份服务器
}

max_fails 和 fail_timeout 状态

upstream loadBalance {
    server localhost:8001;
    server localhost:8002;
    server localhost:8003 max_fails=3 fail_timeout=15;  # 失败 3 次后暂停 15 秒
}

max_conns 状态:用来设置代理服务器同时活动连接的最大数量,默认为 0,表示不限制。

8.4 负载均衡策略

算法名称 说明
轮询 默认方式,按顺序逐一分配
weight 权重方式,权重数字越大,被分配到请求的几率越大
ip_hash 依据 IP 分配方式,通过哈希算法定位到同一台后端服务器
least_conn 依据最少连接方式,把请求转发给连接数较少的后端服务器
url_hash 依据 URL 分配方式,使每个 URL 定向到同一台后端服务器
fair 依据响应时间方式,智能进行负载均衡(第三方模块)

1. 轮询(默认)

upstream loadBalance {
    server localhost:8001;
    server localhost:8002;
    server localhost:8003;
}

2. weight 权重方式

weight=number:用来设置服务器的权重,默认为 1。该权重值主要是针对实际工作环境中不同的后端服务器硬件配置进行调整的,适合服务器硬件配置差别比较大的情况。

upstream loadBalance {
    server localhost:8001 weight=1;
    server localhost:8002 weight=1;
    server localhost:8003 weight=3;  # 高配置机器权重高
}

3. ip_hash 依据 IP 分配方式

当对后端的多台动态应用服务器做负载均衡时,ip_hash 指令能够将某个客户端 IP 的请求通过哈希算法定位到同一台后端服务器上,可以解决 Session 共享问题。

upstream loadBalance {
    ip_hash;
    server localhost:8001;
    server localhost:8002;
    server localhost:8003;
}

注意:使用 ip_hash 指令无法保证后端服务器的负载均衡,可能导致有些后端服务器接收到的请求多,而且设置后端服务器权重等方法将不起作用。

4. least_conn 依据最少连接方式

upstream loadBalance {
    least_conn;
    server localhost:8001;
    server localhost:8002;
    server localhost:8003;
}

5. url_hash 依据 URL 分配方式

按访问 URL 的 hash 结果来分配请求,使每个 URL 定向到同一台后端服务器,要配合缓存命中来使用。

upstream loadBalance {
    hash $request_uri;
    server localhost:8001;
    server localhost:8002;
    server localhost:8003;
}

6. fair 依据响应时间方式

fair 可以根据页面大小、加载时间长短智能地进行负载均衡。fair 属于第三方模块,需要添加 nginx-upstream-fair。

upstream loadBalance {
    fair;
    server localhost:8001;
    server localhost:8002;
    server localhost:8003;
}

九、动静分离(补充)

动静分离是 Nginx 的核心应用场景之一。将静态资源(HTML、CSS、JS、图片等)交给 Nginx 直接处理,动态请求(Java、PHP 等后端接口)转发给后端应用服务器,充分发挥各自优势。

┌──────────┐               ┌──────────────┐     转发动态请求     ┌──────────────┐
│  客户端   │ ─── 请求 ──▶  │     Nginx     │ ──────────────▶  │  Tomcat 后端  │
│ Client   │               │  动静分离网关  │                  └──────────────┘
└──────────┘  ◀── 响应 ──  └──────┬───────┘
                                  │ 直接返回静态资源
                          ┌───────▼───────┐
                          │  静态资源目录   │
                          │  /data/static  │
                          └───────────────┘

配置示例:

server {
    listen 80;
    server_name www.dailyblue.com;

    # 静态资源:Nginx 直接处理
    location /static/ {
        root /data/web;
        autoindex on;  # 开启目录浏览(可选)
    }

    location ~* \.(html|css|js|jpg|png|gif|ico|woff|ttf)$ {
        root /data/web/static;
        expires 30d;  # 静态资源缓存 30 天
        add_header Cache-Control "public, no-transform";
    }

    # 动态请求:转发给后端 Tomcat
    location /api/ {
        proxy_pass http://localhost:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

十、HTTPS/SSL 配置(补充)

生产环境中 HTTPS 已经是标配。Nginx 配置 HTTPS 需要 SSL 证书,可以通过 Let’s Encrypt 免费获取或购买商业证书。

server {
    listen 443 ssl;
    server_name www.dailyblue.com;

    # SSL 证书配置
    ssl_certificate     /etc/nginx/ssl/server.crt;     # 证书文件
    ssl_certificate_key /etc/nginx/ssl/server.key;     # 私钥文件
    ssl_protocols       TLSv1.2 TLSv1.3;               # 使用的 TLS 协议
    ssl_ciphers         HIGH:!aNULL:!MD5;              # 加密套件
    ssl_session_cache   shared:SSL:1m;                 # 会话缓存
    ssl_session_timeout 10m;                           # 会话超时时间

    location / {
        proxy_pass http://localhost:8080;
    }
}

# HTTP 自动跳转 HTTPS
server {
    listen 80;
    server_name www.dailyblue.com;
    rewrite ^(.*)$ https://$host$1 permanent;  # 301 永久重定向
}

十一、性能优化配置(补充)

11.1 核心参数优化

# main 块
worker_processes auto;           # 自动匹配 CPU 核心数
worker_rlimit_nofile 65535;      # worker 进程最大打开文件数

# events 块
events {
    use epoll;                   # 使用 epoll 事件模型(Linux 最优)
    worker_connections 10240;    # 每个 worker 最大连接数
    multi_accept on;             # 允许同时接受多个连接
}

# http 块
http {
    sendfile on;                 # 开启零拷贝,提升文件传输效率
    tcp_nopush on;               # 数据包累积到一定大小再发送
    tcp_nodelay on;              # 小数据包立即发送
    keepalive_timeout 65;        # 长连接超时时间(秒)
    keepalive_requests 1000;     # 长连接最大请求数
    client_max_body_size 20m;    # 客户端请求体最大大小(影响文件上传)
    client_body_buffer_size 128k;# 请求体缓冲区大小

    # Gzip 压缩:减小传输体积,提升页面加载速度
    gzip on;
    gzip_min_length 1k;          # 大于 1K 才压缩
    gzip_comp_level 4;           # 压缩级别(1-9,越大压缩越好但耗 CPU)
    gzip_types text/plain text/css application/json
               application/javascript text/xml application/xml;
    gzip_vary on;                # 添加 Vary: Accept-Encoding 头
}

11.2 Gzip 压缩效果对比

资源类型 压缩前 压缩后 压缩率
HTML 100KB 20KB 80%
CSS 80KB 15KB 81%
JS 150KB 45KB 70%
JSON 50KB 8KB 84%

十二、缓存配置(补充)

Nginx 可以作为缓存服务器,缓存后端服务器的响应,减少后端压力,提升响应速度。

# http 块中定义缓存路径
http {
    # 定义缓存区
    proxy_cache_path /data/nginx/cache levels=1:2
        keys_zone=my_cache:10m        # 缓存区名称和大小
        max_size=10g                   # 缓存最大大小
        inactive=60m                   # 缓存未被访问的过期时间
        use_temp_path=off;

    server {
        listen 80;

        location / {
            proxy_cache my_cache;           # 启用缓存
            proxy_cache_key "$scheme$request_method$host$request_uri";
            proxy_cache_valid 200 304 10m;  # 200/304 响应缓存 10 分钟
            proxy_cache_valid 404 1m;       # 404 响应缓存 1 分钟
            proxy_cache_valid any 5m;       # 其他响应缓存 5 分钟

            # 添加响应头显示是否命中缓存
            add_header X-Cache-Status $upstream_cache_status;

            proxy_pass http://localhost:8080;
        }
    }
}

$upstream_cache_status 的值:

含义
HIT 命中缓存,直接从 Nginx 缓存返回
MISS 未命中缓存,请求转发到后端
EXPIRED 缓存已过期,请求转发到后端
STALE 后端不可用时,返回旧缓存
UPDATING 正在更新缓存,返回旧内容

十三、rewrite 规则(补充)

rewrite 是 Nginx 的 URL 重写功能,常用于伪静态化、域名跳转、旧 URL 兼容等场景。

server {
    listen 80;
    server_name www.dailyblue.com;

    # 1. 域名重定向
    if ($host != 'www.dailyblue.com') {
        rewrite ^/(.*)$ http://www.dailyblue.com/$1 permanent;
    }

    # 2. 伪静态化:/article/123.html → /article.php?id=123
    location / {
        rewrite ^/article/(\d+)\.html$ /article.php?id=$1 last;
    }

    # 3. HTTP 跳转 HTTPS
    rewrite ^(.*)$ https://$host$1 permanent;

    # 4. 根据浏览器语言跳转
    if ($http_accept_language ~* "^zh") {
        rewrite ^/$ /zh/ redirect;
    }
    if ($http_accept_language ~* "^en") {
        rewrite ^/$ /en/ redirect;
    }
}
flag 标志 说明
last 重写后重新发起 location 匹配(最常用)
break 重写后不再执行后续 rewrite,继续执行当前 location
redirect 返回 302 临时重定向
permanent 返回 301 永久重定向

十四、健康检查(补充)

在负载均衡场景中,Nginx 需要检测后端服务器的健康状态,自动剔除不可用的服务器。

14.1 被动健康检查(Nginx 原生)

通过 max_failsfail_timeout 参数实现被动检查:

upstream backend {
    server 192.168.1.10:8080 max_fails=3 fail_timeout=30s;
    server 192.168.1.11:8080 max_fails=3 fail_timeout=30s;
    server 192.168.1.12:8080 max_fails=3 fail_timeout=30s;
}
# 含义:30秒内失败 3 次,则认为该服务器不可用,30秒后重试

14.2 主动健康检查(nginx_upstream_check_module)

第三方模块,支持主动探测后端服务器健康状态:

upstream backend {
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;

    # 主动健康检查
    check interval=3000 rise=2 fall=3 timeout=3000 type=http;
    # interval=3000  每 3 秒检查一次
    # rise=2         连续成功 2 次标记为可用
    # fall=3         连续失败 3 次标记为不可用
    # type=http      检查方式为 HTTP
    check_http_send "HEAD /health HTTP/1.0\r\n\r\n";
    check_http_expect_alive http_2xx http_3xx;
}

十五、日志管理(补充)

Nginx 提供了两种日志:访问日志(access_log)和错误日志(error_log)。

# http 块中定义日志格式
http {
    # 自定义日志格式
    log_format main '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent" '
                    '$upstream_response_time';  # 后端响应时间

    access_log /var/log/nginx/access.log main;
    error_log  /var/log/nginx/error.log warn;  # warn 级别以上记录

    server {
        # 单独为某个 server 配置日志
        access_log /var/log/nginx/www.dailyblue.com.access.log main;

        # 图片等静态资源不记录访问日志
        location ~* \.(jpg|png|gif|css|js)$ {
            access_log off;
        }
    }
}
日志变量 说明
$remote_addr 客户端 IP
$remote_user 客户端用户名
$time_local 访问时间和时区
$request 请求的 URL 和 HTTP 协议
$status HTTP 状态码
$body_bytes_sent 响应体大小(不含头部)
$http_referer 来源页面的 URL
$http_user_agent 客户端浏览器信息
$upstream_response_time 后端服务器响应时间

十六、安全相关配置(补充)

16.1 限流

http {
    # 定义限流区域:按 IP 限流,每秒 10 个请求
    limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
    # 定义连接数限制:按 IP 限制,每个 IP 最多 100 个并发连接
    limit_conn_zone $binary_remote_addr zone=conn_limit:10m;

    server {
        # 应用请求限流:突发请求最多 20 个,不延迟
        location /api/ {
            limit_req zone=mylimit burst=20 nodelay;
            proxy_pass http://backend;
        }

        # 应用并发连接限流
        location / {
            limit_conn conn_limit 100;
            proxy_pass http://backend;
        }
    }
}

16.2 其他安全配置

server {
    # 隐藏 Nginx 版本号,防止暴露已知漏洞
    server_tokens off;

    # 防止图片盗链
    location ~* \.(jpg|png|gif|jpeg|flv|mp3|mp4)$ {
        valid_referers none blocked www.dailyblue.com dailyblue.com;
        if ($invalid_referer) {
            return 403;  # 盗链返回 403
        }
    }

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

    # 禁止访问备份/配置文件
    location ~* \.(bak|sql|ini|sh|conf|swp)$ {
        deny all;
    }

    # IP 黑白名单
    location /admin/ {
        allow 192.168.1.0/24;  # 允许内网访问
        deny all;              # 拒绝其他所有
        proxy_pass http://backend;
    }
}

十七、WebSocket 代理(补充)

现代 Web 应用中 WebSocket 被广泛使用。Nginx 代理 WebSocket 需要额外配置 Upgrade 和 Connection 头。

server {
    listen 80;
    server_name www.dailyblue.com;

    location /ws/ {
        proxy_pass http://localhost:8080;

        # WebSocket 必须配置以下三行
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        # 传递客户端信息
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        # WebSocket 连接超时设置(比普通请求长)
        proxy_read_timeout 3600s;   # 读超时 1 小时
        proxy_send_timeout 3600s;   # 写超时 1 小时
    }
}

十八、Nginx 高可用(补充)

单台 Nginx 存在单点故障风险,生产环境中通常使用 Keepalived + Nginx 实现高可用。

┌─────────────────────────────────────────┐
│              Virtual IP (VIP)            │
│            192.168.1.100                 │
│         (Keepalived 漂移 IP)              │
└────────────┬────────────────────────────┘
             │
     ┌───────▼────────┐         ┌────────────────┐
     │  Nginx Master  │         │  Nginx Backup  │
     │  + Keepalived  │         │  + Keepalived  │
     │  (MASTER 状态)  │         │  (BACKUP 状态)  │
     │  192.168.1.101 │         │  192.168.1.102 │
     └────────────────┘         └────────────────┘
             │                          │
     ┌───────▼──────────────────────────▼───────┐
     │           后端服务器集群                  │
     │    ┌─────────┐ ┌─────────┐ ┌─────────┐  │
     │    │  Tomcat  │ │  Tomcat  │ │  Tomcat  │  │
     │    │   8001   │ │   8002   │ │   8003   │  │
     │    └─────────┘ └─────────┘ └─────────┘  │
     └──────────────────────────────────────────┘

Keepalived 配置(Master 节点):

# /etc/keepalived/keepalived.conf
vrrp_script chk_nginx {
    script "/etc/keepalived/check_nginx.sh"  # 检查 Nginx 是否存活
    interval 2                                # 每 2 秒检查一次
    weight -20                                # 失败则权重减 20
}

vrrp_instance VI_1 {
    state MASTER              # 主节点
    interface eth0            # 绑定的网卡
    virtual_router_id 51      # 虚拟路由 ID
    priority 100              # 优先级(数字越大越优先)
    advert_int 1              # 心跳间隔

    authentication {
        auth_type PASS
        auth_pass 123456
    }

    virtual_ipaddress {
        192.168.1.100         # 虚拟 IP(VIP)
    }

    track_script {
        chk_nginx             # 关联健康检查脚本
    }
}

当 Master 节点的 Nginx 宕机时,Keepalived 检测到后会自动将 VIP 漂移到 Backup 节点,实现无缝切换。

十九、平滑升级(补充)

生产环境中升级 Nginx 版本时,需要做到不中断服务,这称之为”平滑升级”。

# 1. 下载新版本 Nginx
wget http://nginx.org/download/nginx-1.25.0.tar.gz
tar -zxvf nginx-1.25.0.tar.gz
cd nginx-1.25.0

# 2. 使用旧版本的配置参数进行编译(不加 make install)
./configure --prefix=/opt/soft/nginx/
make

# 3. 备份旧的 nginx 二进制文件
cp /opt/soft/nginx/sbin/nginx /opt/soft/nginx/sbin/nginx.old

# 4. 用新的二进制文件覆盖旧的
cp objs/nginx /opt/soft/nginx/sbin/nginx

# 5. 发送 USR2 信号:启动新的 master 进程
kill -USR2 $(cat /opt/soft/nginx/logs/nginx.pid)

# 6. 发送 WINCH 信号:优雅关闭旧的 worker 进程
kill -WINCH $(cat /opt/soft/nginx/logs/nginx.pid.oldbin)

# 7. 确认新版本正常后,发送 QUIT 信号关闭旧 master
kill -QUIT $(cat /opt/soft/nginx/logs/nginx.pid.oldbin)

# 8. 验证版本
nginx -V

整个过程零停机,旧的 worker 会处理完已接收的请求后退出,新请求由新的 worker 处理。

总结

Nginx 是一款轻量级、高性能的 Web 服务器和反向代理服务器,其核心优势在于:

  • 高并发:基于事件驱动的异步非阻塞架构,单机可支撑数万并发连接
  • 低消耗:内存占用少,CPU 利用率高
  • 多功能:静态资源服务、反向代理、负载均衡、缓存、HTTPS 等一站式能力
  • 高可靠:master-worker 架构保证稳定性,配合 Keepalived 可实现高可用
  • 热部署:支持不停机平滑升级和配置重载

在实际生产环境中,Nginx 通常作为最前层的入口网关,承担静态资源服务、反向代理、负载均衡、HTTPS 卸载、安全防护等多重角色,是现代 Web 架构中不可或缺的组件。

By admin

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注