Nginx 完全指南:从原理到实战,用百度告诉你亿级并发的秘密
前言
打开浏览器,输入 www.baidu.com,回车。
一瞬间——百度首页出现在你眼前。从你按下回车到页面加载完成,整个过程不超过 200 毫秒。
但你有没有想过:这一刻,全世界有多少人也在同时访问百度?
根据公开数据,百度日均搜索请求超过 60 亿次,峰值 QPS(每秒查询数)可达数百万乃至千万级别。这意味着在高峰期,每秒钟有数千万人在和百度打交道。
而在这背后,有一个默默工作的"守门人"——Nginx。
这篇文章,我用百度作为贯穿始终的案例,从一个最简单的访问请求讲起,一层层揭开 Nginx 的架构秘密,告诉你它为什么能扛住几亿人的访问,以及百度这样的巨型网站是如何用 Nginx 构建自己的基础设施的。
一、你访问百度时,到底发生了什么
1.1 一次访问的完整旅程
当你输入 www.baidu.com 并回车时,背后发生了一系列精密的协作:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
用户浏览器
↓ 输入 www.baidu.com
↓
DNS 服务器(把 baidu.com 解析成 IP 地址)
↓ 返回服务器 IP
↓
CDN 边缘节点(检查缓存,百度在全国有数百个边缘节点)
↓ 缓存命中 → 直接返回静态资源
↓ 缓存未命中 → 回源到 Nginx 集群
↓
Nginx 集群(第一道入口,千百台 Nginx 组成集群)
↓ 反向代理 / 负载均衡
↓
上游应用服务器(搜索服务、首页服务、广告服务……)
↓ 处理请求
↓
数据库 / 缓存层(Redis、Memcached)
↓ 查询数据
↓ 原路返回
浏览器渲染页面
|
在这个链路中,Nginx 处于用户请求进入后端之前的"咽喉要塞"位置——所有流量必须经过它。这就是 Nginx 最重要的战略价值。
1.2 先搞懂几个基本概念
在继续深入之前,先弄清楚 Nginx 在整个体系中扮演什么角色:
正向代理 vs 反向代理
1
2
3
4
5
6
7
8
9
|
正向代理(VPN 为代表):
用户 → 代理服务器 → 目标网站
目标网站只知道请求来自代理,不知道真实用户是谁
代理站在用户这边,帮用户"代购"
反向代理(Nginx 为代表):
用户 → 反向代理服务器 → 真实应用服务器集群
用户只知道代理的地址,不知道后面有多少台服务器
代理站在服务器这边,帮服务器"接待客户"
|
为什么需要反向代理?
想象一下百度没有 Nginx 的世界:假设百度搜索首页 baidu.com 部署在 10 台真实服务器上,IP 分别是 10.0.1.1 到 10.0.1.10。用户访问 www.baidu.com 时,DNS 只能返回其中一个 IP——这样,10 台服务器中只有 1 台在工作,其余 9 台都闲着。更糟糕的是,那台服务器一旦宕机,整个服务就挂了。
有了 Nginx 反向代理:
- DNS 对外只暴露 Nginx 的 IP(或者 VIP 虚拟 IP)
- 用户的所有请求先打到 Nginx
- Nginx 根据负载均衡策略,把请求分配到后端的 10 台(甚至 1000 台)服务器上
- 任何一台后端服务器宕机,Nginx 自动把它踢出集群,请求自动分发给健康的机器
这就是 Nginx 作为反向代理的核心价值:统一入口 + 负载均衡 + 高可用。
二、Nginx 为什么这么快 — 事件驱动架构
2.1 同步阻塞模型 vs 事件驱动模型
要理解 Nginx 为什么快,先要理解传统 Web 服务器为什么慢。
传统模型(Apache 默认的 prefork 模式):
1
|
一个请求 → 分配一个进程/线程处理 → 等待 I/O(读文件、查数据库、等网络)→ 返回
|
问题在哪?进程在等待 I/O 的时候什么都不干,但仍然占着内存和 CPU 资源。
假设一台服务器有 1000 个并发请求,每个请求都在等待数据库返回数据。在同步阻塞模型下,这 1000 个请求需要 1000 个进程/线程同时存在,每个进程栈占用 2-8MB 内存,光栈内存就要消耗 2-8GB。
这还没算 CPU 切换的开销——进程/线程数量越多,操作系统调度开销越大,性能急剧下降。
Nginx 的事件驱动模型:
1
|
一个请求 → 注册 I/O 事件 → 处理下一个请求 → I/O 就绪(epoll 通知)→ 回来处理
|
Nginx 用一个进程(或少量进程)就可以处理海量并发连接。关键在于:进程不会傻等 I/O 完成,它注册一个"回调",然后去处理其他事情,等 I/O 真的就绪了,操作系统再通知它回来处理。
2.2 用百度的例子理解 epoll
Linux 内核提供了三种 I/O 多路复用机制:select、poll、epoll。Nginx 在 Linux 上默认使用 epoll,它是性能最强的一种。
用一个生活场景来类比:
select 模式(低效):你去餐厅点餐,服务员站在你桌边等你慢慢吃完,才去问下一桌。这叫"轮询"——不管你有没有在吃饭,每隔一段时间服务员都要来看一眼。
epoll 模式(高效):你点完餐后去干别的事(刷手机),服务员去服务其他桌。等你点的菜做好了,厨师按一下铃,服务员才过来给你上菜。这叫"事件驱动"——只有真正发生事情(菜好了)的时候,才通知你去处理。
1
2
|
select/poll: 遍历所有文件描述符 → O(n),每次调用都要全量扫描
epoll: 把文件描述符注册到内核 → O(1),只通知已就绪的
|
epoll 的核心优势:
- 无需遍历:只返回已就绪的文件描述符,时间复杂度 O(1)
- 无并发限制:不限制监视的文件描述符数量(select 默认 1024)
- 边缘触发/水平触发:灵活控制通知策略
在百度的生产环境中,每台 Nginx 服务器可能维护着数万到数十万个并发连接,全靠 epoll 在毫秒级别内精确调度。
2.3 Nginx 的进程架构
Nginx 采用"Master-Worker“多进程架构,这是它高性能和稳定性双重保障的关键:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
┌─────────────────┐
│ Master 进程 │ ← 管理员:管理配置、启动/关闭 worker、热重载
│ (1 个进程) │
└────────┬────────┘
│ 监控 & 信号控制
┌────────────┼────────────┐
↓ ↓ ↓
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Worker │ │ Worker │ │ Worker │ ← 真正干活的工人:处理请求
│ CPU 1 │ │ CPU 2 │ │ CPU 3 │ 每个 worker 独立,用 epoll 处理连接
└──────────┘ └──────────┘ └──────────┘
↑ ↑ ↑
└────────────┴────────────┘
共享监听套接字
(所有 worker 监听同一个端口,accept() 竞争)
|
Master 进程做什么:
- 读取并验证配置文件
- 启动、停止 worker 进程
- 接收管理员信号(reload、quit)
- 热更新:不中断服务的情况下加载新配置(启动新 worker 接收新请求,逐步关闭旧 worker)
Worker 进程做什么:
- 接受客户端连接
- 处理 HTTP 请求(读取请求、调用后端、处理响应)
- 管理 upstream 长连接池
- 写日志
为什么 worker 数量通常等于 CPU 核心数?
每个 worker 进程可以绑定到一个 CPU 核心运行,避免进程切换开销。如果你的服务器有 8 个 CPU 核心,就配置 worker_processes 8;。Nginx 默认 auto,会自动检测。
惊群问题(thundering herd):
当一个连接到达时,所有空闲的 worker 进程都会醒来抢这个连接,但只有一个能抢到——其他进程白醒了,浪费 CPU。在 Nginx 中,通过 accept_mutex 锁机制解决这个问题:只有持有锁的 worker 才能 accept 新连接,其他 worker 继续睡眠,不白跑。
三、Nginx 如何抗住亿级并发 — 横向扩展架构
3.1 单台 Nginx 的能力边界
在说亿级并发之前,先明确一个事实:单台 Nginx 的并发能力是有上限的。
单台 Nginx 能处理多少并发,取决于:
1
|
最大并发连接数 ≈ 文件描述符上限 / worker 进程数
|
Linux 默认文件描述符上限是 1024,但可以通过 ulimit -n 调大到几十万。一台 Nginx 理论上能处理几万到几十万并发连接。
但"几亿人同时访问"显然不是单台 Nginx 能扛得住的。答案是:水平扩展 + 多层架构。
3.2 百度级别的流量对抗策略:三层乃至四层入口
想象百度是如何一步步过滤和保护流量的:
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
|
第一层:DNS 智能解析
↓ 地域、运营商、负载情况返回最优 IP
↓ 全国用户
第二层:CDN 边缘节点(全国数百个)
↓ 静态资源缓存(图片、CSS、JS、字体)→ 直接返回,命中率极高
↓ 动态请求回源
第三层:Anycast + BGP 调度
↓ 同一 IP 路由到最近数据中心
↓ 数据中心入口
第四层:L4 负载均衡(HAProxy / IPVS / F5)
↓ 基于 IP + Port 的四层转发,极高吞吐
↓ 只转发到健康的后端
第五层:Nginx 集群(数十到数百台)
↓ 七层反向代理、SSL 终结、路由规则、限流
↓ 根据 URL 路径分发到不同 upstream
第六层:应用服务层(搜索、Feed、广告)
↓ 各自独立的微服务集群
第七层:数据层(Redis 缓存、MySQL、分布式存储)
↓ 最终数据来源
|
整个链路中,Nginx 位于第五层,是七层协议(HTTP/HTTPS)的第一道关卡。它的作用是:
- SSL/TLS 终结:解密 HTTPS 请求(消耗 CPU),把解密后的明文请求发给后端
- 路由分发:根据 URL 路径、请求头、Cookie 等规则,把请求路由到不同的 upstream
- 限流熔断:限制单 IP 请求频率,防止 DDoS
- Gzip 压缩:减少传输体积
- 静态资源服务:直接从磁盘返回图片、CSS、JS
3.3 负载均衡策略
Nginx 的 upstream 模块支持多种负载均衡策略:
1. 轮询(Round Robin)— 默认策略
1
2
3
4
5
6
|
请求 1 → Server A
请求 2 → Server B
请求 3 → Server C
请求 4 → Server A
请求 5 → Server B
...
|
后端服务器地位均等,轮流处理请求。
2. 加权轮询(Weighted Round Robin)
1
2
3
4
5
|
upstream backend {
server 10.0.1.1:8080 weight=5; # 每轮被选中5次
server 10.0.1.2:8080 weight=3; # 每轮被选中3次
server 10.0.1.3:8080 weight=2; # 每轮被选中2次
}
|
服务器配置强的多扛活,配置弱一些的少扛活。百度的搜索集群和广告集群之间,就用权重区分处理能力。
3. IP Hash
1
2
3
4
5
|
upstream backend {
ip_hash; # 同一 IP 的请求永远打到同一台后端
server 10.0.1.1:8080;
server 10.0.1.2:8080;
}
|
保证同一个用户的所有请求落到同一台服务器,解决 Session 不一致问题。但扩展时不友好(新增服务器会导致大量用户重新路由)。
4. 最少连接数(Least Connections)
1
2
3
4
5
|
upstream backend {
least_conn; # 把请求发给当前连接数最少的 server
server 10.0.1.1:8080;
server 10.0.1.2:8080;
}
|
适合请求处理时间差异较大的场景,比如有些请求处理很快(读缓存),有些很慢(查数据库)。
3.4 Keepalive 长连接:减少 TCP 握手开销
HTTP 是无状态协议,每次请求都要建立 TCP 连接(3 次握手),响应结束后还要断开(4 次挥手)。
如果每个请求都新建连接,SSL/TLS 握手还要额外 2-RTT,光是建立连接就要消耗大量时间和服务器资源。
Nginx 支持 upstream keepalive,大幅减少连接建立的开销:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
upstream backend {
server 10.0.1.1:8080;
server 10.0.1.2:8080;
keepalive 100; # 保持 100 个空闲长连接到后端
}
server {
location / {
proxy_pass http://backend;
proxy_http_version 1.1; # 必须使用 HTTP/1.1
proxy_set_header Connection ""; # 清除 Connection 头,让 Nginx 决定
}
}
|
1
2
3
4
|
没有 keepalive:每个请求都新建 TCP 连接
有 keepalive: 首次建立连接,后续请求复用该连接
效果:后端连接数大幅减少,延迟降低,服务器资源节省约 30-50%
|
3.5 限流:保护后端不被压垮
高并发场景下,限流是保护系统的关键防线。Nginx 提供了多种限流手段:
请求速率限流(ngx_http_limit_req_module):
1
2
3
4
5
6
7
8
9
10
11
12
|
http {
# 定义限流规则:每个 IP 每秒最多 100 个请求
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=100r/s;
server {
location /search/ {
# 突发最多 200 个请求,其余放入队列等待
limit_req zone=mylimit burst=200;
proxy_pass http://backend;
}
}
}
|
连接数限流(ngx_http_limit_conn_module):
1
2
3
4
5
6
7
8
9
10
11
|
http {
# 每个 IP 最多 50 个并发连接
limit_conn_zone $binary_remote_addr zone=connlimit:10m;
server {
location / {
limit_conn connlimit 50;
proxy_pass http://backend;
}
}
}
|
带宽限流:
1
2
3
4
|
location /download/ {
limit_rate 500k; # 每个连接限速 500KB/s
limit_rate_after 10m; # 前 10MB 不限速,之后限速
}
|
对于百度这样的巨型站点,限流策略要复杂得多,通常会在 Nginx 前面再部署一层专用的 WAF(Web Application Firewall)或 DDoS 防护服务(如阿里云 DDoS 高防),用机器学习识别恶意流量。
四、Nginx 的缓存策略:让后端喘口气
4.1 缓存为什么重要
假设百度首页每秒被访问 100 万次。如果每次访问都去后端服务器拉取数据,后端服务器每秒要处理 100 万次请求,压力巨大。但如果把首页内容缓存 5 分钟,100 万次访问中只有 12 次需要真正打后端——99.999% 的请求被 Nginx 直接在内存/磁盘中响应了。
4.2 Nginx 缓存配置
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
|
http {
# 定义缓存路径、容量上限、文件数量上限、缓存时间
proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=my_cache:100m
max_size=10g inactive=60m use_temp_path=off;
server {
location / {
proxy_pass http://backend;
# 启用缓存
proxy_cache my_cache;
# 缓存有效期(按 HTTP 状态码区分)
proxy_cache_valid 200 5m; # 200 响应缓存 5 分钟
proxy_cache_valid 404 1m; # 404 响应缓存 1 分钟
# 对比请求头:相同内容不重复缓存
proxy_cache_key "$scheme$request_method$host$request_uri";
# 添加缓存命中状态响应头,方便调试
add_header X-Cache-Status $upstream_cache_status;
# 缓存 purge 接口(可选)
proxy_cache_purge $arg_purge;
}
}
}
|
X-Cache-Status 响应头有三种值:
- HIT:缓存命中,直接返回
- MISS:缓存未命中,去后端拉取并缓存
- EXPIRED:缓存过期,重新验证
4.3 缓存失效的噩梦:缓存雪崩
缓存策略设计不当会引发"缓存雪崩”——大量缓存同时过期,所有请求瞬间打到后端,后端被压垮。
解决方案:
1
2
3
|
# 缓存过期时间加随机偏移量,避免集中过期
proxy_cache_valid 200 300s;
# 结合后端主动推送缓存更新的机制(如消息队列通知 Nginx 刷新)
|
百度的做法更复杂:采用多级缓存(Nginx 缓存 → CDN 缓存 → 浏览器缓存),以及缓存预热机制(用程序提前把热点数据加载到缓存层),确保在流量高峰期到来之前,缓存就已经就绪。
五、用百度串联 Nginx 全流程
5.1 用户访问百度搜索的完整技术流程
现在,让我们完整地走一遍用户访问 www.baidu.com/s?wd=nginx 的全过程:
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
33
34
35
36
37
38
39
40
41
42
|
步骤 1:DNS 解析
用户输入 www.baidu.com
DNS 服务器返回 CDN 的 IP(假设是北京节点的 123.125.115.110)
(根据用户地域、运营商,返回最近的 CDN 节点 IP)
步骤 2:CDN 边缘节点处理
用户浏览器向 123.125.115.110 发起请求
CDN 边缘节点检查本地缓存:
- 百度 logo、CSS、JS 等静态文件:缓存命中 → 直接返回
- 搜索结果页(动态内容):缓存未命中 → 回源到 Nginx 集群
步骤 3:Nginx 集群接收请求
请求到达百度的 Nginx 集群(全国可能有数十台 Nginx 做负载均衡)
Nginx 根据 URL 路径匹配规则:
- /s* → 路由到搜索服务 upstream
- /news* → 路由到新闻服务 upstream
- /img* → 路由到图片服务 upstream
假设我们访问 /s(搜索),匹配到搜索服务 upstream
Nginx 应用限流规则:单 IP 每秒最多 50 个搜索请求
步骤 4:负载均衡分发
搜索服务 upstream 包含数十台搜索服务器
Nginx 使用加权轮询,把请求分发到不同的搜索服务器
搜索服务器处理请求:
- 解析查询词 "nginx"
- 查询 Redis 缓存(是否已有搜索结果)
- 缓存命中 → 直接返回
- 缓存未命中 → 查询索引服务 → 返回结果
步骤 5:结果返回
搜索服务返回 JSON/HTML
Nginx 接收后:
- Gzip 压缩(减少传输体积)
- 添加各种响应头(缓存控制、安全头等)
- 通过长连接返回给客户端
步骤 6:浏览器渲染
浏览器收到响应,解析 HTML
加载 CSS、JS(这些由 Nginx 直接从 CDN 边缘节点返回,极快)
渲染出百度搜索结果页面
|
整个过程,从 DNS 解析到页面渲染完成,通常在 100-500ms 内完成。用户感知到的是"秒开"。
5.2 亿级并发背后的数字
以百度为例,估算一下各层的并发规模:
| 层级 |
组件 |
并发连接数 |
说明 |
| 用户层 |
浏览器 |
- |
数亿日活用户 |
| CDN 层 |
CDN 边缘节点 |
每节点数万 |
全国数百个节点,分布缓存静态资源 |
| L4 层 |
IPVS / F5 |
每台数十万 |
4 层转发,高吞吐 |
| L7 层 |
Nginx 集群 |
每台数万 |
数十台 Nginx,合计数十万到百万 |
| 应用层 |
搜索服务器 |
每台数千 |
数百台服务器集群 |
| 缓存层 |
Redis |
每节点数十万 |
集群模式,总吞吐极高 |
| 数据层 |
分布式数据库 |
每节点数千 |
数据分片,高可用 |
每一层的并发量逐层递减,但通过水平扩展,每一层都能扛住上一层的所有流量。单个 Nginx 节点处理数万个并发,数十个节点组合就能处理百万级并发——而这,只是整个系统的一小部分。
六、Nginx 配置实战:核心配置解读
6.1 最简配置文件结构
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
# 全局块:影响 Nginx 整体运行
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 10240; # 每个 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;
# upstream 块:定义后端服务器集群
upstream search_backend {
least_conn; # 最少连接优先
server 10.0.1.1:8080 weight=5;
server 10.0.1.2:8080 weight=5;
server 10.0.1.3:8080 weight=3;
server 10.0.1.4:8080 down; # 临时下线,不参与负载均衡
keepalive 100; # upstream 长连接
}
# server 块:定义虚拟主机
server {
listen 80;
server_name www.baidu.com;
location / {
proxy_pass http://search_backend;
proxy_http_version 1.1;
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 Connection "";
}
}
}
|
6.2 常用配置技巧
反向代理 HTTPS(SSL 终结):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
server {
listen 443 ssl http2;
server_name www.baidu.com;
ssl_certificate /etc/nginx/ssl/baidu.crt;
ssl_certificate_key /etc/nginx/ssl/baidu.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 1d;
location / {
proxy_pass http://backend;
}
}
|
动静分离(静态资源 Nginx 直返,后端只处理动态请求):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
server {
listen 80;
server_name www.baidu.com;
# 静态资源:图片、CSS、JS、字体 → 直接从 Nginx 磁盘返回
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2|ttf)$ {
root /data/www/static;
expires 30d; # 缓存 30 天
add_header Cache-Control "public, no-transform";
}
# 动态请求 → 转发到后端应用服务器
location / {
proxy_pass http://backend;
}
}
|
URL 重写(伪静态,SEO 友好):
1
2
3
4
5
|
# 把 /article/123 改写成 /article?id=123 转发给后端
location /article/ {
rewrite ^/article/(\d+)$ /article?id=$1 break;
proxy_pass http://backend;
}
|
灰度发布(基于 Cookie 或 IP 分配不同后端):
1
2
3
4
5
6
7
8
|
# Cookie 中 version=beta 的用户,打到新版本服务器
location / {
if ($cookie_version = "beta") {
proxy_pass http://backend_new;
break;
}
proxy_pass http://backend_old;
}
|
七、Nginx 的局限性与补充技术
7.1 Nginx 不是万能的
Nginx 在高并发领域非常强大,但它也有自己的边界:
静态文件服务强,复杂业务逻辑弱
Nginx 的配置语言(Nginx.conf)非常强大,但它的本质还是一个反向代理和静态文件服务器。对于复杂的业务逻辑(如动态页面模板、数据聚合、多方 API 编排),Nginx 的能力远不如代码层面的框架灵活。
长连接有上限
虽然 Nginx 用 epoll 能处理数十万并发,但每个连接都会消耗文件描述符和内存。当连接数超过一定规模(通常是百万级别),就需要在 Nginx 前面再加一层 L4 负载均衡(IPVS)来分流。
热更新有风险
Nginx 支持热更新配置(nginx -s reload),但热更新会重建监听套接字并逐个重启 worker 进程。在高流量场景下,如果配置有误导致新 worker 无法启动,可能造成短暂的不可用。
7.2 亿级流量架构中 Nginx 的定位总结
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
33
34
35
36
37
38
39
40
41
|
┌─────────────────────────────────────────────────────────────┐
│ 用户终端 │
└───────────────────────────┬─────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 第一层:DNS 智能解析(按地域/运营商返回最优 CDN 节点) │
└───────────────────────────┬─────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 第二层:CDN(全国数百节点,缓存静态资源,命中率 90%+) │
│ 典型产品:Cloudflare、阿里云 CDN、腾讯云 CDN │
└───────────────────────────┬─────────────────────────────────┘
↓ (动态请求回源)
┌─────────────────────────────────────────────────────────────┐
│ 第三层:Anycast + BGP 调度(同一 IP 路由到最近数据中心) │
└───────────────────────────┬─────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 第四层:L4 负载均衡(IPVS / HAProxy / F5) │
│ 基于 IP + Port,高吞吐(千万级并发) │
└───────────────────────────┬─────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 第五层:Nginx 七层反向代理 ⭐(本文主角) │
│ - SSL 终结(HTTPS 解密) │
│ - 路由分发(URL / Header / Cookie 规则) │
│ - 限流熔断 │
│ - 静态资源直返 │
│ - 请求缓存 │
│ - Gzip 压缩 │
│ - 日志记录 │
└───────────────────────────┬─────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 第六层:应用服务集群(搜索、Feed、广告、用户中心……) │
│ 每个服务独立集群,通过服务注册中心(Consul / Nacos)发现 │
└───────────────────────────┬─────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 第七层:数据层(Redis 集群、MySQL 集群、分布式文件系统) │
└─────────────────────────────────────────────────────────────┘
|
Nginx 在这个体系中,扮演的是**“全能型入口网关”**的角色——它不是最快的,也不是最强大的,但它足够稳定、足够灵活、足够通用。在第五层的位置上,Nginx 几乎没有任何竞争对手能同时满足如此多的需求。
结语
回到最初的问题:Nginx 为什么能扛住几亿人的访问?
答案不是 Nginx 本身有多神奇,而是一套精心设计的分层架构:
- 单台 Nginx 通过 epoll 事件驱动,用少量进程处理数万并发连接
- 通过水平扩展,N 台 Nginx 就能处理 N × 10000 的并发量
- 配合 CDN 缓存、L4 负载均衡、限流熔断等多层防线,99% 的流量被挡在前层
- 只有那 1% 的真正需要后端处理的请求,才打到应用服务器
百度的例子告诉我们:没有银弹,只有层层防线。 每一次"秒开"的体验,背后都是几十层基础设施精密协作的结果。Nginx 只是这其中的一环——但正是这关键的一环,撑起了整个互联网的高并发入口。
理解 Nginx,不仅仅是学会配置一个反向代理,而是理解互联网基础设施如何通过分层、解耦、冗余、限流等手段,将不可能变成可能。
当你下次再输入一个网址,看到页面瞬间加载时,不妨想想:有多少台 Nginx,正在那一刻为你的请求保驾护航。
相关推荐阅读: