20.1 前后端分离架构

20.1 前后端分离架构

现代电商平台普遍采用前后端分离架构,这种架构模式带来了开发效率、可扩展性和团队协作上的显著优势。本节将深入讲解如何设计和实现一个高效的前后端分离电商系统。

架构设计原则

1. 分层架构示意图

┌───────────────────────────────────────────────────────────────┐
│                       客户端应用 (Client)                      │
│  ┌─────────────┐    ┌─────────────┐    ┌─────────────────┐  │
│  │    UI组件    │ ←→ │ 状态管理    │ ←→ │   API服务层     │  │
│  └─────────────┘    └─────────────┘    └─────────────────┘  │
└───────────────────────────────────────────────────┬──────────┘
                                                    ↓
┌───────────────────────────────────────────────────┬──────────┐
│                    API网关层 (Gateway)             │          │
│  ┌─────────────┐    ┌─────────────┐    ┌─────────────┐       │
│  │ 路由分发     │ ←→ │ 认证鉴权    │ ←→ │ 请求转发     │ ←─┐   │
│  └─────────────┘    └─────────────┘    └─────────────┘   │   │
└───────────────────────────────────────────────────┬───────┘   │
                                                    ↓           │
┌───────────────────────────────────────────────────┬──────────┐│
│                 微服务层 (Microservices)           │          ││
│  ┌─────────────┐    ┌─────────────┐    ┌─────────────┐       ││
│  │ 用户服务     │    │ 商品服务    │    │ 订单服务    │ ...  ││
│  └─────────────┘    └─────────────┘    └─────────────┘       ││
└───────────────────────────────────────────────────┬──────────┘│
                                                    ↓           │
┌───────────────────────────────────────────────────┬──────────┐│
│                    数据层 (Data)                   │          ││
│  ┌─────────────┐    ┌─────────────┐    ┌─────────────┐       ││
│  │  MySQL      │    │  MongoDB    │    │  Redis      │ ...  ││
│  └─────────────┘    └─────────────┘    └─────────────┘       ││
└───────────────────────────────────────────────────────────────┘

前端架构实现

2. 现代前端项目结构

frontend/
├── public/                  # 静态资源
├── src/
│   ├── api/                 # API服务层
│   │   ├── auth.js          # 认证相关API
│   │   ├── products.js      # 商品相关API
│   │   └── ...              # 其他API模块
│   ├── assets/              # 静态资源
│   ├── components/          # 公共组件
│   ├── composables/         # Vue组合式函数
│   ├── layouts/             # 页面布局
│   ├── router/              # 路由配置
│   ├── stores/              # 状态管理
│   ├── styles/              # 全局样式
│   ├── utils/               # 工具函数
│   └── views/               # 页面组件
├── .env.development         # 开发环境变量
├── .env.production          # 生产环境变量
└── vue.config.js            # 构建配置

3. API服务层封装

// src/api/base.js
import axios from 'axios';
import { useAuthStore } from '@/stores/auth';

const apiClient = axios.create({
  baseURL: process.env.VUE_APP_API_BASE_URL,
  timeout: 30000,
  withCredentials: true
});

// 请求拦截器
apiClient.interceptors.request.use(config => {
  const authStore = useAuthStore();
  if (authStore.token) {
    config.headers.Authorization = `Bearer ${authStore.token}`;
  }
  return config;
});

// 响应拦截器
apiClient.interceptors.response.use(
  response => response.data,
  async error => {
    const originalRequest = error.config;
    
    // 自动刷新token逻辑
    if (error.response?.status === 401 && !originalRequest._retry) {
      originalRequest._retry = true;
      try {
        const authStore = useAuthStore();
        await authStore.refreshToken();
        return apiClient(originalRequest);
      } catch (refreshError) {
        authStore.logout();
        return Promise.reject(refreshError);
      }
    }
    
    return Promise.reject(error);
  }
);

export default apiClient;

4. 商品模块API示例

// src/api/products.js
import apiClient from './base';

export default {
  // 获取商品列表
  getProducts(params = {}) {
    return apiClient.get('/products', { params });
  },
  
  // 获取商品详情
  getProduct(id) {
    return apiClient.get(`/products/${id}`);
  },
  
  // 创建商品
  createProduct(productData) {
    return apiClient.post('/products', productData);
  },
  
  // 搜索商品
  searchProducts(query) {
    return apiClient.get('/products/search', { 
      params: { q: query } 
    });
  }
};

后端架构实现

5. 微服务网关配置

// gateway/src/app.js
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const jwtAuth = require('./middlewares/jwtAuth');

const app = express();

// 认证服务直接路由
app.use('/auth', createProxyMiddleware({ 
  target: 'http://auth-service:3001',
  changeOrigin: true 
}));

// 需要认证的路由
app.use('/api', jwtAuth, createProxyMiddleware({
  target: 'http://api-service:3002',
  changeOrigin: true,
  pathRewrite: {
    '^/api': ''
  }
}));

// 商品服务路由
app.use('/products', jwtAuth, createProxyMiddleware({ 
  target: 'http://product-service:3003',
  changeOrigin: true 
}));

// 错误处理中间件
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({ error: 'Internal Server Error' });
});

module.exports = app;

6. JWT认证中间件

// gateway/src/middlewares/jwtAuth.js
const jwt = require('jsonwebtoken');

module.exports = (req, res, next) => {
  // 从Cookie或Authorization头获取token
  const token = req.cookies.token || 
    req.headers.authorization?.split(' ')[1];
  
  if (!token) {
    return res.status(401).json({ error: 'Unauthorized' });
  }

  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    req.user = decoded;
    next();
  } catch (err) {
    if (err.name === 'TokenExpiredError') {
      return res.status(401).json({ error: 'Token expired' });
    }
    return res.status(401).json({ error: 'Invalid token' });
  }
};

前后端协作规范

7. API设计规范

RESTful API 最佳实践:

  1. 资源命名

    • 使用名词复数形式:/products/users
    • 嵌套资源:/products/{id}/reviews
  2. HTTP方法

    • GET:获取资源
    • POST:创建资源
    • PUT/PATCH:更新资源
    • DELETE:删除资源
  3. 响应格式

    {
      "data": {
        "id": "123",
        "type": "products",
        "attributes": {
          "name": "智能手机",
          "price": 2999
        },
        "relationships": {
          "category": {
            "data": { "id": "1", "type": "categories" }
          }
        }
      },
      "meta": {
        "total": 100,
        "page": 1
      },
      "links": {
        "self": "/products/123",
        "related": "/categories/1"
      }
    }
    
  4. 错误处理

    {
      "error": {
        "code": "invalid_parameter",
        "message": "价格必须是数字",
        "details": {
          "field": "price",
          "value": "abc"
        }
      }
    }
    

8. 接口版本管理

  1. URL路径版本控制

    GET /api/v1/products
    POST /api/v2/products
    
  2. 请求头版本控制

    GET /api/products
    Accept: application/vnd.myapi.v1+json
    
  3. 语义化版本策略

    • v1.0.0 → 初始稳定版本
    • v1.1.0 → 向后兼容的新功能
    • v2.0.0 → 不兼容的API变更

部署架构设计

9. 容器化部署方案

# 前端Dockerfile示例
FROM node:16 as builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
# 后端网关Dockerfile示例
FROM node:16
WORKDIR /app
COPY package*.json ./
RUN npm install --production
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]

10. Nginx配置优化

# nginx.conf
upstream backend {
  server gateway:3000;
  keepalive 64;
}

server {
  listen 80;
  server_name example.com;
  
  # 前端静态资源
  location / {
    root /usr/share/nginx/html;
    index index.html;
    try_files $uri $uri/ /index.html;
    
    # 静态资源缓存
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
      expires 1y;
      add_header Cache-Control "public, immutable";
    }
  }
  
  # API代理
  location /api {
    proxy_pass http://backend;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    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_cache_bypass $http_upgrade;
  }
  
  # WebSocket支持
  location /socket.io {
    proxy_pass http://backend;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
  }
}

性能优化策略

11. 前端性能优化

  1. 代码分割

    // 动态导入组件
    const ProductDetail = () => import('@/views/ProductDetail');
    
  2. 预加载关键资源

    <link rel="preload" href="/fonts/roboto.woff2" as="font" type="font/woff2" crossorigin>
    
  3. API请求优化

    // 使用AbortController取消重复请求
    const controller = new AbortController();
    
    fetch('/api/products', {
      signal: controller.signal
    });
    
    // 取消请求
    controller.abort();
    

12. 后端性能优化

  1. 缓存策略

    // Redis缓存中间件
    const cache = (req, res, next) => {
      const key = req.originalUrl;
      redis.get(key, (err, data) => {
        if (data) {
          return res.json(JSON.parse(data));
        }
        next();
      });
    };
    
  2. 数据库查询优化

    // 添加索引后查询
    Product.find()
      .where('price').gt(100).lt(1000)
      .sort('-createdAt')
      .select('name price image')
      .limit(10)
      .lean();
    
  3. 负载均衡配置

    upstream backend {
      server gateway1:3000;
      server gateway2:3000;
      server gateway3:3000;
      
      # 最少连接算法
      least_conn;
      
      # 健康检查
      check interval=3000 rise=2 fall=3 timeout=1000;
    }
    

安全最佳实践

13. 前端安全措施

  1. CSP策略

    <meta http-equiv="Content-Security-Policy" 
          content="default-src 'self'; 
                   script-src 'self' 'unsafe-inline' cdn.example.com;
                   style-src 'self' 'unsafe-inline';
                   img-src 'self' data: storage.example.com;">
    
  2. XSS防护

    // 自动转义HTML
    function sanitize(input) {
    const div = document.createElement('div');
    div.textContent = input;
    return div.innerHTML;
    }
    
  3. 敏感操作确认

    // 关键操作需要重新验证密码
    async function confirmCriticalAction(password) {
      const response = await apiClient.post('/confirm-action', { password });
      return response.data.confirmed;
    }
    

14. 后端安全措施

  1. 速率限制

    const rateLimit = require('express-rate-limit');
    
    const limiter = rateLimit({
      windowMs: 15 * 60 * 1000, // 15分钟
      max: 100, // 每个IP限制100次请求
      message: '请求过于频繁,请稍后再试'
    });
    
    app.use('/api/', limiter);
    
  2. SQL注入防护

    // 使用参数化查询
    const [products] = await connection.execute(
      'SELECT * FROM products WHERE category = ? AND price > ?',
      [category, minPrice]
    );
    
  3. 请求验证

    const { body } = require('express-validator');
    
    router.post('/products', 
      body('name').isString().trim().notEmpty(),
      body('price').isFloat({ min: 0 }),
      body('stock').isInt({ min: 0 }),
      handleValidationErrors,
      productController.create
    );
    

监控与日志

15. 前端监控

// 错误监控
window.addEventListener('error', (event) => {
  fetch('/api/logs', {
    method: 'POST',
    body: JSON.stringify({
      type: 'client_error',
      message: event.message,
      stack: event.error?.stack,
      filename: event.filename,
      lineno: event.lineno,
      colno: event.colno
    })
  });
});

// 性能监控
const perfData = window.performance.timing;
const loadTime = perfData.loadEventEnd - perfData.navigationStart;
sendAnalytics('page_load', { duration: loadTime });

16. 后端监控

// 请求日志中间件
app.use((req, res, next) => {
  const start = Date.now();
  
  res.on('finish', () => {
    const duration = Date.now() - start;
    logRequest({
      method: req.method,
      path: req.path,
      status: res.statusCode,
      duration,
      ip: req.ip,
      userAgent: req.get('User-Agent')
    });
  });
  
  next();
});

// 异常监控
process.on('uncaughtException', (err) => {
  logError({
    type: 'uncaught_exception',
    error: err.stack,
    timestamp: new Date()
  });
  process.exit(1);
});

通过以上架构设计和实现方案,你可以构建一个高性能、可扩展的前后端分离电商平台。接下来我们将深入讲解RESTful API设计的最佳实践。

#前端开发 分享于 2025-03-25

【 内容由 AI 共享,不代表本站观点,请谨慎参考 】