摘要:本文通过完整的实战项目带你掌握 Nginx 的综合应用,涵盖高可用架构、容器化部署、自动化运维、性能调优和故障演练。通过本文档,你将能够独立完成企业级 Nginx 部署和运维。
关键词:Nginx、实战项目、高可用、容器化、自动化运维、性能调优、故障演练
适合人群:有 Nginx 基础的开发者、运维工程师、架构师
阅读时间:约 60 分钟
版本信息:Nginx 1.24+ | Docker | Keepalived | Ansible
文章目录
- 1. 高可用架构
- 1.1 什么是高可用
- 1.2 Keepalived + Nginx 高可用
- 1.3 双主模式
- 2. 容器化部署
- 2.1 Docker 部署 Nginx
- 2.2 Docker Compose 部署
- 2.3 Kubernetes 部署
- 3. 自动化运维
- 3.1 Ansible 自动化部署
- 3.2 CI/CD 集成
- 4. 性能调优
- 4.1 系统级调优
- 4.2 Nginx 级调优
- 4.3 性能测试
- 5. 故障演练
- 5.1 模拟后端故障
- 5.2 模拟 Nginx 故障
- 5.3 模拟网络故障
- 6. 实战项目
- 项目 1:企业级 Web 平台部署
- 项目 2:微服务网关部署
- 项目 3:CDN 边缘节点部署
- 7. 常见问题 FAQ
- 8. 学习资源与建议
- 学习建议
- 官方资源
- 推荐工具
1. 高可用架构
1.1 什么是高可用
高可用(High Availability, HA)是指系统能够在大部分时间内正常运行,即使部分组件出现故障也不会影响整体服务。
高可用指标:
| 可用性 | 年停机时间 | 说明 |
|---|---|---|
| 99% | 3.65 天 | 基本可用 |
| 99.9% | 8.76 小时 | 较高可用 |
| 99.99% | 52.6 分钟 | 高可用 |
| 99.999% | 5.26 分钟 | 极高可用 |
1.2 Keepalived + Nginx 高可用
使用 Keepalived 实现 Nginx 主备切换:
架构说明:
VIP: 192.168.1.100 ↓ ┌─────────────┴─────────────┐ ↓ ↓ Master Nginx Backup Nginx 192.168.1.101 192.168.1.102 ↓ ↓ ┌────┴────┐ ┌────┴────┐ ↓ ↓ ↓ ↓ Backend1 Backend2 Backend1 Backend2Master 节点配置:
# 安装 Keepalivedsudoaptinstallkeepalived# 编辑配置文件sudonano/etc/keepalived/keepalived.confvrrp_script chk_nginx { script "/etc/keepalived/check_nginx.sh" interval 2 weight -20 } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.1.100 } track_script { chk_nginx } }Backup 节点配置:
vrrp_script chk_nginx { script "/etc/keepalived/check_nginx.sh" interval 2 weight -20 } vrrp_instance VI_1 { state BACKUP interface eth0 virtual_router_id 51 priority 90 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.1.100 } track_script { chk_nginx } }健康检查脚本:
#!/bin/bash# /etc/keepalived/check_nginx.sh# 检查 Nginx 是否运行if!pgrep nginx>/dev/null;then# 尝试启动 Nginxsystemctl start nginxsleep2# 再次检查if!pgrep nginx>/dev/null;then# Nginx 启动失败,停止 Keepalivedsystemctl stop keepalivedfifi# 添加执行权限chmod+x /etc/keepalived/check_nginx.sh1.3 双主模式
两个节点同时提供服务,提高资源利用率:
# 节点 1 配置 vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 priority 100 virtual_ipaddress { 192.168.1.100 } } vrrp_instance VI_2 { state BACKUP interface eth0 virtual_router_id 52 priority 90 virtual_ipaddress { 192.168.1.101 } }# 节点 2 配置 vrrp_instance VI_1 { state BACKUP interface eth0 virtual_router_id 51 priority 90 virtual_ipaddress { 192.168.1.100 } } vrrp_instance VI_2 { state MASTER interface eth0 virtual_router_id 52 priority 100 virtual_ipaddress { 192.168.1.101 } }💡提示:双主模式下,两个节点各自拥有一个 VIP,通过 DNS 轮询将请求分发到两个 VIP。
2. 容器化部署
2.1 Docker 部署 Nginx
使用 Docker 快速部署 Nginx:
# 拉取 Nginx 镜像dockerpull nginx:latest# 运行 Nginx 容器dockerrun-d\--namemy-nginx\-p80:80\-p443:443\-v/etc/nginx/nginx.conf:/etc/nginx/nginx.conf\-v/etc/nginx/conf.d:/etc/nginx/conf.d\-v/var/www/html:/usr/share/nginx/html\-v/var/log/nginx:/var/log/nginx\nginx:latest参数说明:
| 参数 | 说明 |
|---|---|
-d | 后台运行 |
--name | 容器名称 |
-p | 端口映射 |
-v | 挂载卷(持久化) |
2.2 Docker Compose 部署
使用 Docker Compose 管理多容器:
version:'3.8'services:nginx:image:nginx:latestcontainer_name:my-nginxports:-"80:80"-"443:443"volumes:-./nginx.conf:/etc/nginx/nginx.conf-./conf.d:/etc/nginx/conf.d-./html:/usr/share/nginx/html-./logs:/var/log/nginx-./certs:/etc/nginx/certsrestart:alwaysnetworks:-app-networkbackend:image:node:18-alpinecontainer_name:my-backendworking_dir:/appvolumes:-./backend:/appcommand:node server.jsexpose:-"3000"networks:-app-networknetworks:app-network:driver:bridgeNginx 配置:
upstream backend { server backend:3000; } server { listen 80; server_name example.com; location / { root /usr/share/nginx/html; index index.html; } location /api { proxy_pass http://backend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }启动服务:
# 启动所有服务docker-composeup-d# 查看服务状态docker-composeps# 查看日志docker-composelogs-fnginx# 停止服务docker-composedown2.3 Kubernetes 部署
使用 Kubernetes 部署 Nginx Ingress Controller:
apiVersion:apps/v1kind:Deploymentmetadata:name:nginx-ingressnamespace:ingress-nginxspec:replicas:2selector:matchLabels:app:nginx-ingresstemplate:metadata:labels:app:nginx-ingressspec:containers:-name:nginx-ingressimage:nginx/nginx-ingress:latestports:-containerPort:80-containerPort:443resources:requests:memory:"128Mi"cpu:"250m"limits:memory:"256Mi"cpu:"500m"---apiVersion:v1kind:Servicemetadata:name:nginx-ingressnamespace:ingress-nginxspec:type:LoadBalancerselector:app:nginx-ingressports:-name:httpport:80targetPort:80-name:httpsport:443targetPort:4433. 自动化运维
3.1 Ansible 自动化部署
使用 Ansible 自动化部署 Nginx:
目录结构:
nginx-ansible/ ├── ansible.cfg ├── inventory.ini ├── playbook.yml └── roles/ └── nginx/ ├── tasks/ │ └── main.yml ├── templates/ │ └── nginx.conf.j2 └── handlers/ └── main.ymlinventory.ini:
[webservers] 192.168.1.101 192.168.1.102 [webservers:vars] ansible_user=root ansible_ssh_private_key_file=~/.ssh/id_rsaplaybook.yml:
----name:Deploy Nginxhosts:webserversbecome:yesroles:-nginxroles/nginx/tasks/main.yml:
----name:Install Nginxapt:name:nginxstate:presentupdate_cache:yes-name:Copy Nginx configurationtemplate:src:nginx.conf.j2dest:/etc/nginx/nginx.confnotify:Restart Nginx-name:Start Nginxservice:name:nginxstate:startedenabled:yesroles/nginx/templates/nginx.conf.j2:
worker_processes {{ ansible_processor_vcpus }}; events { worker_connections {{ worker_connections | default(1024) }}; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; server_name {{ server_name | default('localhost') }}; location / { root {{ document_root | default('/usr/share/nginx/html') }}; index index.html; } } }roles/nginx/handlers/main.yml:
----name:Restart Nginxservice:name:nginxstate:restarted执行部署:
# 安装 Ansiblepipinstallansible# 执行 playbookansible-playbook-iinventory.ini playbook.yml3.2 CI/CD 集成
将 Nginx 配置集成到 CI/CD 流程:
.gitlab-ci.yml:
stages:-test-deploytest_nginx_config:stage:testimage:nginx:latestscript:-nginx-t-c /etc/nginx/nginx.confonly:-maindeploy_nginx:stage:deployimage:alpine:latestscript:-apk add--no-cache openssh-client-scp nginx.conf user@server:/etc/nginx/nginx.conf-ssh user@server "nginx-t&&nginx-s reload"only:-mainGitHub Actions:
name:Deploy Nginxon:push:branches:[main]jobs:deploy:runs-on:ubuntu-lateststeps:-uses:actions/checkout@v3-name:Test Nginx configuses:nginxinc/nginx-lint@v1with:config:nginx.conf-name:Deploy to serveruses:appleboy/scp-action@masterwith:host:${{secrets.SERVER_HOST}}username:${{secrets.SERVER_USER}}key:${{secrets.SERVER_SSH_KEY}}source:"nginx.conf"target:"/etc/nginx/"-name:Reload Nginxuses:appleboy/ssh-action@masterwith:host:${{secrets.SERVER_HOST}}username:${{secrets.SERVER_USER}}key:${{secrets.SERVER_SSH_KEY}}script:|nginx -t && nginx -s reload4. 性能调优
4.1 系统级调优
优化 Linux 系统参数:
# /etc/sysctl.conf# 增加文件描述符限制fs.file-max=65535# 增加 TCP 连接队列net.core.somaxconn=65535# 启用 TCP SYN Cookiesnet.ipv4.tcp_syncookies=1# 增加 TCP 最大连接数net.ipv4.tcp_max_syn_backlog=65535# 启用 TCP 时间戳net.ipv4.tcp_timestamps=1# 启用 TCP 快速打开net.ipv4.tcp_fastopen=3# 增加本地端口范围net.ipv4.ip_local_port_range=102465535# 启用 TCP 窗口缩放net.ipv4.tcp_window_scaling=1# 应用配置sudosysctl-p增加文件描述符限制:
# /etc/security/limits.conf* soft nofile65535* hard nofile65535root soft nofile65535root hard nofile655354.2 Nginx 级调优
优化 Nginx 配置:
worker_processes auto; worker_cpu_affinity auto; worker_rlimit_nofile 65535; events { worker_connections 65535; use epoll; multi_accept on; } http { sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; keepalive_requests 10000; # 打开文件缓存 open_file_cache max=10000 inactive=60s; open_file_cache_valid 30s; open_file_cache_min_uses 2; open_file_cache_errors on; # 客户端优化 client_body_buffer_size 10K; client_header_buffer_size 1k; client_max_body_size 10m; large_client_header_buffers 4 4k; # 超时优化 client_body_timeout 12; client_header_timeout 12; send_timeout 10; }4.3 性能测试
使用 ab 工具进行性能测试:
# 安装 absudoaptinstallapache2-utils# 基本测试ab-n10000-c100http://example.com/# 带 POST 数据测试ab-n1000-c50-ppost.txt-Tapplication/json http://example.com/api# 带 Cookie 测试ab-n1000-c50-C"session=abc123"http://example.com/输出说明:
Server Software: nginx Server Hostname: example.com Server Port: 80 Document Path: / Document Length: 612 bytes Concurrency Level: 100 Time taken for tests: 2.345 seconds Complete requests: 10000 Failed requests: 0 Total transferred: 8450000 bytes HTML transferred: 6120000 bytes Requests per second: 4264.39 [#/sec] (mean) Time per request: 23.450 [ms] (mean) Time per request: 0.235 [ms] (mean, across all concurrent requests) Transfer rate: 3517.89 [Kbytes/sec] received| 指标 | 说明 |
|---|---|
| Requests per second | 每秒请求数(越高越好) |
| Time per request | 每个请求的平均时间(越低越好) |
| Failed requests | 失败请求数(应为 0) |
| Transfer rate | 传输速率 |
使用 wrk 进行更准确的测试:
# 安装 wrksudoaptinstallwrk# 基本测试wrk-t12-c400-d30shttp://example.com/# 带 POST 数据测试wrk-t12-c400-d30s-spost.lua http://example.com/api5. 故障演练
5.1 模拟后端故障
测试 Nginx 在后端故障时的行为:
# 停止后端服务systemctl stop backend# 观察 Nginx 错误日志tail-f/var/log/nginx/error.log# 观察 Nginx 访问日志tail-f/var/log/nginx/access.log预期结果:
- Nginx 返回 502 Bad Gateway
- 错误日志显示连接被拒绝
- 如果有多个后端,请求会转发到健康的后端
5.2 模拟 Nginx 故障
测试 Keepalived 主备切换:
# 在 Master 节点停止 Nginxsystemctl stop nginx# 观察 Keepalived 日志tail-f/var/log/keepalived.log# 检查 VIP 是否漂移到 Backup 节点ipaddr show eth0预期结果:
- Keepalived 检测到 Nginx 故障
- VIP 自动漂移到 Backup 节点
- Backup 节点接管服务
5.3 模拟网络故障
测试网络延迟和丢包:
# 添加网络延迟tc qdiscadddev eth0 root netem delay 100ms# 添加丢包tc qdiscadddev eth0 root netem loss10%# 清除规则tc qdisc del dev eth0 root预期结果:
- Nginx 超时设置生效
- 请求超时后返回 504 Gateway Timeout
- 错误日志记录超时信息
6. 实战项目
项目 1:企业级 Web 平台部署
项目需求:
- 前端:Vue 3 单页应用
- 后端:Node.js API 服务
- 数据库:MySQL
- 缓存:Redis
- 高可用:Keepalived + Nginx
- 监控:Prometheus + Grafana
架构图:
用户 ↓ VIP: 192.168.1.100 ↓ ┌────────────┴────────────┐ ↓ ↓ Nginx Master Nginx Backup 192.168.1.101 192.168.1.102 ↓ ↓ ┌────┴────┐ ┌────┴────┐ ↓ ↓ ↓ ↓ Node.js1 Node.js2 Node.js1 Node.js2 ↓ ↓ ↓ ↓ └────┬────┘ └────┬────┘ ↓ ↓ ┌────┴────────────────────────┴────┐ ↓ ↓ MySQL Master Redis Cluster 192.168.1.200 192.168.1.201-203Nginx 配置:
worker_processes auto; worker_cpu_affinity auto; worker_rlimit_nofile 65535; events { worker_connections 65535; use epoll; multi_accept on; } http { include mime.types; default_type application/octet-stream; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; keepalive_requests 10000; # Gzip 压缩 gzip on; gzip_comp_level 5; gzip_min_length 1k; gzip_types text/plain text/css application/json application/javascript text/xml application/xml; # 限流配置 limit_req_zone $binary_remote_addr zone=api_limit:10m rate=20r/s; limit_conn_zone $binary_remote_addr zone=conn_limit:10m; # 代理缓存 proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=api_cache:10m max_size=1g inactive=60m; # 后端服务器 upstream node_backend { server 192.168.1.110:3000 max_fails=3 fail_timeout=30s; server 192.168.1.111:3000 max_fails=3 fail_timeout=30s; server 192.168.1.112:3000 max_fails=3 fail_timeout=30s backup; keepalive 32; } # HTTP 重定向到 HTTPS server { listen 80; server_name example.com www.example.com; return 301 https://$host$request_uri; } # HTTPS 服务器 server { listen 443 ssl http2; server_name example.com www.example.com; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; # 安全头 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 Strict-Transport-Security "max-age=31536000; includeSubDomains" always; # 前端静态文件 root /var/www/my-app/dist; index index.html; location / { try_files $uri $uri/ /index.html; } # 静态资源缓存 location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2)$ { expires 1y; add_header Cache-Control "public, immutable"; } # 后端 API 代理 location /api { limit_req zone=api_limit burst=50 nodelay; limit_conn conn_limit 20; proxy_cache api_cache; proxy_cache_valid 200 5m; proxy_cache_valid 404 1m; add_header X-Cache-Status $upstream_cache_status; proxy_pass http://node_backend; proxy_http_version 1.1; proxy_set_header Connection ""; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } # 状态监控 location /nginx_status { stub_status on; access_log off; allow 127.0.0.1; allow 10.0.0.0/8; deny all; } # 日志 access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log warn; } }部署步骤:
# 1. 安装 Nginxsudoaptinstallnginx# 2. 安装 Keepalivedsudoaptinstallkeepalived# 3. 配置 Nginxsudocpnginx.conf /etc/nginx/nginx.conf# 4. 配置 Keepalivedsudocpkeepalived.conf /etc/keepalived/keepalived.conf# 5. 测试配置sudonginx-t# 6. 启动服务sudosystemctl start nginxsudosystemctl start keepalived# 7. 设置开机自启sudosystemctlenablenginxsudosystemctlenablekeepalived项目 2:微服务网关部署
项目需求:
- 用户服务:192.168.1.110:3001
- 订单服务:192.168.1.111:4001
- 商品服务:192.168.1.112:5001
- 认证服务:192.168.1.113:6001
Nginx 配置:
upstream user_service { server 192.168.1.110:3001; server 192.168.1.110:3002; } upstream order_service { server 192.168.1.111:4001; server 192.168.1.111:4002; } upstream product_service { server 192.168.1.112:5001; server 192.168.1.112:5002; } upstream auth_service { server 192.168.1.113:6001; } server { listen 80; server_name gateway.example.com; # 认证服务 location /auth { proxy_pass http://auth_service; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # 用户服务 location /api/users { # 验证 Token auth_request /auth/verify; proxy_pass http://user_service; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # 订单服务 location /api/orders { auth_request /auth/verify; 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; } }项目 3:CDN 边缘节点部署
项目需求:
- 缓存静态资源
- 回源到源站
- 防盗链
- 限流
Nginx 配置:
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=cdn_cache:10m max_size=10g inactive=7d; server { listen 80; server_name cdn.example.com; # 防盗链 valid_referers none blocked server_names *.example.com; location / { # 启用缓存 proxy_cache cdn_cache; proxy_cache_valid 200 7d; proxy_cache_valid 404 1m; proxy_cache_key $scheme$request_method$host$request_uri; # 添加缓存头 add_header X-Cache-Status $upstream_cache_status; add_header Cache-Control "public, max-age=604800"; # 防盗链 if ($invalid_referer) { return 403; } # 回源 proxy_pass http://origin.example.com; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # 限流 location /download { limit_rate 500k; proxy_cache cdn_cache; proxy_cache_valid 200 7d; proxy_pass http://origin.example.com; } }7. 常见问题 FAQ
Q1:如何实现 Nginx 高可用?
A:使用 Keepalived 实现主备切换:
# 安装 Keepalivedsudoaptinstallkeepalived# 配置虚拟 IP# 主节点 priority 100,备节点 priority 90Q2:如何使用 Docker 部署 Nginx?
A:使用以下命令:
dockerrun-d\--namemy-nginx\-p80:80\-v/etc/nginx/nginx.conf:/etc/nginx/nginx.conf\-v/var/www/html:/usr/share/nginx/html\nginx:latestQ3:如何自动化部署 Nginx?
A:使用 Ansible:
# 编写 playbookansible-playbook-iinventory.ini playbook.ymlQ4:如何优化 Nginx 性能?
A:从以下几个方面优化:
- 系统级:增加文件描述符、TCP 参数调优
- Nginx 级:worker_processes、worker_connections、open_file_cache
- 应用级:Gzip 压缩、缓存配置、连接池
Q5:如何进行故障演练?
A:模拟以下场景:
- 后端故障:停止后端服务
- Nginx 故障:停止 Nginx,观察 Keepalived 切换
- 网络故障:使用 tc 添加延迟和丢包
8. 学习资源与建议
学习建议
1.先掌握基础,再学习实战:确保理解基础配置后再进行实战项目
2.多查看官方文档:官方文档是最权威的资料
3.善用测试命令:每次修改配置后,先用nginx -t测试语法
4.查看日志排错:遇到问题时,查看错误日志是最快的排错方法
5.使用版本控制:配置文件使用 Git 管理,方便回滚和对比
官方资源
- Nginx 官方文档
- Keepalived 官方文档
- Docker 官方文档
- Ansible 官方文档
- Prometheus 官方文档
推荐工具
- SSL Labs - SSL 配置测试
- GTmetrix - 网站性能测试
- wrk - HTTP 性能测试工具
- ab - Apache Bench 性能测试