Java微服务架构实战:Spring Cloud Alibaba分布式电商平台开发指南

2025-08-22 0 384

一、微服务架构概述与设计

随着电商业务的快速发展,单体架构已无法满足高并发、高可用的需求。本文将基于Spring Cloud Alibaba生态,构建一个完整的分布式电商平台。

1.1 系统架构设计

我们的电商平台将包含以下核心服务:

  • 用户服务 (user-service) – 用户注册、登录、管理
  • 商品服务 (product-service) – 商品管理、分类、搜索
  • 订单服务 (order-service) – 订单创建、支付、管理
  • 库存服务 (inventory-service) – 库存管理、扣减
  • 支付服务 (payment-service) – 支付处理、回调
  • 网关服务 (api-gateway) – 统一入口、路由转发

1.2 技术栈选型

  • Spring Boot 2.7+
  • Spring Cloud Alibaba 2021.0.1+
  • Nacos – 服务注册与配置中心
  • Sentinel – 流量控制与熔断降级
  • Seata – 分布式事务解决方案
  • RocketMQ – 消息队列
  • MySQL + MyBatis Plus – 数据持久化
  • Redis – 缓存与分布式锁

二、环境准备与项目搭建

2.1 创建父工程

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    
    <groupId>com.ecommerce</groupId>
    <artifactId>ecommerce-platform</artifactId>
    <version>1.0.0</version>
    <packaging>pom</packaging>
    
    <modules>
        <module>user-service</module>
        <module>product-service</module>
        <module>order-service</module>
        <module>inventory-service</module>
        <module>payment-service</module>
        <module>api-gateway</module>
        <module>common-core</module>
    </modules>
    
    <properties>
        <java.version>11</java.version>
        <spring-boot.version>2.7.3</spring-boot.version>
        <spring-cloud.version>2021.0.4</spring-cloud.version>
        <spring-cloud-alibaba.version>2021.0.4.0</spring-cloud-alibaba.version>
    </properties>
    
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

2.2 通用模块设计 (common-core)

// 统一响应格式
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ApiResponse<T> implements Serializable {
    private Integer code;
    private String message;
    private T data;
    private Long timestamp;
    
    public static <T> ApiResponse<T> success(T data) {
        return new ApiResponse(200, "成功", data, System.currentTimeMillis());
    }
    
    public static ApiResponse<?> error(String message) {
        return new ApiResponse(500, message, null, System.currentTimeMillis());
    }
}

// 全局异常处理
@RestControllerAdvice
public class GlobalExceptionHandler {
    
    @ExceptionHandler(BusinessException.class)
    public ApiResponse<?> handleBusinessException(BusinessException e) {
        return ApiResponse.error(e.getMessage());
    }
    
    @ExceptionHandler(Exception.class)
    public ApiResponse<?> handleException(Exception e) {
        log.error("系统异常: ", e);
        return ApiResponse.error("系统繁忙,请稍后重试");
    }
}

// 分布式ID生成器
@Component
public class SnowflakeIdGenerator {
    private final Snowflake snowflake;
    
    public SnowflakeIdGenerator() {
        this.snowflake = Snowflake.create(1, 1);
    }
    
    public long nextId() {
        return snowflake.nextId();
    }
}

三、核心服务实现

3.1 用户服务实现

// User实体类
@Data
@TableName("t_user")
public class User {
    @TableId(type = IdType.ASSIGN_ID)
    private Long id;
    private String username;
    private String password;
    private String email;
    private String phone;
    private Integer status;
    private Date createTime;
    private Date updateTime;
}

// UserService实现
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    @Override
    public ApiResponse<UserVO> register(UserRegisterDTO dto) {
        // 验证用户名是否已存在
        if (lambdaQuery().eq(User::getUsername, dto.getUsername()).exists()) {
            throw new BusinessException("用户名已存在");
        }
        
        // 密码加密
        String encryptedPassword = PasswordUtil.encrypt(dto.getPassword());
        
        // 创建用户
        User user = new User();
        user.setUsername(dto.getUsername());
        user.setPassword(encryptedPassword);
        user.setEmail(dto.getEmail());
        user.setPhone(dto.getPhone());
        user.setStatus(1);
        user.setCreateTime(new Date());
        
        save(user);
        
        // 发送注册成功事件
        rocketMQTemplate.send("user-register-topic", 
            MessageBuilder.withPayload(user).build());
        
        return ApiResponse.success(convertToVO(user));
    }
    
    @Override
    @SentinelResource(value = "userLogin", blockHandler = "loginBlockHandler")
    public ApiResponse<String> login(UserLoginDTO dto) {
        User user = lambdaQuery()
            .eq(User::getUsername, dto.getUsername())
            .one();
            
        if (user == null || !PasswordUtil.matches(dto.getPassword(), user.getPassword())) {
            throw new BusinessException("用户名或密码错误");
        }
        
        // 生成JWT token
        String token = JwtUtil.generateToken(user.getId(), user.getUsername());
        
        // 缓存用户信息
        redisTemplate.opsForValue().set("user:" + user.getId(), user, 30, TimeUnit.MINUTES);
        
        return ApiResponse.success(token);
    }
    
    public ApiResponse<String> loginBlockHandler(UserLoginDTO dto, BlockException ex) {
        log.warn("登录接口被限流: {}", dto.getUsername());
        return ApiResponse.error("系统繁忙,请稍后重试");
    }
}

3.2 商品服务实现

// 商品查询服务
@Service
@Slf4j
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> 
    implements ProductService {
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    @Override
    @Cacheable(value = "product", key = "#id")
    public Product getProductById(Long id) {
        log.info("查询数据库获取商品详情: {}", id);
        return getById(id);
    }
    
    @Override
    public Page<ProductVO> searchProducts(ProductQueryDTO queryDTO) {
        return lambdaQuery()
            .like(StringUtils.isNotBlank(queryDTO.getKeyword()), 
                Product::getName, queryDTO.getKeyword())
            .eq(queryDTO.getCategoryId() != null, 
                Product::getCategoryId, queryDTO.getCategoryId())
            .between(queryDTO.getMinPrice() != null && queryDTO.getMaxPrice() != null,
                Product::getPrice, queryDTO.getMinPrice(), queryDTO.getMaxPrice())
            .eq(Product::getStatus, 1)
            .page(new Page(queryDTO.getPageNum(), queryDTO.getPageSize()))
            .convert(this::convertToVO);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean reduceStock(Long productId, Integer quantity) {
        // 使用分布式锁防止超卖
        String lockKey = "product:stock:lock:" + productId;
        String requestId = UUID.randomUUID().toString();
        
        try {
            // 尝试获取分布式锁
            Boolean locked = redisTemplate.opsForValue()
                .setIfAbsent(lockKey, requestId, 10, TimeUnit.SECONDS);
                
            if (Boolean.TRUE.equals(locked)) {
                Product product = getById(productId);
                if (product.getStock() < quantity) {
                    throw new BusinessException("库存不足");
                }
                
                // 扣减库存
                boolean updated = lambdaUpdate()
                    .setSql("stock = stock - " + quantity)
                    .eq(Product::getId, productId)
                    .ge(Product::getStock, quantity)
                    .update();
                    
                if (!updated) {
                    throw new BusinessException("库存扣减失败");
                }
                
                // 发送库存变更消息
                rocketMQTemplate.send("stock-change-topic", 
                    MessageBuilder.withPayload(new StockChangeEvent(productId, -quantity)).build());
                    
                return true;
            } else {
                throw new BusinessException("系统繁忙,请重试");
            }
        } finally {
            // 释放锁
            if (requestId.equals(redisTemplate.opsForValue().get(lockKey))) {
                redisTemplate.delete(lockKey);
            }
        }
    }
}

3.3 订单服务实现

// 订单服务
@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> 
    implements OrderService {
    
    @Autowired
    private ProductFeignClient productFeignClient;
    
    @Autowired
    private InventoryFeignClient inventoryFeignClient;
    
    @Override
    @GlobalTransactional(name = "create_order", rollbackFor = Exception.class)
    public ApiResponse<OrderVO> createOrder(OrderCreateDTO createDTO) {
        Long userId = UserContext.getCurrentUserId();
        
        // 1. 验证商品信息
        ApiResponse<ProductVO> productResponse = productFeignClient.getProductById(createDTO.getProductId());
        if (!productResponse.getCode().equals(200)) {
            throw new BusinessException("商品不存在");
        }
        
        ProductVO product = productResponse.getData();
        if (product.getStock()  inventoryResponse = inventoryFeignClient.reduceStock(
            createDTO.getProductId(), createDTO.getQuantity());
        if (!inventoryResponse.getCode().equals(200)) {
            throw new BusinessException("库存扣减失败");
        }
        
        // 3. 创建订单
        Order order = new Order();
        order.setOrderNo(generateOrderNo());
        order.setUserId(userId);
        order.setProductId(createDTO.getProductId());
        order.setQuantity(createDTO.getQuantity());
        order.setTotalAmount(product.getPrice().multiply(
            new BigDecimal(createDTO.getQuantity())));
        order.setStatus(OrderStatus.CREATED.getCode());
        order.setCreateTime(new Date());
        
        save(order);
        
        // 4. 发送订单创建消息
        rocketMQTemplate.send("order-create-topic", 
            MessageBuilder.withPayload(order).build());
        
        return ApiResponse.success(convertToVO(order));
    }
    
    private String generateOrderNo() {
        return "ORDER" + System.currentTimeMillis() + 
               String.format("%04d", ThreadLocalRandom.current().nextInt(1000));
    }
}

四、服务治理与配置

4.1 Nacos服务注册与配置

# application.yml
spring:
  application:
    name: user-service
  cloud:
    nacos:
      discovery:
        server-addr: ${NACOS_HOST:localhost}:8848
        namespace: ${NACOS_NAMESPACE:public}
      config:
        server-addr: ${NACOS_HOST:localhost}:8848
        file-extension: yaml
        namespace: ${NACOS_NAMESPACE:public}
        shared-configs:
          - data-id: common.yaml
            refresh: true
          - data-id: datasource.yaml
            refresh: true
          - data-id: redis.yaml
            refresh: true

# bootstrap.yml
spring:
  profiles:
    active: dev
  cloud:
    nacos:
      config:
        group: DEFAULT_GROUP
        prefix: ${spring.application.name}

4.2 Sentinel流量控制配置

@Configuration
public class SentinelConfig {
    
    @PostConstruct
    public void init() {
        // 配置限流规则
        List<FlowRule> rules = new ArrayList();
        
        // 用户登录接口限流
        FlowRule loginRule = new FlowRule();
        loginRule.setResource("userLogin");
        loginRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        loginRule.setCount(10); // 每秒10次
        rules.add(loginRule);
        
        // 商品查询接口限流
        FlowRule productRule = new FlowRule();
        productRule.setResource("getProductById");
        productRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        productRule.setCount(100);
        rules.add(productRule);
        
        FlowRuleManager.loadRules(rules);
    }
}

// 自定义降级处理
@Component
public class CustomBlockExceptionHandler implements BlockExceptionHandler {
    
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, 
                     BlockException e) throws Exception {
        response.setContentType("application/json;charset=utf-8");
        response.setStatus(429);
        
        Map<String, Object> result = new HashMap();
        result.put("code", 429);
        result.put("message", "请求过于频繁,请稍后重试");
        result.put("timestamp", System.currentTimeMillis());
        
        response.getWriter().write(new ObjectMapper().writeValueAsString(result));
    }
}

4.3 Seata分布式事务配置

# seata配置
seata:
  enabled: true
  application-id: ${spring.application.name}
  tx-service-group: default_tx_group
  enable-auto-data-source-proxy: true
  config:
    type: nacos
    nacos:
      server-addr: ${spring.cloud.nacos.discovery.server-addr}
      namespace: ${spring.cloud.nacos.discovery.namespace}
      group: SEATA_GROUP
  registry:
    type: nacos
    nacos:
      server-addr: ${spring.cloud.nacos.discovery.server-addr}
      namespace: ${spring.cloud.nacos.discovery.namespace}
      group: SEATA_GROUP

// 数据源代理配置
@Configuration
public class DataSourceConfiguration {
    
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DruidDataSource druidDataSource() {
        return new DruidDataSource();
    }
    
    @Primary
    @Bean("dataSource")
    public DataSource dataSource(DruidDataSource druidDataSource) {
        return new DataSourceProxy(druidDataSource);
    }
}

五、API网关与安全控制

5.1 Spring Cloud Gateway配置

@Configuration
public class GatewayConfig {
    
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
            .route("user-service", r -> r.path("/api/user/**")
                .filters(f -> f.stripPrefix(1)
                    .addRequestHeader("X-Request-Time", String.valueOf(System.currentTimeMillis()))
                    .circuitBreaker(config -> config.setName("userCircuitBreaker")
                        .setFallbackUri("forward:/fallback/user")))
                .uri("lb://user-service"))
            .route("product-service", r -> r.path("/api/product/**")
                .filters(f -> f.stripPrefix(1)
                    .requestRateLimiter(config -> config.setRateLimiter(redisRateLimiter())
                        .setKeyResolver(userKeyResolver())))
                .uri("lb://product-service"))
            .route("order-service", r -> r.path("/api/order/**")
                .filters(f -> f.stripPrefix(1)
                    .modifyRequestBody(String.class, String.class, 
                        (exchange, s) -> Mono.just(s)))
                .uri("lb://order-service"))
            .build();
    }
    
    @Bean
    public RedisRateLimiter redisRateLimiter() {
        return new RedisRateLimiter(10, 20, 1);
    }
    
    @Bean
    public KeyResolver userKeyResolver() {
        return exchange -> Mono.just(
            exchange.getRequest().getHeaders().getFirst("X-User-Id"));
    }
}

// 全局过滤器
@Component
@Order(-1)
public class AuthFilter implements GlobalFilter {
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");
        
        if (StringUtils.isBlank(token)) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        
        try {
            Claims claims = JwtUtil.parseToken(token.replace("Bearer ", ""));
            String userId = claims.getSubject();
            
            // 将用户信息添加到请求头
            exchange = exchange.mutate()
                .request(builder -> builder.header("X-User-Id", userId))
                .build();
                
        } catch (Exception e) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        
        return chain.filter(exchange);
    }
}

六、部署与监控

6.1 Docker容器化部署

# Dockerfile
FROM openjdk:11-jre-slim
VOLUME /tmp
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]

# docker-compose.yml
version: '3.8'
services:
  nacos:
    image: nacos/nacos-server:2.0.3
    environment:
      - MODE=standalone
    ports:
      - "8848:8848"
  
  redis:
    image: redis:6.2-alpine
    ports:
      - "6379:6379"
  
  mysql:
    image: mysql:8.0
    environment:
      - MYSQL_ROOT_PASSWORD=root
    ports:
      - "3306:3306"
  
  user-service:
    build: ./user-service
    ports:
      - "8081:8080"
    depends_on:
      - nacos
      - redis
      - mysql
  
  product-service:
    build: ./product-service
    ports:
      - "8082:8080"
    depends_on:
      - nacos
      - redis
      - mysql
  
  api-gateway:
    build: ./api-gateway
    ports:
      - "8080:8080"
    depends_on:
      - user-service
      - product-service

6.2 监控与告警

// Spring Boot Actuator配置
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,prometheus
  endpoint:
    health:
      show-details: always
    metrics:
      enabled: true
    prometheus:
      enabled: true

// 自定义健康检查
@Component
public class RedisHealthIndicator implements HealthIndicator {
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    @Override
    public Health health() {
        try {
            String result = redisTemplate.execute((RedisCallback<String>) connection -> 
                connection.ping());
            if ("PONG".equals(result)) {
                return Health.up().withDetail("message", "Redis连接正常").build();
            } else {
                return Health.down().withDetail("error", "Redis连接异常").build();
            }
        } catch (Exception e) {
            return Health.down(e).build();
        }
    }
}

// 业务指标监控
@Component
public class OrderMetrics {
    
    private final MeterRegistry meterRegistry;
    private final Counter orderCreatedCounter;
    private final DistributionSummary orderAmountSummary;
    
    public OrderMetrics(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
        this.orderCreatedCounter = Counter.builder("order.created")
            .description("订单创建数量")
            .register(meterRegistry);
            
        this.orderAmountSummary = DistributionSummary.builder("order.amount")
            .description("订单金额分布")
            .register(meterRegistry);
    }
    
    public void recordOrderCreated(Order order) {
        orderCreatedCounter.increment();
        orderAmountSummary.record(order.getTotalAmount().doubleValue());
        
        // 记录标签信息
        meterRegistry.counter("order.created.by.user", 
            "userId", order.getUserId().toString())
            .increment();
    }
}

七、总结与最佳实践

通过本实战教程,我们构建了一个基于Spring Cloud Alibaba的完整电商微服务系统,涵盖了:

  • 微服务拆分:合理的服务边界划分和职责分离
  • 服务治理:Nacos实现服务注册发现和配置管理
  • 流量控制:Sentinel实现熔断降级和流量控制
  • 分布式事务:Seata保证数据一致性
  • 消息队列:RocketMQ实现异步解耦
  • API网关:统一入口和安全控制
  • 监控告警:完整的可观测性方案

生产环境建议:

  1. 使用Kubernetes进行容器编排和管理
  2. 实现蓝绿部署或金丝雀发布
  3. 建立完善的日志收集和分析系统
  4. 配置APM系统进行性能监控
  5. 建立CI/CD流水线自动化部署
  6. 定期进行压力测试和性能优化

这个电商平台架构具有良好的扩展性和可维护性,可以作为企业级微服务架构的参考实现。

Java微服务架构实战:Spring Cloud Alibaba分布式电商平台开发指南
收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

淘吗网 java Java微服务架构实战:Spring Cloud Alibaba分布式电商平台开发指南 https://www.taomawang.com/server/java/945.html

常见问题

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务