Nginx 是一款高性能的 HTTP 和反向代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器,以高并发、低内存占用、稳定性强著称。
一、基础概念与核心原理
1. 什么是 Nginx?它有哪些特点?
定义 :Nginx 是由 Igor Sysoev 开发的开源轻量级 Web 服务器、反向代理服务器和电子邮件代理服务器,采用事件驱动的异步非阻塞架构。
核心特点:
- 高并发:单台服务器可支持数万甚至数十万并发连接(默认配置下约 1-2 万,调优后可达 10 万 +)
- 低内存:1 万并发连接仅占用约 2.5MB 内存
- 高可用:支持热部署,7×24 小时不间断运行
- 模块化:丰富的第三方模块生态
- 反向代理与负载均衡:内置多种负载均衡策略
- 静态资源处理:高效处理静态文件,比 Apache 快 10 倍以上
2. Nginx 和 Apache 的区别?
| 特性 | Nginx | Apache |
|---|---|---|
| 架构 | 异步非阻塞,事件驱动 | 同步阻塞,多进程 / 多线程 |
| 并发 | 高并发,支持数万连接 | 低并发,默认约 1000 连接 |
| 内存占用 | 极低 | 较高 |
| 静态资源 | 极强 | 一般 |
| 动态请求 | 需转发给后端处理 | 原生支持 PHP 等 |
| 模块 | 核心模块 + 第三方模块,编译时加载 | 模块丰富,支持动态加载 |
| 配置 | 简洁灵活 | 复杂繁琐 |
| 适用场景 | 静态服务、反向代理、负载均衡 | 动态服务、传统 Web 应用 |
3. Nginx 的工作原理?(核心中的核心)
Nginx 采用多进程 + 异步非阻塞事件模型(epoll/kqueue)。
进程模型
- Master 进程:管理进程,负责读取配置、启动 / 停止 Worker 进程、监控 Worker 状态、热部署
- Worker 进程 :工作进程,实际处理网络请求,数量通常设置为 CPU 核心数(
worker_processes auto) - Cache 进程:可选,包括 Cache Manager 和 Cache Loader,负责缓存管理
请求处理流程
- 客户端发送请求到 Nginx 的 80/443 端口
- Master 进程接收请求,将其分配给空闲的 Worker 进程
- Worker 进程通过 epoll 模型监听事件,非阻塞地处理请求
- 如果是静态资源,直接返回给客户端
- 如果是动态请求,通过反向代理转发给后端服务器(如 Tomcat、PHP-FPM)
- 后端服务器处理完成后,将结果返回给 Nginx
- Nginx 将结果返回给客户端
4. 什么是异步非阻塞?Nginx 如何实现?
- 同步阻塞:进程发起请求后,必须等待请求完成才能继续执行,期间 CPU 空闲
- 异步非阻塞:进程发起请求后,立即返回继续执行其他任务,当请求完成时,通过事件通知进程处理结果
Nginx 使用epoll (Linux)或kqueue(FreeBSD)实现异步非阻塞:
- epoll 是 Linux 内核提供的 I/O 多路复用技术
- 它将所有需要监听的文件描述符注册到 epoll 实例中
- 当某个文件描述符有事件发生时,epoll 会通知对应的 Worker 进程
- Worker 进程只处理有事件的连接,避免了轮询所有连接的开销
5. Nginx 如何处理高并发?
- 多进程模型:充分利用多核 CPU,每个 Worker 进程独立运行,互不影响
- 异步非阻塞 I/O:一个 Worker 进程可以同时处理数千个连接
- 事件驱动:只处理有事件的连接,避免了空闲连接的资源浪费
- 内存池:预分配内存,减少内存碎片和分配开销
- 连接池:复用 TCP 连接,减少三次握手和四次挥手的开销
- 静态资源缓存:将静态资源缓存在内存中,直接返回给客户端
二、常用配置详解
1. Nginx 配置文件结构
Nginx 配置文件默认位于 /etc/nginx/nginx.conf,由指令 和指令块组成,指令以分号结尾,指令块用大括号包裹。
javascript
# 全局块:配置影响Nginx全局的指令
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
# events块:配置影响Nginx服务器与用户网络连接的指令
events {
worker_connections 1024; # 每个Worker进程的最大连接数
use epoll; # 使用epoll事件模型
multi_accept on; # 允许同时接受多个新连接
}
# http块:配置HTTP服务器的主要参数
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# 日志格式
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 /var/log/nginx/access.log main;
sendfile on; # 开启高效文件传输模式
tcp_nopush on; # 防止网络阻塞
tcp_nodelay on; # 防止网络阻塞
keepalive_timeout 65; # 长连接超时时间
gzip on; # 开启gzip压缩
# server块:配置虚拟主机
server {
listen 80; # 监听端口
server_name example.com; # 域名
root /usr/share/nginx/html; # 网站根目录
index index.html index.htm; # 默认首页
# location块:配置请求路由
location / {
try_files $uri $uri/ /index.html;
}
location /api/ {
proxy_pass http://backend; # 反向代理到后端服务器
}
}
# upstream块:配置负载均衡服务器组
upstream backend {
server 192.168.1.10:8080;
server 192.168.1.11:8080;
}
}
2. 常用配置指令详解
全局块
user nginx:指定 Nginx 运行的用户和组worker_processes auto:Worker 进程数,建议设置为 CPU 核心数error_log /var/log/nginx/error.log warn:错误日志路径和级别pid /run/nginx.pid:PID 文件路径
events 块
worker_connections 1024:每个 Worker 进程的最大连接数,总连接数 = worker_processes×worker_connectionsuse epoll:指定使用 epoll 事件模型(Linux 默认)multi_accept on:允许 Worker 进程同时接受多个新连接
http 块
sendfile on:开启 sendfile 系统调用,直接在内核中传输文件,避免用户态和内核态之间的拷贝tcp_nopush on:当 sendfile 开启时,将多个小数据包合并成一个大数据包发送,提高网络效率tcp_nodelay on:禁用 Nagle 算法,允许小数据包立即发送,适用于实时性要求高的场景keepalive_timeout 65:长连接超时时间,单位秒gzip on:开启 gzip 压缩,减少传输带宽gzip_types text/plain text/css application/json application/javascript:指定需要压缩的文件类型
server 块
listen 80:监听端口server_name example.com www.example.com:指定域名,支持多个域名和通配符root /usr/share/nginx/html:网站根目录index index.html index.htm:默认首页error_page 404 /404.html:自定义 404 页面error_page 500 502 503 504 /50x.html:自定义 5xx 错误页面
location 块
location 用于匹配请求 URI,语法:location [=|~|~*|^~] /uri/ { ... }
| 修饰符 | 含义 | 匹配优先级 |
|---|---|---|
| = | 精确匹配 | 最高 |
| ^~ | 前缀匹配,匹配成功后不再进行正则匹配 | 次高 |
| ~ | 正则匹配,区分大小写 | 中 |
| ~* | 正则匹配,不区分大小写 | 中 |
| 无修饰符 | 前缀匹配 | 最低 |
javascript
location = / {
# 精确匹配根目录
}
location ^~ /static/ {
# 匹配所有以/static/开头的请求,不再进行正则匹配
root /usr/share/nginx;
}
location ~* \.(jpg|jpeg|png|gif|css|js)$ {
# 匹配所有图片和静态文件,不区分大小写
expires 30d; # 设置缓存时间为30天
}
location / {
# 匹配所有其他请求
}
- 反向代理配置 反向代理是 Nginx 最常用的功能之一,用于将客户端请求转发给后端服务器。
java
location /api/ {
proxy_pass http://127.0.0.1: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_connect_timeout 60s; # 连接后端超时时间
proxy_read_timeout 60s; # 读取后端响应超时时间
proxy_send_timeout 60s; # 发送请求到后端超时时间
}
4. 负载均衡配置
Nginx 内置多种负载均衡策略,通过 upstream 块配置。
轮询(默认)
请求按顺序依次分配给后端服务器。
java
upstream backend {
server 192.168.1.10:8080;
server 192.168.1.11:8080;
}
加权轮询
权重越高的服务器,分配到的请求越多。
javascript
upstream backend {
server 192.168.1.10:8080 weight=3;
server 192.168.1.11:8080 weight=1;
}
IP 哈希
根据客户端 IP 的哈希值分配服务器,保证同一个客户端的请求始终分配到同一个服务器,解决 session 问题。
javascript
upstream backend {
ip_hash;
server 192.168.1.10:8080;
server 192.168.1.11:8080;
}
最少连接
请求分配给当前连接数最少的服务器。
javascript
upstream backend {
least_conn;
server 192.168.1.10:8080;
server 192.168.1.11:8080;
}
健康检查
Nginx 内置被动健康检查,当后端服务器出现错误时,自动将其从负载均衡池中移除。
javascript
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;
}
max_fails=3:允许失败的次数fail_timeout=30s:失败后,服务器被暂停服务的时间
5. HTTPS 配置
HTTPS 基于 SSL/TLS 协议,用于加密 HTTP 通信,保证数据传输安全。
javascript
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/nginx/ssl/example.com.crt; # 证书文件
ssl_certificate_key /etc/nginx/ssl/example.com.key; # 私钥文件
ssl_protocols TLSv1.2 TLSv1.3; # 支持的SSL/TLS版本
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; # 加密套件
ssl_prefer_server_ciphers on; # 优先使用服务器端的加密套件
ssl_session_cache shared:SSL:10m; # SSL会话缓存
ssl_session_timeout 10m; # SSL会话超时时间
location / {
root /usr/share/nginx/html;
index index.html;
}
}
# HTTP重定向到HTTPS
server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}
三、应用场景
- 静态资源服务器:高效处理 HTML、CSS、JS、图片等静态文件
- 反向代理服务器:隐藏后端服务器,提高安全性和性能
- 负载均衡器:将请求分发到多个后端服务器,提高系统可用性和并发能力
- API 网关:统一入口,实现路由、限流、鉴权、日志等功能
- 缓存服务器:缓存静态资源和动态页面,减少后端服务器压力
- SSL 终端:统一处理 HTTPS 加密和解密,减轻后端服务器负担
- 动静分离:静态资源由 Nginx 处理,动态请求转发给后端服务器
四、安全防护
1. 隐藏 Nginx 版本号
javascript
http {
server_tokens off; # 隐藏响应头中的Server版本号
}
2. 禁止非法请求方法
javascript
location / {
if ($request_method !~ ^(GET|HEAD|POST)$) {
return 405;
}
}
3. 防止 SQL 注入
javascript
location / {
if ($args ~* "union.*select.*\(") {
return 403;
}
if ($args ~* "concat.*\(") {
return 403;
}
}
4. 防止目录遍历
javascript
location / {
if ($uri ~* "\.\.") {
return 403;
}
}
5. 限制 IP 访问
javascript
location /admin/ {
allow 192.168.1.0/24;
deny all;
}
6. 配置 WAF(Web 应用防火墙)
使用第三方模块如 ModSecurity,实现更强大的安全防护。
7. 配置 HTTPS
强制使用 HTTPS,禁用不安全的 SSL/TLS 版本和加密套件。
五、性能调优
1. 进程调优
javascript
worker_processes auto; # 设置为CPU核心数
worker_cpu_affinity auto; # 将Worker进程绑定到不同的CPU核心
worker_rlimit_nofile 65535; # 每个Worker进程的最大文件描述符数
2. 连接调优
javascript
events {
use epoll;
worker_connections 65535; # 每个Worker进程的最大连接数
multi_accept on;
}
http {
keepalive_timeout 65;
keepalive_requests 1000; # 一个长连接最多处理的请求数
tcp_nopush on;
tcp_nodelay on;
}
3. 静态资源调优
javascript
http {
sendfile on;
sendfile_max_chunk 1m; # 每次sendfile传输的最大数据量
location ~* \.(jpg|jpeg|png|gif|css|js|ico)$ {
expires 30d; # 设置缓存时间
add_header Cache-Control "public, max-age=2592000";
add_header ETag ""; # 禁用ETag
}
}
4. 压缩调优
javascript
http {
gzip on;
gzip_vary on;
gzip_comp_level 6; # 压缩级别,1-9,越高压缩率越高,CPU消耗越大
gzip_min_length 1k; # 只压缩大于1k的文件
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
}
5. 缓存调优
javascript
http {
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=cache:10m inactive=60m max_size=1g;
location /api/ {
proxy_pass http://backend;
proxy_cache cache;
proxy_cache_valid 200 304 1h; # 缓存200和304响应1小时
proxy_cache_key $host$uri$is_args$args;
add_header X-Cache $upstream_cache_status; # 显示缓存状态
}
}
6. 系统内核调优
修改 /etc/sysctl.conf 文件:
javascript
net.core.somaxconn = 65535 # 最大待处理连接数
net.ipv4.tcp_syncookies = 1 # 开启SYN Cookies,防止SYN洪水攻击
net.ipv4.tcp_fin_timeout = 30 # TCP连接关闭后的超时时间
net.ipv4.tcp_tw_reuse = 1 # 允许将TIME-WAIT状态的连接重新用于新的TCP连接
net.ipv4.tcp_tw_recycle = 1 # 开启TIME-WAIT状态连接的快速回收
net.ipv4.tcp_max_tw_buckets = 5000 # 系统同时保持TIME-WAIT状态的最大数量
net.ipv4.tcp_max_syn_backlog = 65535 # SYN队列的最大长度
net.core.netdev_max_backlog = 5000 # 网络设备接收数据包的速率比内核处理快时,允许送到队列的数据包的最大数目
执行 sysctl -p 使配置生效。
六、高级特性
1. 热部署
Nginx 支持热部署,无需停止服务即可更新配置和升级版本。
-
重新加载配置:
nginx -s reload -
优雅停止服务:
nginx -s quit -
强制停止服务:
nginx -s stop -
nginx -s reload
- master 重新加载配置
- 启动新 worker
- 新请求交给新 worker
- 旧 worker 处理完已有连接后退出服务不中断。
2. 限流
Nginx 支持基于连接数和请求数的限流。
基于请求数的限流
javascript
http {
limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;
server {
location / {
limit_req zone=req_limit burst=5 nodelay;
}
}
}
rate=10r/s:每秒允许 10 个请求burst=5:允许突发 5 个请求nodelay:突发请求立即处理,不延迟
基于连接数的限流
http {
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
server {
location / {
limit_conn conn_limit 10; # 每个IP最多10个连接
}
}
}
3. 灰度发布
通过 Nginx 实现灰度发布,将部分用户流量引导到新版本。
javascript
upstream old {
server 192.168.1.10:8080;
}
upstream new {
server 192.168.1.11:8080;
}
split_clients "${remote_addr}AAA" $variant {
10% new;
* old;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://$variant;
}
}
4. 防盗链
防止其他网站盗用本站资源。
javascript
location ~* \.(jpg|jpeg|png|gif)$ {
valid_referers none blocked example.com *.example.com;
if ($invalid_referer) {
return 403;
}
}
七、高频面试题汇总
- Nginx 为什么这么快?
- Nginx 和 Apache 的区别?
- Nginx 的工作原理?
- Nginx 如何处理高并发?
- 什么是反向代理?和正向代理有什么区别?
- Nginx 有哪些负载均衡策略?
- location 的匹配规则和优先级?
- 如何配置 HTTPS?
- Nginx 如何实现动静分离?
- Nginx 如何实现限流?
- Nginx 如何实现灰度发布?
- Nginx 如何隐藏版本号?
- Nginx 热部署的原理?
- Nginx 常见的状态码有哪些?分别表示什么?
- 如何排查 Nginx 502 错误?
八、分层网关架构
绝大多数企业架构是:Nginx + SCG 一起用,各司其职
互联网 → 【Nginx(边缘网关)】 → 【SCG(业务网关)】 → 微服务集群
Nginx 做(第一层):
- HTTPS 终结(证书、TLS 优化)
- 公网流量清洗(防刷、黑名单、全局限流)
- 静态资源直接返回(动静分离)
- 四层负载均衡(多机房 / 多集群分发)
- 安全屏障(隐藏内网拓扑)
SCG 做(第二层):
- 微服务智能路由(自动发现、动态配置)
- 业务级鉴权(JWT、权限校验)
- 熔断降级、接口限流、重试
- 请求 / 响应修改、日志、监控
- 灰度发布、A/B 测试
Nginx
- 定位 :边缘流量网关 / 通用 Web 服务器 / 反向代理
- 语言:C 语言开发
- 架构:多进程 + 异步非阻塞 + epoll 事件驱动
- 擅长 :高并发、低延迟、静态资源、SSL 卸载、四层 / 七层负载均衡
- 角色 :公网入口、流量门卫、基础设施
Spring Cloud Gateway
- 定位 :微服务 API 网关 / 业务网关
- 语言:Java(基于 Spring WebFlux + Netty + Reactor)
- 架构:响应式异步非阻塞(Netty 线程模型)
- 擅长 :动态路由、服务发现、熔断限流、认证鉴权、业务过滤、微服务治理
- 角色 :内部流量调度、业务逻辑网关
一句话总结 :Nginx 管流量与性能,SCG 管业务与微服务生态。
1. Nginx 和 Spring Cloud Gateway 核心区别?
- 定位不同 :Nginx 是流量 / 基础设施网关 ,SCG 是业务 / 微服务网关。
- 技术栈:Nginx C 语言(性能极致),SCG Java(生态强、易扩展)。
- 场景 :Nginx 管公网入口、静态、SSL、高并发 ;SCG 管微服务路由、业务逻辑、治理。
2. 为什么微服务还要用 Nginx?
- 性能扛压:Nginx 抗公网高并发,保护内部 SCG。
- SSL 卸载:减轻 SCG 的加密计算压力。
- 静态分离:静态不走 Java 网关,节省资源。
- 安全隔离:隐藏内网服务地址。
3. 什么时候可以只用 SCG 不用 Nginx?
- 内网环境、无 HTTPS、中小流量
- 云原生:用云厂商 LB(SLB/ALB)替代 Nginx
- 测试 / 开发环境简化架构