第九章 缓存机制9.1 浏览器缓存expires# 方式一expires 指令 location ~* \.(jpg|png|gif|css|js)$ { expires 30d; # 30天过期 } # 方式二Cache-Control更灵活推荐 location ~* \.(css|js)$ { add_header Cache-Control public, max-age2592000, immutable; } # 不缓存动态内容 location /api/ { add_header Cache-Control no-store, no-cache, must-revalidate; add_header Pragma no-cache; }缓存策略建议资源类型策略说明HTMLno-cache每次验证保证最新CSS/JS带hashimmutable, max-age1y文件名含hash永久缓存图片/字体max-age30d较长缓存API 响应no-store禁止缓存9.2 代理缓存proxy_cachehttp { # 定义缓存区域 proxy_cache_path /var/cache/nginx levels1:2 # 目录层级 keys_zonemy_cache:10m # 共享内存区域存key max_size10g # 磁盘最大缓存 inactive60m # 60分钟未访问则清除 use_temp_pathoff; # 不使用临时路径 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 NginxClient → CDN 边缘节点 → Nginx 源站 → App ServerCDN 缓存静态资源减少源站压力。Nginx 作为源站负责动态内容和回源策略。# 源站配置设置 CDN 友好的缓存头 location ~* \.(css|js|jpg|png)$ { add_header Cache-Control public, max-age31536000; add_header CDN-Cache-Control max-age86400; # CDN 专用缓存头 }10.6 高可用KeepalivedVIP: 192.168.1.100 ┌──────────┐ │ 虚拟 IP │ └────┬─────┘ ┌───────┴───────┐ ▼ ▼ ┌─────────────┐ ┌─────────────┐ │ Nginx Master│ │ Nginx Backup│ │ (MASTER) │ │ (BACKUP) │ │ 优先级 100 │ │ 优先级 90 │ └─────────────┘ └─────────────┘ Master 宕机 → VIP 自动漂移到 Backup# /etc/keepalived/keepalived.confMaster 节点vrrp_script check_nginx{script/usr/bin/killall -0 nginxinterval2weight-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 valid300s;11.2 防 DDoS# 连接级限制 limit_conn_zone $binary_remote_addr zoneddos_conn:10m; limit_conn ddos_conn 50; # 每 IP 50 连接 # 请求级限制 limit_req_zone $binary_remote_addr zoneddos_req:10m rate30r/s; limit_req zoneddos_req burst50 nodelay;11.3 防 CC 攻击# 针对特定接口严格限流 location /api/login { limit_req zonestrict_limit burst5 nodelay; # 每秒2次 # 验证 User-Agent拦截简单爬虫 if ($http_user_agent ~* curl|wget|python|scrapy) { return 403; } }11.4 安全 Headerserver { # 防止点击劫持 add_header X-Frame-Options SAMEORIGIN always; # 防止 MIME 类型嗅探 add_header X-Content-Type-Options nosniff always; # XSS 防护 add_header X-XSS-Protection 1; modeblock always; # HSTS add_header Strict-Transport-Security max-age31536000; 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-tnginx-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.8services:nginx:image:nginx:1.24-alpineports:-80:80-443:443volumes:-./nginx.conf:/etc/nginx/nginx.conf:ro-./conf.d:/etc/nginx/conf.d:ro-./ssl:/etc/nginx/ssl:ro-./logs:/var/log/nginxrestart:unless-stopped12.5 Kubernetes 部署# Ingress ControllerK8s 中 Nginx 的典型用法apiVersion:networking.k8s.io/v1kind:Ingressmetadata:name:app-ingressannotations:nginx.ingress.kubernetes.io/rewrite-target:/nginx.ingress.kubernetes.io/ssl-redirect:truespec: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-9PID# 或修改 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 限制CentOSgetenforce 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.8valid30s;set$backendhttp://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 OpenRestyLuaOpenResty 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 zoneapi burst20 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/3QUICNginx 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; ma86400; # 告知浏览器支持 HTTP/3 # 开启 0-RTT加速连接建立 ssl_early_data on; }14.5 模块开发// 自定义模块基本结构C 语言#includengx_config.h#includengx_core.h#includengx_http.hstaticngx_int_tngx_http_hello_handler(ngx_http_request_t*r){ngx_str_tresponsengx_string(Hello from custom module!);r-headers_out.statusNGX_HTTP_OK;r-headers_out.content_length_nresponse.len;ngx_http_send_header(r);ngx_buf_t*bngx_create_temp_buf(r-pool,response.len);ngx_memcpy(b-pos,response.data,response.len);b-lastb-posresponse.len;b-last_buf1;ngx_chain_tout{.bufb,.nextNULL};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 → NginxSSL终端 静态资源 负载均衡 → TomcatJava 应用15.3 Nginx vs Envoy维度NginxEnvoy开发语言CC配置方式静态文件动态 APIxDS服务发现需第三方原生支持可观测性基础丰富分布式追踪、指标热更新reload微秒级中断热重启零中断适用场景通用 Web/反向代理/LBService MeshIstio Sidecar选型建议传统 Web 项目Nginx成熟稳定、资料丰富云原生/Service MeshEnvoyIstio 默认 Sidecar需要 Lua 扩展OpenRestyNginx 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/svgxml; # ── 安全 ── server_tokens off; add_header X-Frame-Options SAMEORIGIN always; add_header X-Content-Type-Options nosniff always; # ── 限流 ── limit_req_zone $binary_remote_addr zoneglobal:10m rate30r/s; limit_conn_zone $binary_remote_addr zoneconn:10m; # ── 缓存 ── proxy_cache_path /var/cache/nginx levels1:2 keys_zonecache:10m max_size5g inactive60m; # ── 引入站点配置 ── include /etc/nginx/conf.d/*.conf; }