Nginx (发音为 “engine-x”) 是一个高性能的 HTTP 和反向代理服务器,也可以用作 邮件代理服务器 和通用的 TCP/UDP 代理服务器。它最初由 Igor Sysoev 为俄罗斯最大的门户网站和搜索引擎 Rambler 开发,并于 2004 年公开发布。Nginx 因其卓越的性能、稳定性、丰富的功能集和低资源消耗而广受欢迎,是构建现代高并发 Web 应用程序和微服务架构不可或缺的组件。

核心思想:Nginx 采用事件驱动 (event-driven)、异步非阻塞 (asynchronous, non-blocking) 架构,使其在处理大量并发连接时表现出色,远超传统的基于进程/线程模型的服务器。


一、为什么选择 Nginx? (优势)

Nginx 之所以成为众多高流量网站和云服务提供商的首选,主要得益于以下优势:

  1. 高性能高并发
    • 事件驱动架构:Nginx 的核心是其事件驱动的异步非阻塞架构。这意味着单个工作进程可以处理数千个并发连接,而无需为每个连接创建单独的进程或线程。这大大减少了上下文切换的开销和内存消耗。
    • 低内存消耗:相较于 Apache 等基于进程/线程模型的服务器,Nginx 在高并发下占用更少的内存。
  2. 稳定性与可靠性
    • 其设计使得在极端负载下也能保持稳定运行,很少崩溃。
  3. 功能丰富
    • 除了作为高效的静态文件服务器,Nginx 还提供了强大的反向代理、负载均衡、缓存、SSL/TLS 终止、HTTP/2 支持、流媒体服务、限流等功能。
  4. 模块化设计
    • Nginx 的核心功能通过模块实现,这使得其易于扩展和定制。
  5. 易于扩展
    • 可以通过配置实现高度灵活的路由规则和请求处理逻辑。
  6. 活跃的社区支持
    • 拥有庞大而活跃的社区,提供丰富的文档、插件和支持。

二、Nginx 的核心功能与概念

2.1 Web 服务器 (Serving Static Files)

Nginx 可以作为高效的静态文件服务器,直接提供 HTML、CSS、JavaScript 文件、图片等。由于其异步架构,Nginx 在处理静态文件请求方面性能卓越,特别适合作为 CDN 的边缘节点。

2.2 反向代理 (Reverse Proxy)

定义:反向代理服务器接收来自客户端的请求,然后将这些请求转发给后端的一个或多个服务器,并将后端服务器的响应返回给客户端。客户端并不知道它连接的是一个代理服务器。

作用

  • 隐藏后端服务器:客户端只看到 Nginx 的 IP 地址,提高了安全性。
  • 负载均衡:可以将请求分发到多个后端服务器。
  • SSL/TLS 终止:Nginx 可以处理 HTTPS 加密解密,将未加密的请求转发给后端服务器,减轻后端负担。
  • 缓存:Nginx 可以缓存后端服务器的响应,减少对后端服务的压力。
  • 请求过滤与限流:在请求到达后端服务之前进行处理。

2.3 负载均衡 (Load Balancer)

定义:当有多个后端服务器时,Nginx 可以作为负载均衡器,将客户端请求分发到这些服务器上,以平衡服务器负载、提高系统的可用性和可伸缩性。

负载均衡算法

  • Round Robin (轮询):默认算法。按顺序将请求分发给每个服务器。
  • Least Connections (最少连接):将请求发送给当前活动连接数最少的服务器。
  • IP Hash (IP 哈希):根据客户端 IP 地址的哈希值来分发请求,确保同一客户端的请求总是发送到同一台服务器,适用于会话保持。
  • Weighted Round Robin (加权轮询):为不同的服务器设置权重,权重越高,分配到的请求越多。
  • Generic Hash (通用哈希):根据用户自定义的键(如 URL、请求头等)的哈希值来分发。

2.4 代理缓存 (Proxy Cache)

Nginx 可以缓存反向代理的响应,将来自后端服务器的响应存储在本地磁盘上。当相同的请求再次到来时,Nginx 可以直接从缓存中提供响应,而无需再次访问后端服务器,大大提高了响应速度并减轻了后端服务的压力。

2.5 SSL/TLS 终止 (SSL/TLS Termination)

Nginx 可以在接收到客户端的 HTTPS 请求时,负责解密 SSL/TLS 连接。这样,后端服务可以只处理 HTTP 请求,简化了后端配置,并减轻了其加密解密的计算负担。

三、Nginx 的架构

Nginx 采用主进程 (Master Process) 和工作进程 (Worker Processes) 的架构模型:

  • Master Process (主进程)
    • 负责读取和验证配置文件。
    • 管理工作进程,如启动、停止、平滑升级 Nginx。
    • 监控工作进程的状态。
  • Worker Processes (工作进程)
    • 实际处理客户端请求的进程。
    • 每个工作进程都是单线程的,但通过高效的事件循环 (Event Loop) 机制,可以并发处理数千个连接。
    • Nginx 建议将工作进程数设置为 CPU 的核心数,以最大限度地利用 CPU 资源。

四、Nginx 安装 (以 Ubuntu 为例)

通过包管理器安装是推荐的方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 更新包列表
sudo apt update

# 安装 Nginx
sudo apt install nginx

# 启动 Nginx
sudo systemctl start nginx

# 设置开机自启动
sudo systemctl enable nginx

# 检查 Nginx 状态
sudo systemctl status nginx

安装完成后,在浏览器中访问服务器的 IP 地址,如果看到 “Welcome to nginx!” 页面,则表示安装成功。

五、Nginx 配置详解 (nginx.conf)

Nginx 的所有功能都通过配置文件来定义,通常位于 /etc/nginx/nginx.conf/etc/nginx/conf.d/*.conf。配置文件由指令 (directives) 和上下文 (contexts) 组成。

5.1 配置上下文 (Contexts)

指令根据其作用范围被放置在不同的上下文中:

  • main (全局上下文):最高层级,影响整个 Nginx 服务器的运行,如 user, worker_processes, error_log, pid
  • events (事件模型上下文):配置 Nginx 工作进程如何处理连接,如 worker_connections, use
  • http (HTTP 协议上下文):配置所有 HTTP 服务器的通用行为,如 include mime.types, sendfile, gzip
  • server (虚拟主机上下文):定义一个虚拟主机,监听特定端口和域名,通常包含在 http 块中。一个 http 块可以有多个 server 块。
  • location (URI 匹配上下文):在 server 块内部,根据请求 URI 匹配并定义特定的请求处理规则。一个 server 块可以有多个 location 块。
  • upstream (上游服务器上下文):定义一组后端服务器,用于负载均衡和反向代理。通常包含在 http 块中。

5.2 常用指令示例

全局配置 (main context)

1
2
3
4
user nginx;               # Nginx 工作进程运行的用户和组
worker_processes auto; # 工作进程数量,auto 表示根据 CPU 核心数自动设置
error_log /var/log/nginx/error.log warn; # 错误日志路径和级别
pid /var/run/nginx.pid; # Nginx 主进程的 PID 文件路径

事件配置 (events context)

1
2
3
4
events {
worker_connections 1024; # 每个工作进程的最大连接数
# use epoll; # 指定事件处理模型,Linux 默认为 epoll
}

HTTP 配置 (http context)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
http {
include /etc/nginx/mime.types; # 包含 MIME 类型映射表
default_type application/octet-stream; # 默认 MIME 类型

sendfile on; # 启用高效文件传输模式
tcp_nopush on; # 在 sendfile 启用时,将头部和数据一起发送
tcp_nodelay on; # 实时传输数据

keepalive_timeout 65; # 长连接超时时间,65秒
types_hash_max_size 2048;

gzip on; # 启用 Gzip 压缩,减少传输数据量
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

# 包含其他虚拟主机配置文件 (推荐按功能或域名拆分)
include /etc/nginx/conf.d/*.conf;
}

5.3 server 块 (虚拟主机)

一个 server 块定义了一个虚拟主机,监听特定的 IP 地址和端口,并根据 server_name 匹配请求域名。

1
2
3
4
5
6
7
8
9
server {
listen 80; # 监听 80 端口(HTTP)
server_name example.com www.example.com; # 匹配的域名

root /var/www/html; # 网站根目录
index index.html index.htm; # 默认索引文件

# ... location 块定义
}

5.4 location 块 (URI 匹配)

location 块用于根据请求的 URI 路径定义不同的处理规则。Nginx 会按照优先级顺序查找匹配的 location 块。

匹配规则优先级 (从高到低)

  1. = (精确匹配)location = / 只匹配 /
  2. ^~ (前缀匹配,优先于正则表达式)location ^~ /images/ 会匹配所有以 /images/ 开头的 URI,并且如果匹配成功,Nginx 将停止搜索其他正则表达式匹配。
  3. ~~* (正则表达式匹配)
    • ~:区分大小写。location ~ \.php$ 匹配所有以 .php 结尾的 URI。
    • ~*:不区分大小写。location ~* \.(jpg|jpeg|gif)$ 匹配所有以 .jpg, .jpeg, .gif 结尾的 URI。
  4. 无修饰符 (普通前缀匹配)location /location /docs/。匹配以指定字符串开头的 URI,选择最长匹配项。
  5. / (通用匹配,默认处理)location / 匹配所有请求,作为最终的备用处理。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
server {
listen 80;
server_name myapp.com;

root /var/www/myapp/public; # 静态文件根目录

# 匹配精确的根路径
location = / {
index index.html;
}

# 匹配所有以 /api/ 开头的请求,并反向代理到后端服务
location /api/ {
proxy_pass http://localhost:8080; # 转发到本地 8080 端口的后端服务
proxy_set_header Host $host; # 传递原始 Host 头
proxy_set_header X-Real-IP $remote_addr; # 传递客户端真实 IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 传递代理链中的 IP
proxy_set_header X-Forwarded-Proto $scheme; # 传递原始请求协议 (http/https)
}

# 匹配图片文件,并设置缓存
location ~* \.(jpg|jpeg|gif|png|ico|css|js)$ {
expires 30d; # 缓存 30 天
add_header Cache-Control "public";
}

# SPA 单页面应用路由回退:对于所有不匹配的文件,返回 index.html
location / {
# 尝试查找文件或目录,如果找不到,则返回 /index.html
try_files $uri $uri/ /index.html;
}
}

5.5 upstream 块 (负载均衡池)

upstream 块定义一个后端服务器池,供 proxy_pass 指令引用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
upstream backend_servers {
# 负载均衡算法默认为 round robin
server 192.168.1.100:8080 weight=5; # 权重为 5
server 192.168.1.101:8080;
server 192.168.1.102:8080 backup; # 备份服务器,当所有主服务器都失效时才使用
# least_conn; # 启用最少连接算法
# ip_hash; # 启用 IP 哈希算法
}

server {
listen 80;
server_name myapp.com;

location / {
proxy_pass http://backend_servers; # 请求转发给 upstream 定义的服务器组
# ... proxy headers
}
}

六、常用配置场景示例

6.1 静态文件服务器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
server {
listen 80;
server_name static.example.com;

root /usr/share/nginx/html/static;
index index.html;

location / {
try_files $uri $uri/ =404; # 尝试查找文件或目录,否则返回 404
}

location ~* \.(css|js|gif|jpg|jpeg|png)$ {
expires 30d; # 缓存 30 天
add_header Cache-Control "public";
}
}

6.2 反向代理到后端应用 (HTTP)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
server {
listen 80;
server_name api.example.com;

location / {
proxy_pass http://127.0.0.1:3000; # 代理到本地 3000 端口的 Node.js/Go 应用
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_set_header X-Forwarded-Proto $scheme;
# 允许 websocket 连接
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}

6.3 HTTPS 配置 (SSL/TLS Termination)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 强制 HTTP 重定向到 HTTPS
server {
listen 80;
server_name secure.example.com;
return 301 https://$host$request_uri; # 301 永久重定向
}

server {
listen 443 ssl http2; # 监听 443 端口,启用 SSL/TLS 和 HTTP/2
server_name secure.example.com;

ssl_certificate /etc/nginx/ssl/secure.example.com.crt; # SSL 证书路径
ssl_certificate_key /etc/nginx/ssl/secure.example.com.key; # SSL 私钥路径
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
ssl_protocols TLSv1.2 TLSv1.3; # 推荐只使用 TLSv1.2 和 TLSv1.3
ssl_prefer_server_ciphers on;

location / {
proxy_pass http://127.0.0.1:3000; # 转发到后端 HTTP 服务
# ... proxy headers
}
}

七、Nginx 的管理命令

1
2
3
4
5
6
7
8
sudo nginx -t             # 检查 Nginx 配置文件语法,很有用!
sudo nginx -s reload # 重新加载配置,平滑重启 (不中断连接)
sudo nginx -s stop # 快速停止 Nginx
sudo nginx -s quit # 优雅地停止 Nginx (等待当前请求处理完毕)
sudo systemctl start nginx # 启动 Nginx
sudo systemctl stop nginx # 停止 Nginx
sudo systemctl restart nginx # 重启 Nginx
sudo systemctl status nginx # 查看 Nginx 运行状态

八、总结

Nginx 是一个强大而灵活的工具,它不仅可以作为高性能的 Web 服务器,更因其出色的反向代理和负载均衡能力,成为现代 Web 架构中不可或缺的组成部分。理解 Nginx 的事件驱动架构、核心功能和配置方式,对于构建高可用、高性能的 Web 服务至关重要。通过合理配置,Nginx 能够显著提升应用的性能、安全性和可伸缩性。