# 反向代理与网关:Nginx / API Gateway 在系统中的位置 > 💡 **学习指南**:反向代理解决的是"流量怎么分发",API 网关解决的是"请求怎么处理"。本章节会围绕一个问题展开:**在高并发的互联网架构中,如何把流量安全、高效地送到正确的服务?** 在开始之前,建议你先补两块"基础砖": - **HTTP 基础**:可以先阅读 [Web 基础](./web-basics/) 的「HTTP 协议」部分。 - **服务器部署**:如果你还不熟悉 [部署相关概念](./deployment/),建议先了解基础。 --- ## 0. 引言:为什么网站访问慢了、挂了、被攻击了? 很多人在实际搭建网站时都会遇到类似的情况: - 网站流量一高就卡顿,用户体验很差; - 某台服务器宕机,整个网站就不可用了; - 网站被 DDoS 攻击,服务器直接被打垮; - 后台管理接口暴露在外网,被黑客扫描攻击。 直觉上,我们会以为是:**"服务器配置不够"**。 但大多数时候,问题并不在于服务器"性能差",而在于我们**没有把流量处理好**。 面对这些挑战,单纯依靠"升级服务器"已经捉襟见肘。我们需要一套更系统的流量管理方法,在高并发的场景下,把流量安全、高效地分发到正确的服务。这正是**反向代理与网关**试图解决的问题。 --- ## 1. 什么是"反向代理"?(定义 + 场景) 先给一个简短的工作定义,再看几个典型场景。 > 反向代理,是部署在服务器端的"流量中转站",接收客户端请求,转发给内部服务器,并将响应返回给客户端。客户端只知道反向代理的存在,不知道真实服务器的地址。 你可以简单地把它理解成三件事:**接收请求、转发请求、返回响应**。 常见会用到它的场景包括: - **负载均衡**:将流量分发到多台服务器,避免单点压力过大。 - **安全防护**:隐藏真实服务器 IP,防止直接攻击。 - **SSL 终结**:在网关层处理 HTTPS,后端服务使用 HTTP,降低计算开销。 - **动静分离**:静态资源直接由 Nginx 返回,动态请求转发给应用服务器。 接下来,我们就从一个真实团队的"踩坑经历"出发,看看他们是怎么一点点从"单机部署"进化到"网关架构"的。 --- ## 2. 从"血泪教训"说起:某电商大促踩过的坑 本章案例来自 **某电商平台**(日活千万级用户)。 与普通网站不同,电商平台在双十一等大促期间,流量会呈指数级增长,对系统的稳定性、性能、安全性都提出了极高要求。 这带来了核心矛盾: - **如果只用一台服务器**:流量一高就宕机,用户体验极差。 - **如果直接暴露多台服务器**:客户端需要知道多个 IP,无法实现负载均衡,而且安全性极差。 该平台的技术团队经历过多次架构重构,才明白一个道理:**流量不能只靠"挡",而要靠"疏"和"导"。** ### 2.1 四次重构教会我们什么? 该平台的 CTO 在架构分享会上讲过一个"踩坑史": | 阶段 | 遇到的问题 | 当时的想法 | 结果 | | :--- | :--- | :--- | :--- | | **第一次** | 单台服务器扛不住流量 | "换一台更好的服务器" | 流量再涨还是扛不住 | | **第二次** | 多台服务器不知如何分发流量 | "直接暴露多个 IP 给用户" | 用户访问混乱,无法实现负载均衡 | | **第三次** | 网站被 DDoS 攻击,真实 IP 暴露 | "在每台服务器上都配置防火墙" | 管理复杂,防护效果差 | | **第四次** | HTTPS 配置复杂,证书管理混乱 | "每台服务器都配置 SSL 证书" | 证书更新麻烦,配置不一致 | **核心领悟**:**不是服务器越多越好,而是流量管理越智能越好**。 ### 2.2 反向代理到底像什么? **直接暴露服务器** = **没有门卫的大楼**: - 任何人都可以直接找到房间(IP)。 - 来访者(请求)不知道去哪个房间,可能都挤在一个房间。 - 安全隐患大,坏人可以直接找到房间搞破坏。 **反向代理** = **有前台的大楼**: - 来访者(客户端)只知道前台地址(反向代理 IP)。 - 前台根据情况把来访者引导到不同的房间(服务器)。 - 房间的真实位置对外保密,安全性高。 **该平台的经验**:**大楼要有前台,流量要过网关**。 --- ## 3. 第一步:Nginx 架构 - 为什么它能扛住百万并发? 在深入配置之前,我们需要理解 Nginx 为什么能处理如此高的并发。这不是魔法,而是精心设计的架构。 ### 3.1 Master-Worker 进程模型 Nginx 采用**多进程**架构,而不是多线程: **Master 进程(管理者)**: - 负责读取和验证配置文件。 - 管理 Worker 进程(启动、停止、重新加载)。 - 不处理具体请求。 **Worker 进程(工作者)**: - 实际处理 HTTP 请求。 - 每个 Worker 是独立的进程,相互隔离。 - 数量通常设置为 CPU 核心数,避免上下文切换开销。 **优势**: - 一个 Worker 崩溃,不会影响其他 Worker。 - 充分利用多核 CPU。 - 避免多线程编程的复杂性。 ### 3.2 事件驱动 + 异步非阻塞 这是 Nginx 高性能的核心秘密: **传统 Apache(多进程/线程模型)**: - 一个连接 = 一个进程/线程。 - 并发数受限于系统进程/线程数。 - 大量连接时,进程切换开销巨大。 **Nginx(事件驱动模型)**: - 使用 epoll(Linux)/ kqueue(macOS)等高效 I/O 多路复用机制。 - 一个 Worker 进程可以同时处理数万个连接。 - 连接没有数据时,不会占用 CPU,有新数据时通过事件通知唤醒。 **比喻**: - Apache 像餐厅里每个顾客配一个服务员(进程)。 - Nginx 像一个超级服务员,同时服务所有顾客,谁需要服务就去谁那里,而不是一直站在某个顾客旁边。 ### 3.3 生产环境配置建议 ```nginx # 设置 Worker 进程数,通常等于 CPU 核心数 worker_processes auto; # 设置每个 Worker 的最大连接数 # 总并发连接数 = worker_processes * worker_connections events { worker_connections 4096; use epoll; # Linux 下使用 epoll multi_accept on; # 尽可能接受更多连接 } http { # 开启文件高效传输 sendfile on; tcp_nopush on; tcp_nodelay on; # 长连接超时时间 keepalive_timeout 65; # Gzip 压缩 gzip on; gzip_vary on; gzip_min_length 1024; gzip_types text/plain text/css application/json application/javascript; } ``` --- ## 4. 第二步:API 网关 - 系统的"统一大门" 如果说反向代理是"流量中转站",那么 API 网关就是"智能调度中心"。它不仅仅是转发请求,还承担了很多横切关注点的处理。 ### 4.1 为什么需要 API 网关? 想象一个没有网关的系统: - 客户端需要知道多个服务的地址(用户服务、订单服务、支付服务...)。 - 每个服务都要自己做认证、限流、日志。 - 协议不统一,有的用 HTTP,有的用 gRPC。 - 服务升级时,客户端也需要跟着改。 **有了 API 网关之后**: - 客户端只需要知道网关地址,网关负责路由到正确服务。 - 认证、限流、日志等横切逻辑统一在网关处理。 - 网关可以做协议转换,对外统一暴露 HTTP。 - 后端服务升级,只需要改网关配置,客户端无感知。 ### 4.2 API 网关的核心功能 | 功能 | 说明 | 典型场景 | | :--- | :--- | :--- | | **路由转发** | 根据 URL、Header 等规则,将请求转发到不同服务 | `/api/users` → 用户服务,`/api/orders` → 订单服务 | | **负载均衡** | 同一个服务有多实例时,分摊流量 | 用户服务有 3 台实例,轮询分发请求 | | **认证鉴权** | 统一校验 JWT、OAuth Token | 未登录用户无法访问 `/api/admin` | | **限流熔断** | 控制流量上限,防止服务被压垮 | 每秒最多 1000 请求,超过返回 429 | | **协议转换** | 对外 HTTP,内部可转 gRPC | 客户端用 HTTP,网关转 gRPC 调用内部服务 | | **灰度发布** | 按 Header 或比例,将部分流量导到新版本 | 5% 用户体验新版本,95% 用旧版本 | | **日志监控** | 统一记录请求日志,便于分析和排障 | 记录每次请求的耗时、状态码、返回大小 | ### 4.3 Nginx vs Kong vs Spring Cloud Gateway 市面上有很多网关产品,如何选择? | 维度 | Nginx | Kong | Spring Cloud Gateway | | :--- | :--- | :--- | :--- | | **定位** | 高性能反向代理/负载均衡 | 开源 API 网关 | Spring 生态网关 | | **性能** | 极高(C 语言,事件驱动) | 高(基于 OpenResty) | 中等(Java,响应式) | | **功能** | 基础负载均衡、静态文件、缓存 | 丰富的插件生态(认证、限流、日志等) | 与 Spring Cloud 深度集成 | | **配置** | 配置文件(nginx.conf) | REST API + 配置文件 | Java 配置 / YAML | | **扩展** | C 模块 / Lua 脚本 | Lua 插件 | Java 过滤器 | | **适用场景** | 静态资源、七层负载均衡、SSL 终结 | 微服务 API 网关、多租户 SaaS | Spring Cloud 微服务架构 | **选型建议**: - **中小型项目 / 静态资源为主**:Nginx 足够。 - **大型微服务 / 需要丰富插件**:Kong。 - **Spring Cloud 全家桶**:Spring Cloud Gateway。 --- ## 5. 第三步:路由与负载均衡 - 把请求送到正确的地方 网关的核心职责之一,就是**把请求送到正确的地方**。这涉及两个关键能力:**路由**(去哪台服务器)和**负载均衡**(怎么分配流量)。 ### 5.1 路由规则:从 URL 到服务 想象一个电商系统,不同的 URL 对应不同的服务: - `/api/users/*` → 用户服务 - `/api/orders/*` → 订单服务 - `/api/products/*` → 商品服务 - `/api/pay/*` → 支付服务 **Nginx 配置示例**: ```nginx server { listen 80; server_name api.example.com; # 用户服务 location /api/users/ { proxy_pass http://user-service; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # 订单服务 location /api/orders/ { proxy_pass http://order-service; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # 商品服务 location /api/products/ { proxy_pass http://product-service; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # 支付服务(需要更高安全级别) location /api/pay/ { # 限制 IP 访问 allow 10.0.0.0/8; deny all; proxy_pass http://payment-service; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } ``` **高级路由规则**: ```nginx # 基于请求方法的路由 if ($request_method = POST) { proxy_pass http://write-service; } # 基于 Header 的路由(灰度发布) if ($http_x_version = "v2") { proxy_pass http://api-v2; } # 基于 Cookie 的路由(AB 测试) if ($cookie_test_group = "B") { proxy_pass http://variant-b; } # 基于 Query 参数的路由 if ($arg_format = "json") { proxy_pass http://json-api; } ``` ### 5.2 负载均衡:四种策略对比 当同一个服务有多个实例时,如何选择? | 策略 | 原理 | 适用场景 | 优点 | 缺点 | | :--- | :--- | :--- | :--- | :--- | | **轮询** (Round Robin) | 按顺序依次分配给每台服务器 | 服务器性能相近 | 简单公平 | 不考虑服务器当前负载 | | **加权轮询** (Weighted RR) | 按权重比例分配,权重高的分配更多 | 服务器性能不均 | 充分利用高性能服务器 | 需要合理设置权重 | | **最少连接** (Least Connections) | 分配给当前连接数最少的服务器 | 长连接场景(WebSocket、视频流) | 动态适应负载变化 | 需要实时统计连接数 | | **IP 哈希** (IP Hash) | 根据客户端 IP 计算哈希,同一 IP 永远分配到同一台服务器 | 需要会话保持的场景 | 保证会话一致性 | 某个 IP 流量大时会造成单点压力 | **Nginx 配置示例**: ```nginx # 定义 upstream 组 upstream backend { # 轮询(默认) server 10.0.1.10:8080; server 10.0.1.11:8080; server 10.0.1.12:8080; } upstream backend_weighted { # 加权轮询 server 10.0.1.10:8080 weight=3; # 性能好,承担更多流量 server 10.0.1.11:8080 weight=2; server 10.0.1.12:8080 weight=1; # 性能差,承担较少流量 } upstream backend_least_conn { # 最少连接 least_conn; server 10.0.1.10:8080; server 10.0.1.11:8080; server 10.0.1.12:8080; } upstream backend_ip_hash { # IP 哈希(会话保持) ip_hash; server 10.0.1.10:8080; server 10.0.1.11:8080; server 10.0.1.12:8080; } server { listen 80; server_name api.example.com; location / { proxy_pass http://backend; 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; # 健康检查(需要第三方模块或 Nginx Plus) # health_check; } } ``` ### 5.3 避坑指南:负载均衡的常见误区 #### 误区 1:忽视健康检查 ```nginx # ❌ 错误:没有健康检查,后端服务宕机了,流量还会继续发送 upstream backend { server 10.0.1.10:8080; server 10.0.1.11:8080; # 这台宕机了,请求会失败 } # ✅ 正确:配置健康检查(Nginx Plus 或第三方模块) upstream backend { server 10.0.1.10:8080; server 10.0.1.11:8080; # 主动健康检查(Nginx Plus 或配置 check 模块) check interval=3000 rise=2 fall=3 timeout=1000 type=http; check_http_send "GET /health HTTP/1.0\r\n\r\n"; check_http_expect_alive http_2xx http_3xx; } ``` #### 误区 2:会话保持滥用 ```nginx # ❌ 错误:所有请求都使用 IP 哈希,导致负载不均 upstream backend { ip_hash; # 某些 IP 流量特别大,导致单点压力 server 10.0.1.10:8080; server 10.0.1.11:8080; } # ✅ 正确:需要会话保持的才用 IP 哈希,其他用轮询 upstream backend { server 10.0.1.10:8080; server 10.0.1.11:8080; } upstream backend_session { ip_hash; server 10.0.1.10:8080; server 10.0.1.11:8080; } server { location /api/ { proxy_pass http://backend; # 普通 API,无需会话保持 } location /cart/ { proxy_pass http://backend_session; # 购物车,需要会话保持 } } ``` #### 误区 3:忽视后端获取真实 IP ```nginx # ❌ 错误:后端应用获取到的 IP 是 Nginx 的 IP,不是客户端真实 IP server { location / { proxy_pass http://backend; # 缺少 Header 设置 } } # ✅ 正确:传递真实 IP 和协议信息 server { location / { proxy_pass http://backend; # 必须设置的 Header 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; # 代理链 proxy_set_header X-Forwarded-Proto $scheme; # 原始协议(http/https) # 如果后端也是 Nginx,可以设置真实端口 proxy_set_header X-Forwarded-Port $server_port; } } ``` 后端应用(以 Node.js Express 为例)获取真实 IP: ```javascript const express = require('express'); const app = express(); // 信任代理(必须设置,否则 X-Forwarded-* 会被忽略) app.set('trust proxy', true); app.get('/api/test', (req, res) => { res.json({ // 客户端真实 IP(经过代理链后的第一个 IP) realIp: req.ip, // 完整的代理链(客户端, 代理1, 代理2, ...) forwardedFor: req.get('X-Forwarded-For'), // 原始协议(http 或 https) protocol: req.protocol, // 原始 Host host: req.get('Host') }); }); app.listen(3000); ``` --- ## 4. 第三步:限流与熔断 - 防止系统被"流量洪水"冲垮 在高并发场景下,保护系统不被突发流量压垮,是网关的核心职责之一。这需要用到**限流**和**熔断**机制。 ### 4.1 限流算法对比:令牌桶 vs 漏桶 vs 滑动窗口 | 算法 | 核心思想 | 突发流量 | 适用场景 | 实现复杂度 | | :--- | :--- | :--- | :--- | :--- | | **令牌桶** | 桶里装令牌,有令牌才能通过 | 允许一定程度的突发 | API 限流、带宽控制 | 中等 | | **漏桶** | 请求进桶,匀速流出处理 | 强制平滑,突发会被缓存或拒绝 | 需要严格匀速处理的场景 | 中等 | | **滑动窗口** | 统计时间窗口内的请求数 | 严格按窗口计数,超出一律拒绝 | 精确统计(如"1分钟内最多100次") | 较高 | ### 4.2 Nginx 限流配置实战 ```nginx # 定义限流区域(放在 http 块中) # 1. 基于 IP 的限流(漏桶算法) # zone=mylimit:10m - 区域名称和内存大小(10MB 约可存储 16 万 IP) # rate=10r/s - 每秒允许 10 个请求 limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s; # 2. 基于 IP 的连接数限制(防止单个 IP 建立过多连接) limit_conn_zone $binary_remote_addr zone=addr:10m; # 3. 基于服务端点的限流(不区分 IP,保护后端整体) limit_req_zone $server_name zone=server_limit:10m rate=100r/s; server { listen 80; server_name api.example.com; # 用户服务 - 普通限流 location /api/users/ { # 应用限流 # burst=20 - 桶容量,允许突发 20 个请求 # nodelay - 不延迟处理突发请求(立即处理或拒绝) limit_req zone=mylimit burst=20 nodelay; # 限制单个 IP 的连接数 limit_conn addr 10; proxy_pass http://user-service; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # 订单服务 - 更严格的限流 location /api/orders/ { # 更严格的限流:每秒 5 个请求 limit_req_zone $binary_remote_addr zone=order_limit:10m rate=5r/s; limit_req zone=order_limit burst=10 nodelay; proxy_pass http://order-service; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # 支付服务 - 最高级别保护 location /api/pay/ { # 多层限流保护 # 第一层:单 IP 限流(每秒 2 个请求) limit_req_zone $binary_remote_addr zone=pay_ip_limit:10m rate=2r/s; limit_req zone=pay_ip_limit burst=5 nodelay; # 第二层:全局限流(保护后端数据库) limit_req zone=server_limit burst=50 nodelay; # 第三层:连接数限制 limit_conn addr 5; # 只允许内网访问(额外安全层) allow 10.0.0.0/8; deny all; proxy_pass http://payment-service; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; # 支付接口增加超时时间 proxy_connect_timeout 30s; proxy_send_timeout 30s; proxy_read_timeout 30s; } # 限流后的处理 # 当请求被限流时,返回 429 Too Many Requests error_page 429 /429.html; location = /429.html { internal; return 429 '{"error": "Too Many Requests", "message": "Rate limit exceeded. Please try again later."}'; add_header Content-Type application/json; } } ``` ### 4.3 熔断降级:当依赖服务出问题时 限流是防止外部流量压垮系统,**熔断**是防止内部依赖故障扩散。 **熔断器的工作原理**: 1. **关闭状态**:正常转发请求,同时统计错误率。 2. **开启状态**:当错误率超过阈值,熔断器开启,直接返回错误,不再转发请求。 3. **半开状态**:经过一段时间后,允许少量请求通过试探,如果成功则关闭熔断器。 **Nginx 实现熔断(使用 Lua 模块或第三方模块)**: ```nginx # 使用 nginx-upsync-module 或 lua-resty-healthcheck 实现健康检查和熔断 upstream backend { server 10.0.1.10:8080; server 10.0.1.11:8080; # 健康检查(需要 nginx_upstream_check_module) check interval=3000 rise=2 fall=3 timeout=1000 type=http; check_http_send "GET /health HTTP/1.0\r\n\r\n"; check_http_expect_alive http_2xx http_3xx; } server { location / { proxy_pass http://backend; # 代理错误时返回自定义错误页(降级) proxy_intercept_errors on; error_page 500 502 503 504 /fallback.html; } location = /fallback.html { internal; # 返回降级数据(如缓存数据、简化版页面) return 200 '{"status": "degraded", "message": "Service temporarily unavailable. Showing cached data."}'; add_header Content-Type application/json; } } ``` **使用 OpenResty + Lua 实现更完善的熔断**: ```lua -- 使用 lua-resty-circuit-breaker 库实现熔断 local circuit_breaker = require "resty.circuit-breaker" local cb = circuit_breaker.new({ name = "payment_service", group = "payment", -- 熔断策略 failure_threshold = 5, -- 连续失败 5 次触发熔断 success_threshold = 2, -- 连续成功 2 次关闭熔断 timeout = 60, -- 熔断后等待 60 秒进入半开状态 -- 错误类型 expected_statuses = {200, 201}, -- 期望的 HTTP 状态码 ignored_statuses = {404, 422}, -- 不计入失败的 status }) -- 使用熔断器执行请求 local ok, err = cb:execute(function() -- 发起 HTTP 请求 local httpc = require "resty.http".new() local res, err = httpc:request_uri("http://payment-service/charge", { method = "POST", body = body, headers = { ["Content-Type"] = "application/json", }, }) if not res then return nil, err end return res end) if not ok then -- 熔断器开启或请求失败,执行降级逻辑 ngx.log(ngx.WARN, "Circuit breaker open or request failed: ", err) -- 返回降级响应 ngx.status = 503 ngx.say('{"error": "Service temporarily unavailable", "fallback": true}') return end -- 请求成功,返回正常响应 ngx.status = res.status ngx.say(res.body) ``` --- ## 6. 第四步:认证与安全 - 守护大门的"门卫" 网关是系统的统一入口,自然也成为**安全防护的第一道防线**。在网关层处理认证和安全,可以避免每个后端服务重复实现。 ### 6.1 在网关层统一认证 **传统方式(每个服务各自认证)**: - 用户服务、订单服务、支付服务...每个都要校验 JWT。 - 代码重复,维护困难。 - secret 分散在各个服务,泄露风险高。 **网关统一认证**: - 客户端携带 Token 访问网关。 - 网关校验 Token 合法性(签名、过期时间)。 - 校验通过后,将用户信息(如 user_id)添加到请求头,转发给后端服务。 - 后端服务无需校验,直接从 Header 获取用户信息。 **Nginx + Lua 实现 JWT 校验**: ```nginx server { listen 80; server_name api.example.com; location / { # 使用 access_by_lua_block 进行认证 access_by_lua_block { local jwt = require "resty.jwt" -- 从请求头获取 Token local auth_header = ngx.var.http_authorization if not auth_header then ngx.status = 401 ngx.say('{"error": "Missing authorization header"}') ngx.exit(ngx.HTTP_UNAUTHORIZED) end -- 提取 Token(Bearer token) local token = auth_header:match("^Bearer%s+(.+)$") if not token then ngx.status = 401 ngx.say('{"error": "Invalid authorization format"}') ngx.exit(ngx.HTTP_UNAUTHORIZED) end -- 验证 JWT local jwt_obj = jwt:verify("your-secret-key", token) if not jwt_obj.verified then ngx.status = 401 ngx.say('{"error": "Invalid or expired token"}') ngx.exit(ngx.HTTP_UNAUTHORIZED) end -- 将用户信息设置到变量,供后续使用 ngx.var.user_id = jwt_obj.payload.sub ngx.var.user_role = jwt_obj.payload.role } # 将用户信息传递给后端服务 proxy_set_header X-User-ID $user_id; proxy_set_header X-User-Role $user_role; proxy_set_header X-Real-IP $remote_addr; proxy_pass http://backend; } # 公开接口,无需认证 location /api/public/ { proxy_pass http://backend; proxy_set_header X-Real-IP $remote_addr; } } ``` ### 6.2 HTTPS 与 SSL 终结 HTTPS 是现代 Web 应用的标配。但如果在每台后端服务器都配置 HTTPS,会带来很多麻烦: - 证书管理复杂,每台服务器都要部署、更新证书。 - 后端服务需要处理 TLS 握手,消耗 CPU 资源。 - 配置容易出错,不一致。 **SSL 终结(SSL Termination)** 方案: - 只在网关(Nginx)层配置 HTTPS 和证书。 - 网关负责 TLS 握手和加解密。 - 网关和后端服务之间使用 HTTP 明文传输(内部网络可信)。 - 后端服务专注于业务逻辑,无需处理 TLS。 **SSL 终结流程**: 1. 客户端发送 HTTPS 请求到 Nginx。 2. Nginx 和客户端完成 TLS 握手,建立加密通道。 3. Nginx 解密请求,得到明文 HTTP 请求。 4. Nginx 将明文 HTTP 请求转发给后端服务(通过内部网络)。 5. 后端服务处理请求,返回明文 HTTP 响应给 Nginx。 6. Nginx 加密响应,通过 HTTPS 返回给客户端。 **Nginx HTTPS 配置**: ```nginx server { # 监听 443 端口,启用 SSL listen 443 ssl http2; server_name api.example.com; # SSL 证书配置 ssl_certificate /etc/nginx/ssl/api.example.com.crt; # 证书文件 ssl_certificate_key /etc/nginx/ssl/api.example.com.key; # 私钥文件 # SSL 协议和密码套件(安全配置) ssl_protocols TLSv1.2 TLSv1.3; # 只启用安全的 TLS 版本 ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; # 强密码套件 ssl_prefer_server_ciphers off; # 优先使用客户端支持的密码套件 # SSL 会话缓存(提升性能) ssl_session_cache shared:SSL:50m; # 会话缓存大小 ssl_session_timeout 1d; # 会话超时时间 ssl_session_tickets off; # 禁用会话票证(前向安全) # OCSP Stapling(提升性能和隐私) ssl_stapling on; # 启用 OCSP Stapling ssl_stapling_verify on; # 验证 OCSP 响应 ssl_trusted_certificate /etc/nginx/ssl/chain.crt; # 信任链 resolver 8.8.8.8 8.8.4.4 valid=300s; # DNS 解析器 resolver_timeout 5s; # DNS 解析超时 # 安全响应头 add_header Strict-Transport-Security "max-age=63072000" always; # HSTS add_header X-Frame-Options "SAMEORIGIN" always; # 防止点击劫持 add_header X-Content-Type-Options "nosniff" always; # 防止 MIME 嗅探 add_header Referrer-Policy "strict-origin-when-cross-origin" always; # Referrer 策略 # SSL 终结后,转发到后端 HTTP 服务 location / { proxy_pass http://backend; # 后端使用 HTTP 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; # 传递原始协议(https) proxy_set_header X-Forwarded-Port 443; # 传递原始端口 } } # HTTP 重定向到 HTTPS(强制 HTTPS) server { listen 80; server_name api.example.com; # 所有 HTTP 请求 301 重定向到 HTTPS return 301 https://$server_name$request_uri; } ``` ### 6.3 安全配置清单 | 配置项 | 说明 | 推荐值 | | :--- | :--- | :--- | | **SSL 协议** | 启用的 TLS 版本 | `TLSv1.2 TLSv1.3`(禁用 SSLv3、TLSv1.0/1.1) | | **密码套件** | 加密算法组合 | 优先使用 `ECDHE` + `AES-GCM`,禁用 `RC4`、`DES`、`MD5` | | **HSTS** | 强制 HTTPS | `max-age=63072000`(两年) | | **证书有效期** | SSL 证书过期时间 | 不超过 397 天(行业规范) | | **OCSP Stapling** | 证书状态检查 | 启用,提升性能和隐私 | | **Session Tickets** | 会话恢复机制 | 禁用(前向安全考虑)或定期轮换密钥 | --- ## 7. 系统整合:打造完整的网关架构 现在,是时候把之前学到的所有组件整合起来,搭建一个完整的网关架构了。 ### 7.1 完整架构图 ``` ┌─────────────────────────────────────────────────────────────────────────────┐ │ 客户端(浏览器/APP) │ └───────────────────────────────┬─────────────────────────────────────────────┘ │ HTTPS ▼ ┌─────────────────────────────────────────────────────────────────────────────┐ │ 外层:CDN + WAF │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ CDN(内容分发网络) │ │ │ │ - 静态资源缓存(图片、CSS、JS) │ │ │ │ - 就近访问,降低延迟 │ │ │ └─────────────────────────────────────────────────────────────────────┘ │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ WAF(Web 应用防火墙) │ │ │ │ - 防护 SQL 注入、XSS 攻击 │ │ │ │ - 拦截恶意 Bot、爬虫 │ │ │ │ - CC 攻击防护(Challenge Collapsar) │ │ │ └─────────────────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────────┐ │ 中层:API 网关(Nginx/Kong) │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ 第一层:SSL 终结 + 安全防护 │ │ │ │ - HTTPS / TLS 1.3 │ │ │ │ - HSTS、安全响应头 │ │ │ │ - OCSP Stapling │ │ │ └─────────────────────────────────────────────────────────────────────┘ │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ 第二层:认证与鉴权 │ │ │ │ - JWT Token 校验 │ │ │ │ - OAuth 2.0 / SSO 集成 │ │ │ │ - API Key 管理 │ │ │ │ - 权限校验(RBAC) │ │ │ └─────────────────────────────────────────────────────────────────────┘ │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ 第三层:流量控制 │ │ │ │ - 限流(Rate Limiting)- 令牌桶/漏桶算法 │ │ │ │ - 熔断(Circuit Breaking)- 防止故障扩散 │ │ │ │ - 降级(Degradation)- 服务不可用时的备用方案 │ │ │ │ - 灰度发布(Canary Release)- 按比例分配流量 │ │ │ └─────────────────────────────────────────────────────────────────────┘ │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ 第四层:路由与负载均衡 │ │ │ │ - 路径路由(Path-based Routing) │ │ │ │ - 域名路由(Host-based Routing) │ │ │ │ - Header 路由(Header-based Routing) │ │ │ │ - 负载均衡算法(轮询/加权/最少连接/IP 哈希) │ │ │ │ - 服务发现(Service Discovery)集成 │ │ │ └─────────────────────────────────────────────────────────────────────┘ │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ 第五层:协议转换与数据处理 │ │ │ │ - SSL 终结(HTTPS ↔ HTTP) │ │ │ │ - 协议转换(HTTP ↔ gRPC / WebSocket) │ │ │ │ - 请求/响应转换(JSON ↔ XML) │ │ │ │ - 数据压缩(Gzip / Brotli) │ │ │ │ - 缓存(Cache)- 静态资源和 API 响应 │ │ │ └─────────────────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────────┐ │ 内层:微服务集群 │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ 用户服务 │ │ 订单服务 │ │ 商品服务 │ │ 支付服务 │ │ │ │ User Svc │ │ Order Svc │ │ Product Svc │ │ Payment Svc │ │ │ │ │ │ │ │ │ │ │ │ │ │ 服务注册 │ │ 服务注册 │ │ 服务注册 │ │ 服务注册 │ │ │ │ Consul │ │ Consul │ │ Consul │ │ Consul │ │ │ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │ │ │ │ │ │ │ │ └────────────────┴────────────────┴────────────────┘ │ │ │ │ │ 服务发现与配置中心(Consul / etcd) │ │ - 服务注册与发现 │ │ - 健康检查 │ │ - KV 配置存储 │ └─────────────────────────────────────────────────────────────────────────────┘ ``` ### 7.2 实战代码模板:完整的 Nginx 网关配置 ```nginx # /etc/nginx/nginx.conf user nginx; worker_processes auto; # 自动设置为 CPU 核心数 error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; # 加载动态模块(根据实际需要启用) # load_module modules/ngx_http_geoip2_module.so; # 工作模式和连接数上限 events { use epoll; # Linux 下使用 epoll worker_connections 4096; # 每个 Worker 的最大连接数 multi_accept on; # 尽可能接受更多连接 } 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" ' 'rt=$request_time uct="$upstream_connect_time" ' 'uht="$upstream_header_time" urt="$upstream_response_time"'; access_log /var/log/nginx/access.log main; # 性能优化 sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; # Gzip 压缩 gzip on; gzip_vary on; gzip_proxied any; gzip_comp_level 6; gzip_min_length 1000; gzip_types text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml; # 安全响应头 add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; # 防止点击劫持(可选) # add_header Content-Security-Policy "default-src 'self'; frame-ancestors 'self';" always; # 上游服务定义 # 用户服务(加权轮询) upstream user_service { server 10.0.1.10:8080 weight=3; server 10.0.1.11:8080 weight=2; keepalive 32; } # 订单服务(最少连接) upstream order_service { least_conn; server 10.0.1.20:8080; server 10.0.1.21:8080; server 10.0.1.22:8080; keepalive 32; } # 商品服务(IP 哈希,会话保持) upstream product_service { ip_hash; server 10.0.1.30:8080; server 10.0.1.31:8080; keepalive 32; } # 支付服务(严格的负载均衡 + 健康检查) upstream payment_service { server 10.0.1.40:8080 weight=2; server 10.0.1.41:8080 backup; # 备份服务器 keepalive 32; } # 限流区域定义 # 普通 API 限流:每秒 10 请求 limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s; # 严格限流:每秒 2 请求(用于敏感接口) limit_req_zone $binary_remote_addr zone=strict_limit:10m rate=2r/s; # 全局限流:保护后端整体 limit_req_zone $server_name zone=global_limit:10m rate=100r/s; # 连接数限制 limit_conn_zone $binary_remote_addr zone=conn_limit:10m; # 虚拟主机配置 server { listen 80; server_name api.example.com; # 强制 HTTPS return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; server_name api.example.com; # SSL 配置(略,见上文) ssl_certificate /etc/nginx/ssl/api.example.com.crt; ssl_certificate_key /etc/nginx/ssl/api.example.com.key; # ... 其他 SSL 配置 # 全局限流 limit_req zone=global_limit burst=200 nodelay; # ===== 用户服务路由 ===== location /api/users/ { # 应用限流 limit_req zone=api_limit burst=20 nodelay; limit_conn conn_limit 10; # 超时设置 proxy_connect_timeout 5s; proxy_send_timeout 10s; proxy_read_timeout 10s; proxy_pass http://user_service; 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; # 错误处理 proxy_intercept_errors on; error_page 500 502 503 504 /error.html; } # ===== 订单服务路由 ===== location /api/orders/ { # 更严格的限流 limit_req zone=strict_limit burst=10 nodelay; limit_conn conn_limit 5; proxy_pass http://order_service; 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; } # ===== 商品服务路由 ===== location /api/products/ { # 缓存静态资源 location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ { expires 30d; add_header Cache-Control "public, immutable"; } proxy_pass http://product_service; 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; } # ===== 支付服务路由(最高安全级别) ===== location /api/pay/ { # 多重限流保护 limit_req zone=strict_limit burst=5 nodelay; limit_req zone=global_limit burst=50 nodelay; limit_conn conn_limit 3; # 只允许内网访问(额外安全层) allow 10.0.0.0/8; allow 172.16.0.0/12; allow 192.168.0.0/16; deny all; # 详细日志记录 access_log /var/log/nginx/payment-access.log detailed; proxy_pass http://payment_service; 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; # 支付接口增加超时时间 proxy_connect_timeout 30s; proxy_send_timeout 30s; proxy_read_timeout 30s; } # 健康检查端点 location /health { access_log off; return 200 "healthy\n"; add_header Content-Type text/plain; } # 错误页面 location /error.html { internal; root /var/www/html; } # 限流错误处理 error_page 429 /429.html; location = /429.html { internal; return 429 '{"error": "Too Many Requests", "message": "Rate limit exceeded. Please try again later."}'; add_header Content-Type application/json; } } } ``` ### 7.3 为什么这样设计最强? 这个架构的设计哲学,是为了解决三个核心矛盾: **1. 高性能与高可用(负载均衡 + 健康检查)** - **矛盾**:单台服务器性能有限,容易成为瓶颈;多台服务器需要协调,避免单点故障。 - **解法**:使用 Nginx 作为负载均衡器,支持多种负载均衡算法(轮询、加权、最少连接、IP 哈希)。配合健康检查,自动剔除故障节点,保证服务高可用。 **2. 安全性与易用性(SSL 终结 + 统一认证)** - **矛盾**:HTTPS 保证安全,但配置复杂、证书管理麻烦;每个服务都认证,代码重复、维护困难。 - **解法**:在 Nginx 层统一做 SSL 终结和认证。客户端只需信任 Nginx 的证书,后端服务之间使用 HTTP 明文通信,简化配置。认证逻辑统一在网关处理,后端服务专注于业务逻辑。 **3. 灵活性与稳定性(限流熔断 + 灰度发布)** - **矛盾**:新功能需要快速上线验证,但全量发布风险大;突发流量可能压垮系统,需要保护机制。 - **解法**:使用 Nginx 的限流和熔断功能,防止系统被突发流量压垮。配合灰度发布,按 Header 或比例将部分流量导到新版本,验证稳定性后再全量上线。 --- ## 8. 实战模板:直接抄作业 为了让你更直观地理解这套机制是如何运作的,我们为你准备了**全链路配置模板**。 ### 场景 1:中小型 Web 应用(单域名,多服务) > 适用场景:创业公司官网 + 后台管理 + API 服务 ```nginx # /etc/nginx/nginx.conf user nginx; worker_processes auto; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { use epoll; worker_connections 4096; multi_accept on; } 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_vary on; gzip_proxied any; gzip_comp_level 6; gzip_min_length 1000; gzip_types text/plain text/css text/xml application/json application/javascript; # 安全响应头 add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block" always; # 上游服务 upstream app_servers { server 127.0.0.1:3000; server 127.0.0.1:3001; keepalive 32; } upstream api_servers { server 127.0.0.1:4000; keepalive 32; } # 限流配置 limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s; limit_req_zone $binary_remote_addr zone=api:10m rate=20r/s; # HTTP 服务器 server { listen 80; server_name example.com www.example.com; # 强制 HTTPS(生产环境启用) # return 301 https://$server_name$request_uri; # 静态文件 location /static/ { alias /var/www/html/static/; expires 30d; add_header Cache-Control "public, immutable"; } location /images/ { alias /var/www/html/images/; expires 90d; add_header Cache-Control "public, immutable"; } # 前端应用 location / { limit_req zone=general burst=20 nodelay; proxy_pass http://app_servers; 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; } # API 接口 location /api/ { limit_req zone=api burst=40 nodelay; proxy_pass http://api_servers; 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; } # 健康检查 location /health { access_log off; return 200 "healthy\n"; add_header Content-Type text/plain; } } # HTTPS 服务器(生产环境启用) # server { # listen 443 ssl http2; # server_name example.com www.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_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; # ssl_prefer_server_ciphers off; # ssl_session_cache shared:SSL:50m; # ssl_session_timeout 1d; # # # 复制 HTTP 服务器的 location 配置 # # ... # } } ``` ### 场景 2:微服务架构(多域名,复杂路由) > 适用场景:大型互联网公司,多业务线,多团队协作 ```nginx # 微服务架构下的 Nginx 配置示例 # 特点:多域名、复杂路由、服务发现集成 # 服务发现集成(使用 Consul 或 etcd) # 需要 nginx-upsync-module 模块 upstream user_service { # 从 Consul 自动发现服务实例 upsync 127.0.0.1:8500/v1/catalog/service/user-service upsync_timeout=6m upsync_interval=500ms; upsync_dump_path /var/nginx/conf/user_service.conf; # 默认服务器(Consul 不可用时使用) server 127.0.0.1:11111 down; keepalive 64; keepalive_timeout 60s; keepalive_requests 1000; } # 动态 upstream 示例(Lua + Redis) upstream dynamic_backend { server 0.0.0.0; # 占位符 balancer_by_lua_block { local balancer = require "ngx.balancer" local resty_redis = require "resty.redis" -- 从 Redis 获取可用后端列表 local redis = resty_redis:new() redis:connect("127.0.0.1", 6379) local backends, err = redis:smembers("backends:available") if not backends or #backends == 0 then ngx.log(ngx.ERR, "no available backends") return ngx.exit(503) end -- 简单的轮询选择 local hash = ngx.var.remote_addr .. ngx.var.request_uri local index = ngx.crc32_short(hash) % #backends + 1 local selected = backends[index] -- 设置后端地址 local ok, err = balancer.set_current_peer(selected, 80) if not ok then ngx.log(ngx.ERR, "failed to set peer: ", err) return ngx.exit(500) end } } # 基于 Host 的多域名路由 server { listen 80; server_name api.user.example.com; return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; server_name api.user.example.com; ssl_certificate /etc/nginx/ssl/user.example.com.crt; ssl_certificate_key /etc/nginx/ssl/user.example.com.key; # JWT 认证(使用 Lua) access_by_lua_block { local jwt = require "resty.jwt" local auth_header = ngx.var.http_authorization if not auth_header then ngx.exit(401) end local token = auth_header:match("^Bearer%s+(.+)$") if not token then ngx.exit(401) end local jwt_obj = jwt:verify(os.getenv("JWT_SECRET"), token) if not jwt_obj.verified then ngx.exit(401) end -- 将用户信息设置到变量 ngx.var.user_id = jwt_obj.payload.sub ngx.var.user_role = jwt_obj.payload.role } location / { # 权限控制 if ($user_role != "user" && $user_role != "admin") { return 403; } proxy_pass http://user_service; proxy_set_header Host $host; proxy_set_header X-User-ID $user_id; proxy_set_header X-User-Role $user_role; 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; } } # Admin API(管理后台,更严格的权限控制) server { listen 443 ssl http2; server_name api.admin.example.com; ssl_certificate /etc/nginx/ssl/admin.example.com.crt; ssl_certificate_key /etc/nginx/ssl/admin.example.com.key; # IP 白名单(只允许公司内网访问) allow 10.0.0.0/8; allow 172.16.0.0/12; allow 192.168.0.0/16; deny all; # 严格的限流 limit_req zone=strict_limit burst=5 nodelay; limit_conn conn_limit 5; # 只允许管理员角色访问 set $admin_required 1; location / { if ($user_role != "admin") { return 403; } proxy_pass http://admin_service; proxy_set_header Host $host; proxy_set_header X-User-ID $user_id; proxy_set_header X-User-Role $user_role; 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; } } ``` --- ## 9. 名词对照表 | 英文术语 | 中文对照 | 解释 | | :--- | :--- | :--- | | **Reverse Proxy** | 反向代理 | 部署在服务器端,接收客户端请求并转发给内部服务器的代理服务。客户端只知道反向代理的存在,不知道真实服务器地址。 | | **Forward Proxy** | 正向代理 | 部署在客户端侧,代替客户端访问外部资源的代理服务。服务端看到的是代理的 IP,不知道真实客户端。典型应用:VPN、翻墙工具。 | | **API Gateway** | API 网关 | 位于客户端和后端服务之间的中间层,提供路由、认证、限流、日志等功能,是微服务架构的"统一大门"。 | | **Load Balancing** | 负载均衡 | 将请求流量分配到多台服务器,避免单台服务器过载,提高系统可用性和性能。 | | **Rate Limiting** | 限流 | 限制单位时间内的请求数量,防止系统被突发流量压垮。常用算法:令牌桶、漏桶、滑动窗口。 | | **Circuit Breaking** | 熔断 | 当依赖服务出现故障时,自动切断调用,防止故障扩散,并提供降级方案。 | | **SSL Termination** | SSL 终结 | 在网关层处理 HTTPS 加密解密,后端服务使用 HTTP,降低后端计算开销,简化证书管理。 | | **Health Check** | 健康检查 | 定期检查后端服务的健康状态,自动剔除故障节点,保证流量只发送到健康的服务实例。 | | **Sticky Session** | 会话保持 | 将同一客户端的请求始终路由到同一台后端服务器,用于需要保持会话状态的场景。 | | **Blue-Green Deployment** | 蓝绿部署 | 同时运行两个生产环境(蓝、绿),切换流量实现零停机发布。 | | **Canary Release** | 灰度发布 | 将少量流量导到新版本,验证稳定性后逐步扩大比例,降低发布风险。 | | **Upstream** | 上游 | 在 Nginx 配置中,指代后端服务器组。 | | **Location** | 位置块 | Nginx 中用于匹配请求 URL 并定义处理规则的配置块。 | | **Worker Process** | 工作进程 | Nginx 中实际处理请求的进程,多个 Worker 并行工作,充分利用多核 CPU。 | | **Master Process** | 主进程 | Nginx 中负责管理 Worker 进程(启动、停止、重新加载配置)的控制进程。 | | **Event-Driven** | 事件驱动 | 一种编程模型,通过监听和响应事件(如 I/O 就绪)来处理并发,Nginx 的核心架构。 | | **epoll / kqueue** | I/O 多路复用 | Linux/macOS 下的高性能 I/O 事件通知机制,允许单个进程同时处理大量连接。 | --- ## 总结:反向代理与网关的本质 经过这一章的学习,我们可以得出几个核心结论: **从实践来看**: - 反向代理解决的是"流量怎么分发"的问题,通过负载均衡、健康检查、会话保持等机制,将流量高效、可靠地送达后端服务。 - API 网关解决的是"请求怎么处理"的问题,在统一的入口点处理横切关注点(认证、限流、日志等),让后端服务专注于业务逻辑。 **从架构视角看**: - 网关是系统的"门面",所有流量都经过这里,是安全防护的第一道防线,也是性能优化的关键节点。 - 合理的网关架构,可以将单台服务器的处理能力扩展到整个集群,将单点故障风险分散到多个节点,将复杂的安全策略收敛到统一入口。 **从运维视角看**: - 证书管理、限流策略、路由规则,都应该在网关层统一配置,避免分散在各个服务。 - 监控和日志也应该在网关层统一收集,便于分析流量模式、排查问题、审计安全事件。 目标是:在给定的资源和性能约束下,让每一次请求都能被安全、高效、可靠地处理。