当前位置: 首页 > news >正文

Nginx 知识体系 · 下篇:高级与实战


第九章 缓存机制

9.1 浏览器缓存(expires)

# 方式一:expires 指令 location ~* \.(jpg|png|gif|css|js)$ { expires 30d; # 30天过期 } # 方式二:Cache-Control(更灵活,推荐) location ~* \.(css|js)$ { add_header Cache-Control "public, max-age=2592000, immutable"; } # 不缓存动态内容 location /api/ { add_header Cache-Control "no-store, no-cache, must-revalidate"; add_header Pragma "no-cache"; }

缓存策略建议

资源类型策略说明
HTMLno-cache每次验证,保证最新
CSS/JS(带hash)immutable, max-age=1y文件名含hash,永久缓存
图片/字体max-age=30d较长缓存
API 响应no-store禁止缓存

9.2 代理缓存(proxy_cache)

http { # 定义缓存区域 proxy_cache_path /var/cache/nginx levels=1:2 # 目录层级 keys_zone=my_cache:10m # 共享内存区域(存key) max_size=10g # 磁盘最大缓存 inactive=60m # 60分钟未访问则清除 use_temp_path=off; # 不使用临时路径 server { location / { proxy_pass http://backend; proxy_cache my_cache; proxy_cache_valid 200 301 302 10m; # 成功响应缓存10分钟 proxy_cache_valid 404 1m; # 404 缓存1分钟 proxy_cache_key "$scheme$host$request_uri"; # 添加缓存状态头(调试用) add_header X-Cache-Status $upstream_cache_status; # 值:HIT / MISS / EXPIRED / BYPASS / STALE } } }

9.3 缓存控制策略

# 指定条件绕过缓存 proxy_cache_bypass $http_cache_control $cookie_nocache; # 指定不缓存的条件 proxy_no_cache $arg_nocache $http_pragma; # 后端宕机时使用过期缓存(容灾) proxy_cache_use_stale error timeout updating http_500 http_502 http_503; # 缓存锁(防止缓存击穿) proxy_cache_lock on; proxy_cache_lock_timeout 5s; # 手动清除缓存(需要 ngx_cache_purge 模块) location ~ /purge(/.*) { allow 127.0.0.1; deny all; proxy_cache_purge my_cache "$scheme$host$1"; }

第十章 架构设计

10.1 单机部署

Client → Nginx → 本机应用(Node/Java/Python)

最简单的部署方式,适合小型项目和开发环境。

10.2 反向代理架构

┌────────────────┐ Client ──→ Nginx ──→│ App Server │ │ (单台后端) │ └────────────────┘

适合中小型项目,Nginx 负责 SSL 终端、静态资源、请求转发。

10.3 负载均衡架构

┌─── App Server 1 Client ──→ Nginx ──┤─── App Server 2 (LB) └─── App Server 3

水平扩展,Nginx 按策略分发流量。

10.4 微服务网关架构

┌─────────────┐ │ Nginx 网关 │ │ (路由/鉴权) │ └──┬──┬──┬────┘ │ │ │ ┌──────┘ │ └──────┐ ▼ ▼ ▼ ┌────────┐┌────────┐┌────────┐ │用户服务 ││商品服务 ││订单服务 │ └────────┘└────────┘└────────┘
# 微服务网关配置示例 upstream user_service { server 10.0.1.1:8001; server 10.0.1.2:8001; } upstream product_service { server 10.0.2.1:8002; server 10.0.2.2:8002; } upstream order_service { server 10.0.3.1:8003; server 10.0.3.2:8003; } server { listen 443 ssl; location /api/user/ { proxy_pass http://user_service; } location /api/product/ { proxy_pass http://product_service; } location /api/order/ { proxy_pass http://order_service; } }

10.5 CDN + Nginx

Client → CDN 边缘节点 → Nginx 源站 → App Server

CDN 缓存静态资源,减少源站压力。Nginx 作为源站负责动态内容和回源策略。

# 源站配置:设置 CDN 友好的缓存头 location ~* \.(css|js|jpg|png)$ { add_header Cache-Control "public, max-age=31536000"; add_header CDN-Cache-Control "max-age=86400"; # CDN 专用缓存头 }

10.6 高可用(Keepalived)

VIP: 192.168.1.100 ┌──────────┐ │ 虚拟 IP │ └────┬─────┘ ┌───────┴───────┐ ▼ ▼ ┌─────────────┐ ┌─────────────┐ │ Nginx Master│ │ Nginx Backup│ │ (MASTER) │ │ (BACKUP) │ │ 优先级 100 │ │ 优先级 90 │ └─────────────┘ └─────────────┘ Master 宕机 → VIP 自动漂移到 Backup
# /etc/keepalived/keepalived.conf(Master 节点)vrrp_script check_nginx{script"/usr/bin/killall -0 nginx"interval2weight-20}vrrp_instance VI_1{state MASTER interface eth0 virtual_router_id51priority100advert_int1virtual_ipaddress{192.168.1.100}track_script{check_nginx}}

第十一章 安全体系

11.1 HTTPS 安全加固

# TLS 安全最佳实践 ssl_protocols TLSv1.2 TLSv1.3; # 禁用旧协议 ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; ssl_prefer_server_ciphers on; ssl_ecdh_curve X25519:P-256; # OCSP Stapling(加速证书验证) ssl_stapling on; ssl_stapling_verify on; resolver 8.8.8.8 valid=300s;

11.2 防 DDoS

# 连接级限制 limit_conn_zone $binary_remote_addr zone=ddos_conn:10m; limit_conn ddos_conn 50; # 每 IP 50 连接 # 请求级限制 limit_req_zone $binary_remote_addr zone=ddos_req:10m rate=30r/s; limit_req zone=ddos_req burst=50 nodelay;

11.3 防 CC 攻击

# 针对特定接口严格限流 location /api/login { limit_req zone=strict_limit burst=5 nodelay; # 每秒2次 # 验证 User-Agent(拦截简单爬虫) if ($http_user_agent ~* "curl|wget|python|scrapy") { return 403; } }

11.4 安全 Header

server { # 防止点击劫持 add_header X-Frame-Options "SAMEORIGIN" always; # 防止 MIME 类型嗅探 add_header X-Content-Type-Options "nosniff" always; # XSS 防护 add_header X-XSS-Protection "1; mode=block" always; # HSTS add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; # CSP 内容安全策略 add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'" always; # 隐藏 Nginx 版本号 server_tokens off; }

11.5 限流与黑名单

# 使用 geo 模块定义黑名单 geo $blocked_ip { default 0; 1.2.3.4 1; 5.6.7.0/24 1; } server { if ($blocked_ip) { return 444; # 直接关闭连接,不返回任何内容 } } # 或使用外部文件 # include /etc/nginx/blocklist.conf;

第十二章 运维与部署

12.1 配置热更新

# 平滑重载(不中断服务)nginx-t&&nginx-sreload# 原理:# 1. Master 读取新配置# 2. 启动新的 Worker 进程# 3. 旧 Worker 处理完当前请求后退出# 4. 全程不中断已建立的连接

12.2 滚动发布

upstream backend { server 10.0.0.1:8080; # 先更新这台 server 10.0.0.2:8080; server 10.0.0.3:8080; } # 滚动流程: # 1. 标记 server1 为 down → reload # 2. 更新 server1 应用 # 3. 恢复 server1 → reload # 4. 对 server2、server3 重复

12.3 灰度发布

upstream stable { server 10.0.0.1:8080; } upstream canary { server 10.0.0.2:8080; } # 方式一:按 Cookie map $cookie_version $backend { "canary" canary; default stable; } # 方式二:按 IP 百分比 split_clients "$remote_addr" $backend { 10% canary; # 10% 流量到金丝雀 * stable; # 90% 流量到稳定版 } server { location / { proxy_pass http://$backend; } }

12.4 Docker 部署

# Dockerfile FROM nginx:1.24-alpine COPY nginx.conf /etc/nginx/nginx.conf COPY conf.d/ /etc/nginx/conf.d/ COPY html/ /usr/share/nginx/html/ EXPOSE 80 443
# docker-compose.ymlversion:'3.8'services:nginx:image:nginx:1.24-alpineports:-"80:80"-"443:443"volumes:-./nginx.conf:/etc/nginx/nginx.conf:ro-./conf.d:/etc/nginx/conf.d:ro-./ssl:/etc/nginx/ssl:ro-./logs:/var/log/nginxrestart:unless-stopped

12.5 Kubernetes 部署

# Ingress Controller(K8s 中 Nginx 的典型用法)apiVersion:networking.k8s.io/v1kind:Ingressmetadata:name:app-ingressannotations:nginx.ingress.kubernetes.io/rewrite-target:/nginx.ingress.kubernetes.io/ssl-redirect:"true"spec:ingressClassName:nginxtls:-hosts:[app.example.com]secretName:app-tlsrules:-host:app.example.comhttp:paths:-path:/apipathType:Prefixbackend:service:name:api-serviceport:number:8080-path:/pathType:Prefixbackend:service:name:web-serviceport:number:80

第十三章 故障排查

13.1 启动失败

# 检查配置语法nginx-t# 常见原因:# - 配置文件语法错误(缺少分号、括号不匹配)# - 端口被占用(见13.2)# - 权限不足(80端口需要root)# - 证书文件路径错误或证书过期

13.2 端口占用

# 查看端口占用sudolsof-i:80sudonetstat-tlnp|grep:80sudoss-tlnp|grep:80# 终止占用进程sudokill-9<PID># 或修改 Nginx 监听端口

13.3 403 错误

# 排查清单:# 1. 文件权限:Nginx Worker 用户是否有读权限ls-la/var/www/html/chmod-R755/var/www/html/chown-Rnginx:nginx /var/www/html/# 2. SELinux 限制(CentOS)getenforce setsebool-Phttpd_read_user_content1# 或临时关闭:setenforce 0# 3. 没有 index 文件且未开启 autoindex# 4. allow/deny 规则拦截

13.4 404 错误

# 排查清单:# 1. root 路径配置错误# 2. location 匹配不到# 3. try_files 配置问题(SPA 应用常见)# 4. proxy_pass URI 拼接错误(带不带 / 的区别)# 调试:开启 debug 日志error_log /var/log/nginx/error.log debug;

13.5 502 / 504 错误

# 502 Bad Gateway:后端服务没响应# 排查:# 1. 后端服务是否启动curlhttp://127.0.0.1:8080/health# 2. upstream 地址是否正确# 3. 后端服务是否崩溃(查看后端日志)# 504 Gateway Timeout:后端响应超时# 解决:调大超时时间proxy_connect_timeout 60s;proxy_read_timeout 120s;proxy_send_timeout 60s;

13.6 域名解析问题

# 检查 DNS 解析nslookupexample.comdigexample.com# Nginx 中使用域名做 upstream 时的坑:# Nginx 启动时解析一次 DNS,之后不再更新!# 解决方案:resolver8.8.8.8valid=30s;set$backend"http://dynamic-host.example.com";proxy_pass$backend;# 使用变量才会触发动态解析

13.7 性能瓶颈分析

# 查看 Nginx 连接状态curlhttp://localhost/nginx_status# 查看系统资源top-p$(pgrep -d, nginx)# CPU/内存ss-s# 连接统计ulimit-n# 文件描述符上限# 常见瓶颈及解决:# - worker_connections 不够 → 增大# - 文件描述符不够 → ulimit -n 65535# - CPU 满 → 检查 gzip level、正则匹配# - 内存不够 → 减小 buffer、限制缓存大小# - 磁盘 I/O → 开启 sendfile、使用 SSD

第十四章 进阶扩展

14.1 OpenResty(Lua)

OpenResty = Nginx + LuaJIT,支持在 Nginx 中嵌入 Lua 代码,实现复杂业务逻辑。

# 使用 Lua 实现动态限流 location /api/ { access_by_lua_block { local limit = require "resty.limit.req" local lim, err = limit.new("my_limit", 100, 50) local delay, err = lim:incoming(ngx.var.remote_addr, true) if not delay then return ngx.exit(429) end } proxy_pass http://backend; } # 使用 Lua 操作 Redis location /cache { content_by_lua_block { local redis = require "resty.redis" local red = redis:new() red:connect("127.0.0.1", 6379) local val = red:get("my_key") ngx.say(val) } }

Lua 执行阶段

阶段指令用途
rewriterewrite_by_luaURL 重写
accessaccess_by_lua鉴权、限流
contentcontent_by_lua生成响应内容
loglog_by_lua自定义日志
header_filterheader_filter_by_lua修改响应头
body_filterbody_filter_by_lua修改响应体

14.2 动态配置

# 使用 Consul + consul-template 动态更新 upstream # consul-template 模板: upstream backend { {{range service "web"}} server {{.Address}}:{{.Port}}; {{end}} } # 或使用 Nginx Plus 的动态 upstream API # 或使用 OpenResty + lua-resty-dns 动态解析

14.3 API 网关实现

# 完整的 API 网关配置 server { listen 443 ssl; # 统一鉴权 location /api/ { access_by_lua_block { local token = ngx.req.get_headers()["Authorization"] if not token then return ngx.exit(401) end -- 验证 JWT token... } # 限流 limit_req zone=api burst=20 nodelay; # 路由转发 location /api/user/ { proxy_pass http://user_svc; } location /api/order/ { proxy_pass http://order_svc; } location /api/product/ { proxy_pass http://product_svc; } } }

14.4 HTTP/2 与 HTTP/3

# HTTP/2(需要 HTTPS) server { listen 443 ssl http2; # http2_push /css/style.css; # Server Push(已被弃用) # http2_max_concurrent_streams 128; } # HTTP/3(QUIC,Nginx 1.25+) server { listen 443 ssl; listen 443 quic reuseport; # QUIC 监听 ssl_protocols TLSv1.3; # HTTP/3 要求 TLS 1.3 add_header Alt-Svc 'h3=":443"; ma=86400'; # 告知浏览器支持 HTTP/3 # 开启 0-RTT(加速连接建立) ssl_early_data on; }

14.5 模块开发

// 自定义模块基本结构(C 语言)#include<ngx_config.h>#include<ngx_core.h>#include<ngx_http.h>staticngx_int_tngx_http_hello_handler(ngx_http_request_t*r){ngx_str_tresponse=ngx_string("Hello from custom module!");r->headers_out.status=NGX_HTTP_OK;r->headers_out.content_length_n=response.len;ngx_http_send_header(r);ngx_buf_t*b=ngx_create_temp_buf(r->pool,response.len);ngx_memcpy(b->pos,response.data,response.len);b->last=b->pos+response.len;b->last_buf=1;ngx_chain_tout={.buf=b,.next=NULL};returnngx_http_output_filter(r,&out);}

常用第三方模块:

模块功能
ngx_cache_purge手动清除缓存
ngx_brotliBrotli 压缩(比 gzip 更优)
headers-more灵活操作 HTTP 头
lua-nginx-module嵌入 Lua 脚本
njs嵌入 JavaScript

第十五章 对比与选型

15.1 Nginx vs Apache

维度NginxApache
架构事件驱动,异步非阻塞进程/线程模型(prefork/worker)
并发能力数万级千级
内存消耗极低较高
静态文件极快较慢
动态内容需反代到后端直接集成(mod_php)
.htaccess❌ 不支持✅ 支持
模块加载编译时确定(动态模块需重编译)运行时动态加载
适用场景高并发、反向代理、负载均衡传统 PHP 项目、共享主机

结论:新项目首选 Nginx;老旧 PHP 项目或需要.htaccess时用 Apache。

15.2 Nginx vs Tomcat

维度NginxTomcat
定位Web Server / 反向代理Java Servlet 容器
静态文件极强较弱
动态内容不直接处理运行 Java 应用
并发能力数万级数百到数千

典型组合Client → Nginx(SSL终端 + 静态资源 + 负载均衡) → Tomcat(Java 应用)

15.3 Nginx vs Envoy

维度NginxEnvoy
开发语言CC++
配置方式静态文件动态 API(xDS)
服务发现需第三方原生支持
可观测性基础丰富(分布式追踪、指标)
热更新reload(微秒级中断)热重启(零中断)
适用场景通用 Web/反向代理/LBService Mesh(Istio Sidecar)

选型建议

  • 传统 Web 项目:Nginx(成熟稳定、资料丰富)
  • 云原生/Service Mesh:Envoy(Istio 默认 Sidecar)
  • 需要 Lua 扩展:OpenResty(Nginx + Lua)
  • 需要商业支持:Nginx Plus

附录:生产环境完整配置模板

# /etc/nginx/nginx.conf user nginx; worker_processes auto; worker_rlimit_nofile 65535; error_log /var/log/nginx/error.log warn; pid /run/nginx.pid; events { worker_connections 65535; multi_accept on; use epoll; } http { include mime.types; default_type application/octet-stream; # ── 日志 ── log_format main '$remote_addr - [$time_local] "$request" ' '$status $body_bytes_sent $request_time'; access_log /var/log/nginx/access.log main; # ── 性能 ── sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; keepalive_requests 1000; # ── 压缩 ── gzip on; gzip_vary on; gzip_min_length 1k; gzip_comp_level 4; gzip_types text/plain text/css application/json application/javascript text/xml image/svg+xml; # ── 安全 ── server_tokens off; add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; # ── 限流 ── limit_req_zone $binary_remote_addr zone=global:10m rate=30r/s; limit_conn_zone $binary_remote_addr zone=conn:10m; # ── 缓存 ── proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=cache:10m max_size=5g inactive=60m; # ── 引入站点配置 ── include /etc/nginx/conf.d/*.conf; }

http://www.jsqmd.com/news/688777/

相关文章:

  • 从一道CTF题深入理解PHP文件包含漏洞:绕过过滤与伪协议利用详解
  • 从问题到解决方案:AB Download Manager插件开发的架构思维与实践指南
  • 从GPIO寄存器到流水灯:手把手教你玩转DSP F28335的GPIO配置(附完整代码)
  • 深度解析开源项目:Windows多显示器DPI精准控制的实战指南
  • 从注解到链路:揭秘@DubboReference与@DubboService的微服务通信全貌
  • VTJ 项目模型架构深度评测:从协议定义到全链路协同
  • STM32CubeMX新手避坑指南:从时钟配置到GPIO点灯,一次搞定F407ZGT6工程创建
  • 从一次线上BUG复盘说起:strict-origin-when-cross-origin如何影响你的第三方登录与支付回调
  • 不止于GET请求:用编译好的libcurl静态库实现一个简易的Windows HTTP客户端工具
  • 2026届学术党必备的六大降AI率助手实际效果
  • 终极指南:如何使用QMK Toolbox轻松刷写机械键盘固件
  • RK3588 MIPI屏幕点不亮?别慌!用这份DTS屏参调试清单快速排错
  • 华为OD机试前必看:在家考还是去公司?摄像头、网络、IDE环境保姆级避坑指南
  • 靠“咬牙死扛”撑下去的努力,其实最不堪一击
  • 5分钟彻底清理Windows系统:Bulk Crap Uninstaller终极卸载神器使用指南
  • 不只是测试!Win11麦克风设置进阶指南:让会议录音清晰度翻倍
  • 指南:从零到一,掌握Python虚拟环境的核心操作与最佳实践
  • 从Google KDD 2018论文到线上A/B测试:MMoE多任务模型在亿级用户推荐场景的落地复盘
  • VSCode日志分析插件开发终极手册(2026 LTS版深度适配):支持TB级日志秒级检索、智能模式识别与AI异常聚类
  • 智能机器人赋能锂电智造:工业场景化应用与落地实践—— 成都数智碳合机器人智能取送样系统,重塑锂电材料样品转运新生态
  • 单元测试守护神:pytest框架下的代码质量保障
  • 算法训练营第十天|26.删除有序数组中的重复项
  • AZ音乐下载器完整指南:一站式解决音乐下载难题
  • 保姆级避坑指南:高通CamX/CHI中VendorTag的三种类型(hw/component/core)到底该怎么选?
  • Windows电脑C盘满了怎么办?三招教你无损清理!
  • 别再只用jstack了!JDK自带的JMC(Java Mission Control)实战:5分钟搞定线上应用性能监控与JFR分析
  • 别再瞎调参数了!手把手教你用Fluent VOF模型搞定水沸腾模拟(附避坑指南)
  • 3分钟搞定清华风格PPT:告别答辩季的模板焦虑
  • 深入x64分页机制:手写代码实现PTE/PDE遍历与物理页拷贝(为自定义Hook打基础)
  • 掌握Multi-Agent架构:提升大模型应用效率的5种编排模式(收藏学习)