跳转至

第 6 章:完整架构实战

将前面学到的所有技术整合起来,构建一个生产就绪的 Web 服务架构。


6.1 架构全景图

                        ┌──────────────────────────────────────────┐
                        │              互联网                        │
                        └──────────────────────┬─────────────────────┘
                    ┌──────────────────────────────────────────────┐
                    │              DNS (Cloudflare)                 │
                    │        域名解析 + CDN + DDoS 防护              │
                    └──────────────────────┬───────────────────────┘
                    ┌──────────────────────────────────────────────┐
                    │                 Nginx                         │
                    │  ┌───────────────────────────────────────┐   │
                    │  │  SSL/TLS 终止 (HTTPS → HTTP)          │   │
                    │  │  静态文件服务 (HTML/CSS/JS/图片)       │   │
                    │  │  限流 (API 10r/s, 登录 1r/s)          │   │
                    │  │  缓存 (产品列表 10min)                  │   │
                    │  │  负载均衡 (轮询 + 健康检查)              │   │
                    │  └───────────────────────────────────────┘   │
                    └──┬──────────┬──────────────────┬────────────┘
                       │          │                  │
              /api/*   │   /ai/*  │           /      │
                       ▼          ▼                  ▼
          ┌─────────────────┐ ┌─────────────┐ ┌──────────────┐
          │  Express 集群    │ │ FastAPI集群  │ │ 前端静态站点  │
          │  (Node.js)      │ │ (Python)     │ │ (Vue/React)  │
          │                 │ │             │ │              │
          │ • 用户管理       │ │ • AI 推理   │ │ • SPA 应用   │
          │ • 订单处理       │ │ • 数据处理   │ │ • 静态资源   │
          │ • 支付接口       │ │ • 模型服务   │ │              │
          └───┬──────┬──────┘ └──────┬───────┘ └──────────────┘
              │      │               │
              ▼      ▼               ▼
    ┌─────────────────────────────────────────────────────────────┐
    │                    数据层                                     │
    │                                                              │
    │  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐   │
    │  │PostgreSQL│  │  Redis   │  │MongoDB   │  │MinIO/S3  │   │
    │  │(用户/订单)│  │ (缓存/会话)│  │ (日志/分析)│  │ (文件存储) │   │
    │  └──────────┘  └──────────┘  └──────────┘  └──────────┘   │
    └─────────────────────────────────────────────────────────────┘

6.2 项目结构

my-project/
├── docker/
│   ├── nginx/
│   │   └── nginx.conf
│   ├── express/
│   │   ├── Dockerfile
│   │   └── ...
│   └── fastapi/
│       ├── Dockerfile
│       └── ...
├── services/
│   ├── api/                    # Express 应用
│   │   ├── src/
│   │   │   ├── app.js
│   │   │   ├── routes/
│   │   │   ├── controllers/
│   │   │   ├── models/
│   │   │   └── middleware/
│   │   ├── package.json
│   │   └── Dockerfile
│   ├── ai/                     # FastAPI 应用
│   │   ├── app/
│   │   │   ├── main.py
│   │   │   ├── api/
│   │   │   ├── models/
│   │   │   └── services/
│   │   ├── requirements.txt
│   │   └── Dockerfile
│   └── web/                    # 前端
│       ├── dist/
│       └── Dockerfile
├── docker-compose.yml
├── .env
└── README.md

6.3 Docker Compose 编排

docker-compose.yml

version: '3.8'

services:
  # Nginx 反向代理
  nginx:
    image: nginx:1.25-alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./certs:/etc/nginx/certs:ro
    depends_on:
      - express-api
      - fastapi-ai
    restart: always
    networks:
      - frontend

  # Express API
  express-api:
    build:
      context: ./services/api
      dockerfile: Dockerfile
    environment:
      - NODE_ENV=production
      - DATABASE_URL=postgresql://user:pass@postgres:5432/mydb
      - REDIS_URL=redis://redis:6379
      - JWT_SECRET=${JWT_SECRET}
    depends_on:
      - postgres
      - redis
    restart: always
    networks:
      - frontend
      - backend

  # FastAPI AI 服务
  fastapi-ai:
    build:
      context: ./services/ai
      dockerfile: Dockerfile
    environment:
      - REDIS_URL=redis://redis:6379
    volumes:
      - ./models:/app/models:ro
    restart: always
    networks:
      - frontend
      - backend

  # PostgreSQL
  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: mydb
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
    volumes:
      - pgdata:/var/lib/postgresql/data
    restart: always
    networks:
      - backend

  # Redis
  redis:
    image: redis:7-alpine
    command: redis-server --requirepass redispass
    volumes:
      - redisdata:/data
    restart: always
    networks:
      - backend

volumes:
  pgdata:
  redisdata:

networks:
  frontend:
  backend:
    internal: true  # 后端网络不对外暴露

6.4 Nginx 配置

docker/nginx/nginx.conf

worker_processes auto;

events {
    worker_connections 4096;
    multi_accept on;
}

http {
    include 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" '
                    'rt=$request_time';
    access_log /var/log/nginx/access.log main;
    error_log /var/log/nginx/error.log warn;

    # 性能
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    keepalive_requests 1000;
    client_max_body_size 50m;

    # Gzip
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types text/plain text/css application/json application/javascript text/xml;

    # 限流
    limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
    limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;

    # Express 上游
    upstream express_backend {
        least_conn;
        server express-api:3000 max_fails=3 fail_timeout=30s;
    }

    # FastAPI 上游
    upstream fastapi_backend {
        least_conn;
        server fastapi-ai:8000 max_fails=3 fail_timeout=30s;
    }

    # HTTP → HTTPS
    server {
        listen 80;
        server_name _;
        return 301 https://$host$request_uri;
    }

    # HTTPS
    server {
        listen 443 ssl http2;
        server_name example.com;

        ssl_certificate /etc/nginx/certs/fullchain.pem;
        ssl_certificate_key /etc/nginx/certs/privkey.pem;
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_ciphers HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers on;
        ssl_session_cache shared:SSL:10m;

        # 安全头
        add_header X-Frame-Options "SAMEORIGIN" always;
        add_header X-Content-Type-Options "nosniff" always;
        add_header Strict-Transport-Security "max-age=31536000" always;
        server_tokens off;

        # 前端静态文件
        location / {
            root /usr/share/nginx/html;
            index index.html;
            try_files $uri $uri/ /index.html;

            expires 1h;
            add_header Cache-Control "public";
        }

        # Express API
        location /api/ {
            limit_req zone=api burst=20 nodelay;

            proxy_pass http://express_backend;
            proxy_http_version 1.1;
            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_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";

            proxy_connect_timeout 30s;
            proxy_read_timeout 60s;
        }

        # 登录限流(更严格)
        location /api/auth/login {
            limit_req zone=login burst=3 nodelay;

            proxy_pass http://express_backend;
            proxy_http_version 1.1;
            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;
        }

        # FastAPI AI 服务
        location /ai/ {
            proxy_pass http://fastapi_backend;
            proxy_http_version 1.1;
            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;

            # AI 推理可能较慢
            proxy_read_timeout 300s;
            proxy_send_timeout 300s;
        }

        # FastAPI 健康检查(不限流)
        location /ai/health {
            proxy_pass http://fastapi_backend;
        }

        # 静态资源缓存
        location ~* \.(jpg|jpeg|png|gif|ico|svg|webp|css|js|woff2?)$ {
            expires 1y;
            add_header Cache-Control "public, immutable";
        }
    }
}

6.5 Express Dockerfile

services/api/Dockerfile

# 多阶段构建
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY src ./src
COPY package.json ./

# 非 root 用户运行
RUN addgroup -g 1001 -S appgroup && \
    adduser -S appuser -u 1001 -G appgroup
USER appuser

EXPOSE 3000
CMD ["node", "src/server.js"]

services/api/src/server.js

const app = require('./app');
const PORT = process.env.PORT || 3000;

const server = app.listen(PORT, () => {
  console.log(`Express API running on port ${PORT}`);
});

// 优雅关闭
process.on('SIGTERM', () => {
  console.log('SIGTERM received, shutting down gracefully...');
  server.close(() => {
    console.log('Server closed');
    process.exit(0);
  });
});

process.on('SIGINT', () => {
  server.close(() => process.exit(0));
});

6.6 FastAPI Dockerfile

services/ai/Dockerfile

FROM python:3.11-slim
WORKDIR /app

# 安装依赖
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 复制代码
COPY app ./app
COPY models ./models

# 非 root 用户
RUN useradd -m appuser && chown -R appuser:appuser /app
USER appuser

EXPOSE 8000
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4"]

6.7 生产部署脚本

deploy.sh

#!/bin/bash
set -e

echo "=== 部署开始 ==="

# 1. 拉取最新代码
git pull origin main

# 2. 构建并启动
docker compose build --no-cache
docker compose up -d

# 3. 等待服务启动
echo "等待服务启动..."
sleep 10

# 4. 健康检查
echo "=== 健康检查 ==="
curl -sf http://localhost/health && echo "✅ Nginx OK" || echo "❌ Nginx FAIL"
curl -sf http://localhost/api/health && echo "✅ Express OK" || echo "❌ Express FAIL"
curl -sf http://localhost/ai/health && echo "✅ FastAPI OK" || echo "❌ FastAPI FAIL"

# 5. 查看日志
echo "=== 最近日志 ==="
docker compose logs --tail=20

echo "=== 部署完成 ==="

6.8 监控与告警

健康检查端点

// Express 健康检查
app.get('/health', async (req, res) => {
  const checks = {
    database: false,
    redis: false,
    uptime: process.uptime()
  };

  try {
    await db.query('SELECT 1');
    checks.database = true;
  } catch {}

  try {
    await redis.ping();
    checks.redis = true;
  } catch {}

  const status = checks.database && checks.redis ? 'healthy' : 'unhealthy';
  const statusCode = status === 'healthy' ? 200 : 503;

  res.status(statusCode).json({ status, checks });
});
# FastAPI 健康检查
@app.get("/health")
async def health():
    checks = {
        "redis": False,
        "model_loaded": model is not None,
    }
    try:
        await redis.ping()
        checks["redis"] = True
    except:
        pass

    status = "healthy" if all(checks.values()) else "unhealthy"
    status_code = 200 if status == "healthy" else 503
    return JSONResponse(
        status_code=status_code,
        content={"status": status, "checks": checks}
    )

Nginx 监控

# 启用 Nginx 状态页
location /nginx_status {
    stub_status on;
    allow 127.0.0.1;
    deny all;
}

# 查看状态
curl http://localhost/nginx_status
# Active connections: 123
# server accepts handled requests
#  10000 10000 50000
# Reading: 2 Writing: 5 Waiting: 116

6.9 完整请求流程

1. 用户在浏览器输入 https://example.com/api/users/123

2. DNS 解析 → Cloudflare CDN → 路由到服务器 IP

3. Nginx 接收请求:
   - SSL 终止(解密 HTTPS)
   - 匹配 location /api/
   - 限流检查(10r/s)
   - 负载均衡选择 Express 实例

4. Express 处理请求:
   - 认证中间件:验证 JWT Token
   - 路由处理:GET /api/users/:id
   - Controller:查询数据库
   - 返回 JSON 响应

5. Nginx 返回响应:
   - 添加安全头
   - 压缩响应体(Gzip)
   - 返回给客户端

6. 客户端收到响应:
   HTTP/2 200 OK
   Content-Type: application/json
   X-Frame-Options: SAMEORIGIN
   Content-Encoding: gzip
   X-Cache-Status: MISS

   {"id": 123, "name": "Alice", "email": "alice@example.com"}

6.10 总结

层级 技术 职责
入口层 Nginx SSL、限流、负载均衡、缓存、静态文件
应用层 Express / FastAPI 业务逻辑、API 实现
数据层 PostgreSQL / Redis / MongoDB 数据存储、缓存
编排层 Docker Compose 服务编排、网络隔离、数据持久化
监控层 健康检查 + 日志 服务状态、性能监控

这套架构可以支撑: - 日均 100 万请求 - 峰值 1000 QPS - 99.9% 可用性

扩展到更大规模需要: - Kubernetes 替代 Docker Compose - 服务网格(Istio) - 分布式追踪(Jaeger) - 集中式日志(ELK) - 指标监控(Prometheus + Grafana)


🎓 系列总结

技术 一句话总结 适合场景
Node.js 事件驱动 + 非阻塞 I/O 的 JS 运行时 I/O 密集型、高并发
REST API 用 HTTP 方法 + URL 资源设计接口 通用 Web API
Express 最小灵活的 Node.js Web 框架 全栈 JS、快速原型
FastAPI 类型安全 + 自动文档的 Python 框架 AI/ML 服务、Python 生态
Nginx 高性能反向代理 + Web 服务器 生产环境标配

上一章:Nginx 原理与配置