← Lesson 0012 讲了协议原理。这一课把理论落到 Nginx 配置和真实场景。
Lesson 0007 讲了基础反代。现在上生产级配置:
# /etc/nginx/sites-available/myapp —— 生产级配置
upstream app_backend {
least_conn; # 最少连接数算法(默认是轮询)
server 127.0.0.1:3000 max_fails=3 fail_timeout=30s; # 3次失败后摘除30秒
server 127.0.0.1:3001 max_fails=3 fail_timeout=30s;
server 10.0.0.5:3000 backup; # 备用服务器,只在其他都挂了才用
keepalive 32; # 保持 32 个到后端的空闲连接
}
server {
listen 80;
server_name example.com;
# 限流:每个 IP 每秒最多 10 个请求
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
limit_req zone=mylimit burst=20 nodelay;
# 限并发:每个 IP 最多 5 个并发连接
limit_conn_zone $binary_remote_addr zone=connlimit:10m;
limit_conn connlimit 5;
# 静态文件直接返回(不转发到后端)
location /static/ {
alias /var/www/static/;
expires 30d;
add_header Cache-Control "public, immutable";
}
# API 请求转发到后端
location /api/ {
proxy_pass http://app_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;
# 超时配置
proxy_connect_timeout 5s; # 连后端超时
proxy_read_timeout 30s; # 读后端响应超时
proxy_send_timeout 10s; # 发请求给后端超时
}
# 健康检查端点(不记日志)
location /health {
access_log off;
return 200 "OK";
}
}
| 算法 | Nginx 指令 | 适用场景 |
|---|---|---|
| 轮询(默认) | — | 后端服务器性能相同 |
| 加权轮询 | server ... weight=3; | 服务器性能不同 |
| 最少连接 | least_conn; | 请求处理时间不均匀 |
| IP Hash | ip_hash; | 需要会话保持(同一 IP 总到同一台) |
DNS 层 Route53 / Cloudflare → 把域名解析到不同 IP(最简单,但切换慢)
L4 (TCP) Nginx stream / HAProxy → 只看 IP+端口,不看内容。性能最高
L7 (HTTP) Nginx http / Traefik → 看 URL、Header、Cookie 做路由。最灵活
CDN = 把静态文件缓存在离用户最近的边缘节点。
用户在北京 → 北京边缘节点(有缓存)→ 直接返回 ✈️ 快
用户在北京 → 北京边缘节点(无缓存)→ 回源到你的服务器 → 缓存后返回
关键配置:
public, max-age=86400 → CDN 缓存 24 小时# 1. 从用户侧开始
curl -w "DNS:%{time_namelookup}s TCP:%{time_connect}s TLS:%{time_appconnect}s FirstByte:%{time_starttransfer}s Total:%{time_total}s\n" -o /dev/null -s https://example.com
# 2. 看服务器负载
ssh server "uptime; free -h; iostat -x 1 3"
# 3. 看 Nginx 访问日志——找慢请求
awk '$NF > 3 {print $0}' /var/log/nginx/access.log # 响应时间 > 3 秒的
# 4. 看数据库慢查询(如果有的话)
# MySQL: SHOW FULL PROCESSLIST; 或 slow query log
# 1. 确认后端是否活着
ss -tlnp | grep 3000
curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:3000/health
# 2. 看 Nginx 错误日志
tail -100 /var/log/nginx/error.log | grep "upstream"
# 3. 检查是不是连接数爆了
ss -s # 看总连接数
# 如果大量 TIME_WAIT → 调内核参数或启用 keepalive
# 4. 检查文件描述符限制
cat /proc/$(pgrep nginx | head -1)/limits | grep "open files"
# 从外到内排查
ping -c 3 server-ip # 1. 机器活着吗?
nc -zv server-ip 80 # 2. 端口开着吗?
# 如果是云服务器:
# 3. 检查安全组/防火墙是否放行 80
# 4. 检查服务是否绑在 0.0.0.0 而不是 127.0.0.1
sudo ss -tlnp | grep :80 # 0.0.0.0:80 = 对外监听,127.0.0.1:80 = 只本地
用 Docker 搭两个后端 + Nginx 负载均衡:
mkdir /tmp/lb-demo && cd /tmp/lb-demo
# docker-compose.yml: Nginx + 2 个 Node.js 后端
cat > docker-compose.yml << 'EOF'
services:
nginx:
image: nginx:alpine
ports: ["8080:80"]
volumes: ["./nginx.conf:/etc/nginx/conf.d/default.conf"]
backend1:
image: node:22-alpine
command: node -e "require('http').createServer((q,r)=>{r.end('Server 1\\n')}).listen(3000)"
backend2:
image: node:22-alpine
command: node -e "require('http').createServer((q,r)=>{r.end('Server 2\\n')}).listen(3000)"
EOF
cat > nginx.conf << 'EOF'
upstream backends { server backend1:3000; server backend2:3000; }
server {
listen 80;
location / { proxy_pass http://backends; }
}
EOF
docker compose up -d
# 多次 curl,看到轮询返回 Server 1 和 Server 2
for i in 1 2 3 4; do curl -s http://localhost:8080; done
docker compose down
Lesson 0014:Kubernetes 核心概念 →——Pod、Deployment、Service、Namespace。容器编排的真正入口。