单体架构详细解析:从概念到实践--购物网站搭建

一、单体架构的本质与核心特征

1.1 什么是单体架构?

单体架构(Monolithic Architecture)是将整个应用的所有功能模块(前端、后端、数据库交互等)打包成一个单一的、自包含的部署单元。

形象比喻

  • 就像一家"全能小店":一个老板(服务器)负责所有事情(接待、烹饪、收银、清洁)
  • 所有代码在一个"大包裹"里,部署时一次性上传整个包裹
  • 访问数据库像"一个大脑(单一数据库)管理所有记忆"

1.2 核心特征

复制代码
1. 单一代码库:所有功能在同一个项目/代码仓库中
2. 统一部署:编译成一个可执行文件(如JAR/WAR)或一组文件
3. 共享数据库:所有模块访问同一个数据库实例
4. 进程内调用:模块间通过函数/方法调用通信,而非网络
5. 技术栈统一:前后端使用相同的技术生态

二、典型单体购物网站详细架构

2.1 三层架构模型(最经典)

复制代码
┌─────────────────────────────────────────────────────────────┐
│                   表现层 (Presentation Layer)                 │
├─────────────────────────────────────────────────────────────┤
│  [浏览器] → [Nginx] → [Spring MVC Controller / Django View] │
│                                                            │
│  职责:                                                     │
│  1. 接收HTTP请求,解析参数                                 │
│  2. 调用业务逻辑层                                         │
│  3. 渲染HTML/JSON响应                                     │
│  4. 用户会话管理                                          │
└─────────────────────────────┬───────────────────────────────┘
                              ↓
┌─────────────────────────────────────────────────────────────┐
│                   业务逻辑层 (Business Logic Layer)           │
├─────────────────────────────────────────────────────────────┤
│  [Service类 / Manager类]                                   │
│                                                            │
│  职责:                                                     │
│  1. 实现核心业务逻辑(购物车、订单、支付)                  │
│  2. 事务管理 (@Transactional)                              │
│  3. 数据验证与业务规则                                     │
│  4. 调用数据访问层                                         │
└─────────────────────────────┬───────────────────────────────┘
                              ↓
┌─────────────────────────────────────────────────────────────┐
│                   数据访问层 (Data Access Layer)             │
├─────────────────────────────────────────────────────────────┤
│  [DAO类 / Repository类 / Mapper]                           │
│                                                            │
│  职责:                                                     │
│  1. 封装数据库访问细节                                     │
│  2. 执行SQL查询/更新                                       │
│  3. ORM映射(对象-关系映射)                               │
│  4. 连接池管理                                             │
└─────────────────────────────┬───────────────────────────────┘
                              ↓
                    ┌────────────────────┐
                    │    数据库层         │
                    │   [MySQL]         │
                    │   - 用户表         │
                    │   - 商品表         │
                    │   - 订单表         │
                    │   - 购物车表       │
                    └────────────────────┘

2.2 目录结构示例(Spring Boot + Thymeleaf)

复制代码
src/main/
├── java/com/example/eshop/
│   ├── EshopApplication.java           # 启动类
│   ├── config/                         # 配置类
│   │   ├── WebConfig.java              # Web配置
│   │   ├── SecurityConfig.java         # 安全配置(Spring Security)
│   │   └── DataSourceConfig.java       # 数据源配置
│   ├── controller/                     # 控制器层
│   │   ├── HomeController.java         # 首页
│   │   ├── UserController.java         # 用户相关
│   │   ├── ProductController.java      # 商品相关
│   │   ├── CartController.java         # 购物车
│   │   ├── OrderController.java        # 订单
│   │   └── PaymentController.java      # 支付
│   ├── service/                        # 业务逻辑层
│   │   ├── impl/                       # 实现类
│   │   │   ├── UserServiceImpl.java
│   │   │   ├── ProductServiceImpl.java
│   │   │   ├── CartServiceImpl.java
│   │   │   ├── OrderServiceImpl.java
│   │   │   └── PaymentServiceImpl.java
│   │   └── interface/                  # 接口定义
│   │       ├── UserService.java
│   │       ├── ProductService.java
│   │       └── ...
│   ├── dao/ 或 repository/             # 数据访问层
│   │   ├── UserRepository.java         # JPA Repository
│   │   ├── ProductRepository.java
│   │   ├── OrderRepository.java
│   │   └── CustomRepositoryImpl.java   # 自定义复杂查询
│   ├── model/ 或 entity/               # 实体类
│   │   ├── User.java
│   │   ├── Product.java
│   │   ├── Category.java
│   │   ├── CartItem.java
│   │   ├── Order.java
│   │   └── OrderItem.java
│   ├── dto/                            # 数据传输对象
│   │   ├── UserDTO.java
│   │   ├── ProductDTO.java
│   │   └── OrderDTO.java
│   ├── util/                           # 工具类
│   │   ├── JwtUtil.java                # JWT工具
│   │   ├── DateUtil.java
│   │   └── MoneyUtil.java
│   └── exception/                      # 异常处理
│       ├── GlobalExceptionHandler.java
│       ├── BusinessException.java
│       └── ErrorCode.java
├── resources/
│   ├── static/                         # 静态资源
│   │   ├── css/
│   │   ├── js/
│   │   ├── images/
│   │   └── uploads/                    # 上传文件(实际生产中建议用云存储)
│   ├── templates/                      # 模板文件(Thymeleaf)
│   │   ├── layout/                     # 布局文件
│   │   │   ├── base.html
│   │   │   └── header.html
│   │   ├── home/                       # 首页
│   │   ├── product/                    # 商品相关页面
│   │   ├── cart/                       # 购物车页面
│   │   ├── order/                      # 订单页面
│   │   └── user/                       # 用户相关页面
│   ├── application.properties          # 主配置文件
│   ├── application-dev.properties      # 开发环境配置
│   ├── application-prod.properties     # 生产环境配置
│   └── banner.txt                      # Spring Boot启动横幅
└── test/                               # 测试代码
    ├── EshopApplicationTests.java
    ├── controller/
    ├── service/
    └── repository/

2.3 数据库表设计(简化版)

sql 复制代码
-- 用户表
CREATE TABLE users (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) UNIQUE NOT NULL,
    password VARCHAR(100) NOT NULL,  -- 存储加密后的密码
    email VARCHAR(100) UNIQUE NOT NULL,
    phone VARCHAR(20),
    avatar VARCHAR(255),              -- 头像URL
    status TINYINT DEFAULT 1,         -- 用户状态 1-正常 0-禁用
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    INDEX idx_username (username),
    INDEX idx_email (email)
);

-- 商品表
CREATE TABLE products (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(200) NOT NULL,
    description TEXT,
    price DECIMAL(10, 2) NOT NULL,
    stock INT DEFAULT 0,              -- 库存数量
    category_id BIGINT,               -- 分类ID
    main_image VARCHAR(255),          -- 主图
    images TEXT,                      -- 商品图片JSON数组
    status TINYINT DEFAULT 1,         -- 1-上架 0-下架
    sales_count INT DEFAULT 0,        -- 销量
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    INDEX idx_category (category_id),
    INDEX idx_status (status),
    FULLTEXT idx_search (name, description)  -- 全文索引,用于搜索
);

-- 购物车表
CREATE TABLE cart_items (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    user_id BIGINT NOT NULL,
    product_id BIGINT NOT NULL,
    quantity INT NOT NULL DEFAULT 1,
    selected BOOLEAN DEFAULT TRUE,    -- 是否选中
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    UNIQUE KEY uk_user_product (user_id, product_id),  -- 防止重复添加
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
    FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE CASCADE
);

-- 订单表
CREATE TABLE orders (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    order_no VARCHAR(32) UNIQUE NOT NULL,  -- 订单号,唯一
    user_id BIGINT NOT NULL,
    total_amount DECIMAL(10, 2) NOT NULL,
    payment_amount DECIMAL(10, 2) NOT NULL,
    payment_method TINYINT,           -- 支付方式 1-支付宝 2-微信
    payment_status TINYINT DEFAULT 0, -- 0-待支付 1-已支付 2-支付失败
    order_status TINYINT DEFAULT 0,   -- 0-待付款 1-待发货 2-待收货 3-已完成 4-已取消
    shipping_address TEXT,            -- 收货地址
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    INDEX idx_user_id (user_id),
    INDEX idx_order_no (order_no),
    INDEX idx_created_at (created_at),
    FOREIGN KEY (user_id) REFERENCES users(id)
);

-- 订单明细表
CREATE TABLE order_items (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    order_id BIGINT NOT NULL,
    product_id BIGINT NOT NULL,
    product_name VARCHAR(200) NOT NULL,
    product_image VARCHAR(255),
    price DECIMAL(10, 2) NOT NULL,    -- 下单时的价格
    quantity INT NOT NULL,
    total_price DECIMAL(10, 2) NOT NULL,
    FOREIGN KEY (order_id) REFERENCES orders(id) ON DELETE CASCADE,
    FOREIGN KEY (product_id) REFERENCES products(id)
);

三、关键技术实现细节

3.1 用户认证与授权

java 复制代码
// 使用Spring Security实现
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Autowired
    private UserDetailsService userDetailsService;
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()  // 前后端分离时可禁用CSRF
            .authorizeRequests()
                .antMatchers("/", "/home", "/products/**", "/register", "/login").permitAll()
                .antMatchers("/cart/**", "/order/**").hasRole("USER")
                .antMatchers("/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
            .and()
            .formLogin()
                .loginPage("/login")
                .defaultSuccessUrl("/")
                .permitAll()
            .and()
            .logout()
                .logoutSuccessUrl("/")
                .permitAll()
            .and()
            .rememberMe()  // 记住我功能
                .tokenValiditySeconds(7 * 24 * 60 * 60)  // 7天
                .key("eshopRememberMeKey");
    }
    
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();  // 使用BCrypt加密
    }
}

3.2 购物车实现

java 复制代码
@Service
public class CartServiceImpl implements CartService {
    
    @Autowired
    private CartRepository cartRepository;
    
    @Autowired
    private ProductRepository productRepository;
    
    @Transactional
    public void addToCart(Long userId, Long productId, Integer quantity) {
        // 1. 检查商品是否存在且库存足够
        Product product = productRepository.findById(productId)
            .orElseThrow(() -> new BusinessException("商品不存在"));
        
        if (product.getStock() < quantity) {
            throw new BusinessException("库存不足");
        }
        
        // 2. 检查购物车是否已有该商品
        Optional<CartItem> existingItem = cartRepository
            .findByUserIdAndProductId(userId, productId);
        
        if (existingItem.isPresent()) {
            // 3. 已有商品,更新数量
            CartItem item = existingItem.get();
            item.setQuantity(item.getQuantity() + quantity);
            cartRepository.save(item);
        } else {
            // 4. 新增购物车项
            CartItem newItem = new CartItem();
            newItem.setUserId(userId);
            newItem.setProductId(productId);
            newItem.setQuantity(quantity);
            cartRepository.save(newItem);
        }
    }
    
    public CartDTO getCart(Long userId) {
        List<CartItem> items = cartRepository.findByUserId(userId);
        CartDTO cartDTO = new CartDTO();
        cartDTO.setItems(items);
        
        // 计算总价
        BigDecimal total = BigDecimal.ZERO;
        for (CartItem item : items) {
            if (item.isSelected()) {
                Product product = productRepository.findById(item.getProductId()).orElse(null);
                if (product != null) {
                    total = total.add(product.getPrice()
                        .multiply(BigDecimal.valueOf(item.getQuantity())));
                }
            }
        }
        cartDTO.setTotalAmount(total);
        
        return cartDTO;
    }
}

3.3 订单处理(含事务管理)

java 复制代码
@Service
public class OrderServiceImpl implements OrderService {
    
    @Autowired
    private OrderRepository orderRepository;
    
    @Autowired
    private OrderItemRepository orderItemRepository;
    
    @Autowired
    private ProductRepository productRepository;
    
    @Autowired
    private CartRepository cartRepository;
    
    @Transactional(rollbackFor = Exception.class)  // 事务管理
    public OrderDTO createOrder(Long userId, OrderRequest request) {
        // 1. 生成订单号
        String orderNo = generateOrderNo();
        
        // 2. 验证并扣减库存
        List<OrderItem> orderItems = new ArrayList<>();
        BigDecimal totalAmount = BigDecimal.ZERO;
        
        for (OrderItemRequest itemRequest : request.getItems()) {
            Product product = productRepository.findById(itemRequest.getProductId())
                .orElseThrow(() -> new BusinessException("商品不存在: " + itemRequest.getProductId()));
            
            // 乐观锁扣减库存
            int updated = productRepository.decreaseStock(
                itemRequest.getProductId(), 
                itemRequest.getQuantity(), 
                product.getVersion());
            
            if (updated == 0) {
                throw new BusinessException("商品库存不足或已更新: " + product.getName());
            }
            
            // 计算商品总价
            BigDecimal itemTotal = product.getPrice()
                .multiply(BigDecimal.valueOf(itemRequest.getQuantity()));
            totalAmount = totalAmount.add(itemTotal);
            
            // 创建订单项
            OrderItem orderItem = new OrderItem();
            orderItem.setProductId(product.getId());
            orderItem.setProductName(product.getName());
            orderItem.setProductImage(product.getMainImage());
            orderItem.setPrice(product.getPrice());
            orderItem.setQuantity(itemRequest.getQuantity());
            orderItem.setTotalPrice(itemTotal);
            orderItems.add(orderItem);
        }
        
        // 3. 创建订单
        Order order = new Order();
        order.setOrderNo(orderNo);
        order.setUserId(userId);
        order.setTotalAmount(totalAmount);
        order.setPaymentAmount(totalAmount);  // 这里简化,实际可能有优惠
        order.setShippingAddress(request.getShippingAddress());
        order.setOrderStatus(OrderStatus.PENDING_PAYMENT.getCode());
        order.setPaymentStatus(PaymentStatus.UNPAID.getCode());
        
        Order savedOrder = orderRepository.save(order);
        
        // 4. 保存订单项
        for (OrderItem item : orderItems) {
            item.setOrderId(savedOrder.getId());
            orderItemRepository.save(item);
        }
        
        // 5. 清空购物车中已下单的商品
        cartRepository.deleteByUserIdAndProductIdIn(
            userId, 
            request.getItems().stream()
                .map(OrderItemRequest::getProductId)
                .collect(Collectors.toList())
        );
        
        return convertToDTO(savedOrder, orderItems);
    }
    
    private String generateOrderNo() {
        // 生成规则:时间戳 + 随机数
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String timeStr = sdf.format(new Date());
        String randomStr = String.valueOf((int)((Math.random() * 9 + 1) * 1000));
        return timeStr + randomStr;
    }
}

3.4 支付回调处理

java 复制代码
@RestController
@RequestMapping("/payment")
public class PaymentController {
    
    @Autowired
    private OrderService orderService;
    
    @PostMapping("/alipay/callback")
    public String alipayCallback(HttpServletRequest request) {
        // 1. 验证签名(实际需对接支付宝SDK)
        Map<String, String> params = convertRequestToMap(request);
        boolean signVerified = verifySignature(params);  // 验证签名
        
        if (!signVerified) {
            return "failure";
        }
        
        // 2. 验证订单状态
        String orderNo = params.get("out_trade_no");
        String tradeStatus = params.get("trade_status");
        
        if ("TRADE_SUCCESS".equals(tradeStatus) || 
            "TRADE_FINISHED".equals(tradeStatus)) {
            // 3. 更新订单状态
            orderService.updatePaymentStatus(orderNo, PaymentStatus.PAID);
            
            // 4. 触发其他业务逻辑(如发送邮件、通知发货等)
            asyncSendOrderPaidNotification(orderNo);
        }
        
        return "success";
    }
    
    // 异步发送支付成功通知
    @Async
    public void asyncSendOrderPaidNotification(String orderNo) {
        // 发送邮件、短信等
        // 这里可以使用Spring的@Async实现异步
    }
}

四、单体架构的优化策略

4.1 数据库层面优化

sql 复制代码
-- 1. 添加合适的索引
CREATE INDEX idx_orders_user_status ON orders(user_id, order_status);
CREATE INDEX idx_products_category_price ON products(category_id, price);

-- 2. 读写分离(主从复制)
-- 主库:写操作
-- 从库:读操作(在Spring中配置多个数据源)

-- 3. 查询优化示例
-- 避免 SELECT *,只选择需要的字段
SELECT id, name, price FROM products WHERE category_id = ?;

-- 使用分页,避免一次性查询大量数据
SELECT * FROM products ORDER BY created_at DESC LIMIT 20 OFFSET 0;

4.2 应用层优化

java 复制代码
// 1. 引入缓存(Redis)
@Service
public class ProductServiceImpl implements ProductService {
    
    @Autowired
    private ProductRepository productRepository;
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    private static final String PRODUCT_CACHE_PREFIX = "product:";
    private static final long CACHE_EXPIRE_HOURS = 24;
    
    @Cacheable(value = "products", key = "#id")  // 使用Spring Cache注解
    public ProductDTO getProductById(Long id) {
        // 先查缓存
        String cacheKey = PRODUCT_CACHE_PREFIX + id;
        ProductDTO cached = (ProductDTO) redisTemplate.opsForValue().get(cacheKey);
        
        if (cached != null) {
            return cached;
        }
        
        // 缓存未命中,查数据库
        Product product = productRepository.findById(id)
            .orElseThrow(() -> new BusinessException("商品不存在"));
        
        ProductDTO dto = convertToDTO(product);
        
        // 写入缓存
        redisTemplate.opsForValue().set(
            cacheKey, 
            dto, 
            CACHE_EXPIRE_HOURS, 
            TimeUnit.HOURS
        );
        
        return dto;
    }
}

// 2. 异步处理
@Service
public class EmailService {
    
    @Async  // 使用Spring的异步支持
    public void sendOrderConfirmationEmail(Order order) {
        // 发送邮件,可能耗时较长
        // 不影响主流程的响应速度
    }
}

4.3 静态资源优化

nginx 复制代码
# Nginx配置示例
server {
    listen 80;
    server_name www.eshop.com;
    
    # 静态资源直接由Nginx处理
    location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
        root /var/www/eshop/static;
        expires 30d;  # 设置缓存过期时间
        add_header Cache-Control "public, immutable";
    }
    
    # 动态请求转发给应用服务器
    location / {
        proxy_pass http://localhost:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

五、部署与运维

5.1 传统部署方式

bash 复制代码
# 1. 打包应用
mvn clean package -DskipTests

# 2. 上传到服务器
scp target/eshop-1.0.0.jar user@server:/opt/eshop/

# 3. 启动应用
java -jar eshop-1.0.0.jar --spring.profiles.active=prod

# 4. 使用systemd管理服务
# /etc/systemd/system/eshop.service
[Unit]
Description=Eshop Application
After=network.target

[Service]
User=eshop
WorkingDirectory=/opt/eshop
ExecStart=/usr/bin/java -jar eshop-1.0.0.jar
SuccessExitStatus=143
Restart=always

[Install]
WantedBy=multi-user.target

5.2 Docker容器化部署

dockerfile 复制代码
# Dockerfile
FROM openjdk:11-jre-slim
VOLUME /tmp
COPY target/eshop-1.0.0.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
EXPOSE 8080
yaml 复制代码
# docker-compose.yml (适合小型部署)
version: '3.8'
services:
  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: rootpassword
      MYSQL_DATABASE: eshop
      MYSQL_USER: eshop
      MYSQL_PASSWORD: eshoppassword
    volumes:
      - mysql_data:/var/lib/mysql
    ports:
      - "3306:3306"
  
  redis:
    image: redis:6-alpine
    ports:
      - "6379:6379"
  
  eshop-app:
    build: .
    ports:
      - "8080:8080"
    environment:
      SPRING_PROFILES_ACTIVE: prod
      DB_HOST: mysql
      REDIS_HOST: redis
    depends_on:
      - mysql
      - redis

volumes:
  mysql_data:

六、监控与日志

6.1 Spring Boot Actuator 监控

yaml 复制代码
# application.yml
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,env
  endpoint:
    health:
      show-details: always
  metrics:
    export:
      prometheus:
        enabled: true

6.2 日志配置(Logback)

xml 复制代码
<!-- src/main/resources/logback-spring.xml -->
<configuration>
    <property name="LOG_PATH" value="./logs" />
    
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/eshop.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/eshop.%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    
    <logger name="com.eshop" level="DEBUG" />
    <logger name="org.springframework" level="INFO" />
    
    <root level="INFO">
        <appender-ref ref="FILE" />
    </root>
</configuration>

七、单体架构的适用场景与演进时机

7.1 最适合单体架构的场景

  1. 初创公司/新产品:团队规模小(3-5人),需要快速验证商业模式
  2. 简单业务场景:功能明确,业务逻辑不复杂
  3. 低流量应用:预计日活<1万,QPS<100
  4. 开发周期短:需要在1-3个月内上线
  5. 技术团队经验有限:没有微服务运维经验

7.2 需要演进的信号

  • 代码复杂度:代码行数超过10万,模块间依赖混乱
  • 团队协作困难:10+人同时开发,频繁代码冲突
  • 部署问题:每次小改动都需要重新部署整个应用
  • 性能瓶颈:数据库连接池不够用,CPU使用率持续高位
  • 技术栈限制:不同模块需要不同的技术栈(如AI推荐模块需要Python)

7.3 演进路径建议

  1. 先优化单体:引入缓存、异步、读写分离
  2. 垂直拆分:按业务模块拆分成多个单体(如用户中心、商品中心)
  3. 微服务化:服务注册发现、API网关、配置中心等

八、常见问题与解决方案

8.1 数据库连接池耗尽

java 复制代码
// 解决方案:配置合适的连接池参数
spring:
  datasource:
    hikari:
      maximum-pool-size: 20  # 根据实际需求调整
      minimum-idle: 5
      connection-timeout: 30000
      idle-timeout: 600000
      max-lifetime: 1800000

8.2 大文件上传导致内存溢出

java 复制代码
// 解决方案:使用流式处理
@PostMapping("/upload")
public String uploadFile(@RequestParam("file") MultipartFile file) {
    // 限制文件大小
    if (file.getSize() > 10 * 1024 * 1024) { // 10MB
        throw new BusinessException("文件大小不能超过10MB");
    }
    
    // 使用try-with-resources确保流关闭
    try (InputStream inputStream = file.getInputStream()) {
        // 流式上传到云存储
        uploadToCloudStorage(inputStream, file.getOriginalFilename());
    } catch (IOException e) {
        throw new BusinessException("文件上传失败");
    }
    
    return "success";
}

8.3 全表扫描导致性能问题

sql 复制代码
-- 解决方案:添加合适的索引和优化查询
-- 避免全表扫描
EXPLAIN SELECT * FROM orders WHERE created_at > '2024-01-01';

-- 使用覆盖索引
CREATE INDEX idx_orders_user_date ON orders(user_id, created_at);
SELECT id, order_no FROM orders 
WHERE user_id = 123 AND created_at > '2024-01-01';

总结

单体架构是构建购物网站最直接、最高效的起点。它的核心优势在于简单性:开发简单、测试简单、部署简单、调试简单。对于大多数初创项目和中小型电商平台,单体架构完全能够满足需求。

关键要点

  1. 三层架构清晰划分职责,保持代码整洁
  2. 数据库设计要考虑扩展性,适当冗余
  3. 引入缓存和异步可以显著提升性能
  4. 监控和日志是生产环境的必需品
  5. 不要过早优化,在真正遇到问题前保持简单

单体架构不是"落后"的代名词,而是务实的选择 。当业务发展到一定规模,确实遇到瓶颈时,再考虑向更复杂的架构演进。记住:没有最好的架构,只有最适合当前阶段的架构

相关推荐
不思念一个荒废的名字2 小时前
【黑马JavaWeb+AI知识梳理】Web后端开发04-登录认证
java·后端
java1234_小锋2 小时前
Redis到底支不支持事务啊?
java·数据库·redis
爱笑的眼睛112 小时前
超越`cross_val_score`:深入剖析Scikit-learn交叉验证API的设计哲学与高阶实践
java·人工智能·python·ai
L0CK2 小时前
三种依赖注入详解
java
記億揺晃着的那天3 小时前
Amazon SP-API,授权封装、SDK 分层与 AAD 加密一致性设计
spring boot·架构设计·amazon sp-api·sdk 设计
shoubepatien3 小时前
JAVA -- 07
java·后端·intellij-idea
Gu_yyqx3 小时前
Maven进阶
java·maven
小肖爱笑不爱笑3 小时前
JavaScript
java·javascript·json·web
专注于大数据技术栈3 小时前
java学习--String和StringBuffer互转
java·学习