Java学习第25天 - Spring Cloud Alibaba微服务生态

学习目标

掌握Spring Cloud Alibaba完整微服务生态,学习Nacos服务注册发现和配置管理,掌握Sentinel流量控制和熔断降级,了解Seata分布式事务解决方案,掌握RocketMQ消息队列中间件。


1. Spring Cloud Alibaba生态体系

1.1 Alibaba微服务架构概述

核心组件:

  • Nacos:服务注册发现和配置管理
  • Sentinel:流量控制和熔断降级
  • Seata:分布式事务解决方案
  • RocketMQ:消息队列中间件
  • Dubbo:RPC框架
  • Spring Cloud Gateway:API网关

代码示例:

java 复制代码
// 父项目pom.xml
<?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.example</groupId>
    <artifactId>spring-cloud-alibaba-demo</artifactId>
    <version>1.0.0</version>
    <packaging>pom</packaging>
    
    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <spring-boot.version>2.7.14</spring-boot.version>
        <spring-cloud.version>2021.0.8</spring-cloud.version>
        <spring-cloud-alibaba.version>2021.0.5.0</spring-cloud-alibaba.version>
    </properties>
    
    <dependencyManagement>
        <dependencies>
            <!-- Spring Boot -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            
            <!-- Spring Cloud -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            
            <!-- Spring Cloud Alibaba -->
            <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>
    
    <modules>
        <module>nacos-server</module>
        <module>user-service</module>
        <module>order-service</module>
        <module>notification-service</module>
        <module>api-gateway</module>
    </modules>
</project>

// 微服务通用依赖
<dependencies>
    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <!-- Spring Boot Starter Actuator -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    
    <!-- Nacos Discovery -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    
    <!-- Nacos Config -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    </dependency>
    
    <!-- Sentinel -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    </dependency>
    
    <!-- Seata -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
    </dependency>
    
    <!-- RocketMQ -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-stream-rocketmq</artifactId>
    </dependency>
    
    <!-- MyBatis Plus -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.5.3.1</version>
    </dependency>
    
    <!-- MySQL Connector -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    
    <!-- Lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

1.2 微服务架构设计

服务拆分策略:

java 复制代码
// 用户服务 - 用户管理
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class UserServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }
}

// 订单服务 - 订单管理
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class, args);
    }
}

// 通知服务 - 消息通知
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class NotificationServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(NotificationServiceApplication.class, args);
    }
}

// API网关
@SpringBootApplication
@EnableDiscoveryClient
public class ApiGatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(ApiGatewayApplication.class, args);
    }
}

2. Nacos服务注册发现和配置管理

2.1 Nacos服务注册发现

Nacos客户端配置:

yaml 复制代码
# application.yml
spring:
  application:
    name: user-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
        namespace: dev
        group: DEFAULT_GROUP
        cluster-name: BJ
        metadata:
          version: 1.0.0
          region: beijing
      config:
        server-addr: localhost:8848
        namespace: dev
        group: DEFAULT_GROUP
        file-extension: yml
        shared-configs:
          - data-id: common-config.yml
            group: SHARED_GROUP
            refresh: true
          - data-id: database-config.yml
            group: SHARED_GROUP
            refresh: true

server:
  port: 8081

management:
  endpoints:
    web:
      exposure:
        include: "*"

服务注册配置:

java 复制代码
// Nacos配置类
@Configuration
@EnableDiscoveryClient
@Slf4j
public class NacosConfig {
    
    @Autowired
    private NacosDiscoveryProperties nacosDiscoveryProperties;
    
    @PostConstruct
    public void init() {
        log.info("Nacos配置初始化完成");
        log.info("服务名称: {}", nacosDiscoveryProperties.getService());
        log.info("服务地址: {}", nacosDiscoveryProperties.getServerAddr());
        log.info("命名空间: {}", nacosDiscoveryProperties.getNamespace());
        log.info("分组: {}", nacosDiscoveryProperties.getGroup());
    }
    
    @Bean
    public NacosServiceRegistry nacosServiceRegistry() {
        return new NacosServiceRegistry(nacosDiscoveryProperties);
    }
}

// 服务健康检查
@Component
@Slf4j
public class ServiceHealthChecker {
    
    @Autowired
    private NacosDiscoveryProperties nacosDiscoveryProperties;
    
    @Autowired
    private NacosServiceManager nacosServiceManager;
    
    @Scheduled(fixedRate = 30000)
    public void checkServiceHealth() {
        try {
            String serviceName = nacosDiscoveryProperties.getService();
            String groupName = nacosDiscoveryProperties.getGroup();
            String clusterName = nacosDiscoveryProperties.getClusterName();
            
            List<Instance> instances = nacosServiceManager
                .getNamingService()
                .selectInstances(serviceName, groupName, true);
            
            log.info("服务健康检查 - 服务名: {}, 实例数: {}", serviceName, instances.size());
            
            for (Instance instance : instances) {
                log.info("实例信息 - IP: {}, Port: {}, 健康状态: {}", 
                    instance.getIp(), instance.getPort(), instance.isHealthy());
            }
        } catch (Exception e) {
            log.error("服务健康检查失败", e);
        }
    }
}

2.2 Nacos配置管理

配置中心集成:

java 复制代码
// 配置刷新监听器
@Component
@Slf4j
public class ConfigRefreshListener {
    
    @NacosConfigListener(dataId = "user-service.yml", groupId = "DEFAULT_GROUP")
    public void onConfigChange(String configInfo) {
        log.info("配置发生变化: {}", configInfo);
        // 处理配置变化逻辑
    }
    
    @NacosConfigListener(dataId = "database-config.yml", groupId = "SHARED_GROUP")
    public void onDatabaseConfigChange(String configInfo) {
        log.info("数据库配置发生变化: {}", configInfo);
        // 重新初始化数据源
    }
}

// 动态配置属性
@Component
@ConfigurationProperties(prefix = "user")
@NacosConfigurationProperties(dataId = "user-service.yml", groupId = "DEFAULT_GROUP", autoRefreshed = true)
@Data
public class UserConfig {
    
    private String defaultRole = "USER";
    private Integer maxLoginAttempts = 5;
    private Long sessionTimeout = 3600L;
    private Boolean enableEmailVerification = true;
    private String emailTemplate = "default";
    
    @PostConstruct
    public void init() {
        log.info("用户配置初始化完成: {}", this);
    }
}

// 配置管理服务
@Service
@Slf4j
public class ConfigManagementService {
    
    @Autowired
    private ConfigService configService;
    
    public void updateConfig(String dataId, String group, String content) {
        try {
            boolean result = configService.publishConfig(dataId, group, content);
            log.info("配置更新结果: {}", result);
        } catch (NacosException e) {
            log.error("配置更新失败", e);
        }
    }
    
    public String getConfig(String dataId, String group) {
        try {
            return configService.getConfig(dataId, group, 5000);
        } catch (NacosException e) {
            log.error("获取配置失败", e);
            return null;
        }
    }
    
    public void deleteConfig(String dataId, String group) {
        try {
            boolean result = configService.removeConfig(dataId, group);
            log.info("配置删除结果: {}", result);
        } catch (NacosException e) {
            log.error("配置删除失败", e);
        }
    }
}

2.3 服务发现和负载均衡

Feign客户端配置:

java 复制代码
// 用户服务Feign客户端
@FeignClient(name = "user-service", fallback = UserServiceFallback.class)
public interface UserServiceClient {
    
    @GetMapping("/api/users/{id}")
    User getUserById(@PathVariable("id") Long id);
    
    @PostMapping("/api/users")
    User createUser(@RequestBody User user);
    
    @PutMapping("/api/users/{id}")
    User updateUser(@PathVariable("id") Long id, @RequestBody User user);
    
    @DeleteMapping("/api/users/{id}")
    void deleteUser(@PathVariable("id") Long id);
    
    @GetMapping("/api/users/search")
    List<User> searchUsers(@RequestParam("keyword") String keyword);
}

// 用户服务降级处理
@Component
@Slf4j
public class UserServiceFallback implements UserServiceClient {
    
    @Override
    public User getUserById(Long id) {
        log.warn("用户服务调用失败,使用降级处理: {}", id);
        return User.builder()
            .id(id)
            .username("unknown")
            .email("unknown@example.com")
            .status(UserStatus.INACTIVE)
            .build();
    }
    
    @Override
    public User createUser(User user) {
        log.warn("用户服务调用失败,使用降级处理");
        throw new ServiceUnavailableException("用户服务暂时不可用");
    }
    
    @Override
    public User updateUser(Long id, User user) {
        log.warn("用户服务调用失败,使用降级处理: {}", id);
        throw new ServiceUnavailableException("用户服务暂时不可用");
    }
    
    @Override
    public void deleteUser(Long id) {
        log.warn("用户服务调用失败,使用降级处理: {}", id);
        throw new ServiceUnavailableException("用户服务暂时不可用");
    }
    
    @Override
    public List<User> searchUsers(String keyword) {
        log.warn("用户服务调用失败,使用降级处理: {}", keyword);
        return Collections.emptyList();
    }
}

// 负载均衡配置
@Configuration
public class LoadBalancerConfig {
    
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
    
    @Bean
    public IRule loadBalancerRule() {
        return new RoundRobinRule(); // 轮询策略
    }
    
    @Bean
    public IPing loadBalancerPing() {
        return new PingUrl();
    }
}

3. Sentinel流量控制和熔断降级

3.1 Sentinel基础配置

Sentinel配置:

yaml 复制代码
# application.yml
spring:
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8080
        port: 8719
      datasource:
        ds1:
          nacos:
            server-addr: localhost:8848
            data-id: sentinel-rules.yml
            group-id: SENTINEL_GROUP
            rule-type: flow
        ds2:
          nacos:
            server-addr: localhost:8848
            data-id: sentinel-degrade-rules.yml
            group-id: SENTINEL_GROUP
            rule-type: degrade
      web-context-unify: false
      eager: true

# 自定义配置
sentinel:
  flow:
    rules:
      - resource: getUserById
        count: 100
        grade: 1
        strategy: 0
        control-behavior: 0
      - resource: createUser
        count: 50
        grade: 1
        strategy: 0
        control-behavior: 0
  degrade:
    rules:
      - resource: getUserById
        count: 0.5
        grade: 2
        timeWindow: 10
        minRequestAmount: 5

Sentinel规则配置:

java 复制代码
// Sentinel配置类
@Configuration
@EnableSentinel
@Slf4j
public class SentinelConfig {
    
    @PostConstruct
    public void initRules() {
        initFlowRules();
        initDegradeRules();
        initSystemRules();
        initAuthorityRules();
    }
    
    private void initFlowRules() {
        List<FlowRule> rules = new ArrayList<>();
        
        // 用户查询限流规则
        FlowRule userQueryRule = new FlowRule();
        userQueryRule.setResource("getUserById");
        userQueryRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        userQueryRule.setCount(100);
        userQueryRule.setStrategy(RuleConstant.STRATEGY_DIRECT);
        userQueryRule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);
        rules.add(userQueryRule);
        
        // 用户创建限流规则
        FlowRule userCreateRule = new FlowRule();
        userCreateRule.setResource("createUser");
        userCreateRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        userCreateRule.setCount(50);
        userCreateRule.setStrategy(RuleConstant.STRATEGY_DIRECT);
        userCreateRule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);
        rules.add(userCreateRule);
        
        FlowRuleManager.loadRules(rules);
        log.info("流量控制规则加载完成");
    }
    
    private void initDegradeRules() {
        List<DegradeRule> rules = new ArrayList<>();
        
        // 用户服务降级规则
        DegradeRule userServiceRule = new DegradeRule();
        userServiceRule.setResource("getUserById");
        userServiceRule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
        userServiceRule.setCount(100); // 平均响应时间超过100ms
        userServiceRule.setTimeWindow(10); // 熔断时长10秒
        userServiceRule.setMinRequestAmount(5); // 最小请求数
        userServiceRule.setStatIntervalMs(1000); // 统计时长
        rules.add(userServiceRule);
        
        DegradeRuleManager.loadRules(rules);
        log.info("熔断降级规则加载完成");
    }
    
    private void initSystemRules() {
        List<SystemRule> rules = new ArrayList<>();
        
        // 系统保护规则
        SystemRule systemRule = new SystemRule();
        systemRule.setHighestSystemLoad(3.0); // 系统负载
        systemRule.setHighestCpuUsage(0.8); // CPU使用率
        systemRule.setQps(1000); // QPS
        systemRule.setRt(100); // 平均响应时间
        systemRule.setMaxThread(200); // 最大线程数
        rules.add(systemRule);
        
        SystemRuleManager.loadRules(rules);
        log.info("系统保护规则加载完成");
    }
    
    private void initAuthorityRules() {
        List<AuthorityRule> rules = new ArrayList<>();
        
        // 白名单规则
        AuthorityRule whitelistRule = new AuthorityRule();
        whitelistRule.setResource("getUserById");
        whitelistRule.setStrategy(RuleConstant.AUTHORITY_WHITE);
        whitelistRule.setLimitApp("admin,user");
        rules.add(whitelistRule);
        
        AuthorityRuleManager.loadRules(rules);
        log.info("授权规则加载完成");
    }
}

3.2 流量控制和熔断降级实现

服务层流量控制:

java 复制代码
// 用户服务实现
@Service
@Slf4j
public class UserServiceImpl implements UserService {
    
    @Autowired
    private UserMapper userMapper;
    
    @Override
    @SentinelResource(
        value = "getUserById",
        fallback = "getUserByIdFallback",
        blockHandler = "getUserByIdBlockHandler",
        exceptionsToIgnore = {IllegalArgumentException.class}
    )
    public User getUserById(Long id) {
        log.info("查询用户信息: {}", id);
        
        if (id == null || id <= 0) {
            throw new IllegalArgumentException("用户ID不能为空或小于等于0");
        }
        
        User user = userMapper.selectById(id);
        if (user == null) {
            throw new UserNotFoundException("用户不存在");
        }
        
        return user;
    }
    
    // 降级处理方法
    public User getUserByIdFallback(Long id, Throwable ex) {
        log.warn("用户查询降级处理: {}, 异常: {}", id, ex.getMessage());
        return User.builder()
            .id(id)
            .username("unknown")
            .email("unknown@example.com")
            .status(UserStatus.INACTIVE)
            .build();
    }
    
    // 限流处理方法
    public User getUserByIdBlockHandler(Long id, BlockException ex) {
        log.warn("用户查询限流处理: {}, 异常: {}", id, ex.getMessage());
        throw new RateLimitExceededException("请求过于频繁,请稍后重试");
    }
    
    @Override
    @SentinelResource(
        value = "createUser",
        fallback = "createUserFallback",
        blockHandler = "createUserBlockHandler"
    )
    public User createUser(User user) {
        log.info("创建用户: {}", user.getUsername());
        
        // 参数验证
        validateUser(user);
        
        // 检查用户名是否已存在
        if (userMapper.selectByUsername(user.getUsername()) != null) {
            throw new UserAlreadyExistsException("用户名已存在");
        }
        
        // 设置默认值
        user.setStatus(UserStatus.ACTIVE);
        user.setCreatedAt(LocalDateTime.now());
        user.setUpdatedAt(LocalDateTime.now());
        
        // 密码加密
        user.setPassword(BCrypt.hashpw(user.getPassword(), BCrypt.gensalt()));
        
        int result = userMapper.insert(user);
        if (result <= 0) {
            throw new UserCreationException("用户创建失败");
        }
        
        return user;
    }
    
    // 创建用户降级处理
    public User createUserFallback(User user, Throwable ex) {
        log.warn("用户创建降级处理: {}, 异常: {}", user.getUsername(), ex.getMessage());
        throw new ServiceUnavailableException("用户服务暂时不可用");
    }
    
    // 创建用户限流处理
    public User createUserBlockHandler(User user, BlockException ex) {
        log.warn("用户创建限流处理: {}, 异常: {}", user.getUsername(), ex.getMessage());
        throw new RateLimitExceededException("请求过于频繁,请稍后重试");
    }
    
    private void validateUser(User user) {
        if (user == null) {
            throw new IllegalArgumentException("用户信息不能为空");
        }
        if (StringUtils.isBlank(user.getUsername())) {
            throw new IllegalArgumentException("用户名不能为空");
        }
        if (StringUtils.isBlank(user.getEmail())) {
            throw new IllegalArgumentException("邮箱不能为空");
        }
        if (StringUtils.isBlank(user.getPassword())) {
            throw new IllegalArgumentException("密码不能为空");
        }
    }
}

3.3 自定义流量控制规则

动态规则管理:

java 复制代码
// 动态规则管理服务
@Service
@Slf4j
public class SentinelRuleManagementService {
    
    @Autowired
    private NacosConfigService nacosConfigService;
    
    public void updateFlowRule(String resource, int count, int grade) {
        try {
            // 构建流量控制规则
            FlowRule rule = new FlowRule();
            rule.setResource(resource);
            rule.setGrade(grade);
            rule.setCount(count);
            rule.setStrategy(RuleConstant.STRATEGY_DIRECT);
            rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);
            
            // 更新规则
            List<FlowRule> rules = new ArrayList<>();
            rules.add(rule);
            FlowRuleManager.loadRules(rules);
            
            // 同步到Nacos
            syncRulesToNacos(resource, count, grade);
            
            log.info("流量控制规则更新成功: resource={}, count={}, grade={}", 
                resource, count, grade);
        } catch (Exception e) {
            log.error("流量控制规则更新失败", e);
        }
    }
    
    public void updateDegradeRule(String resource, double count, int grade, int timeWindow) {
        try {
            // 构建熔断降级规则
            DegradeRule rule = new DegradeRule();
            rule.setResource(resource);
            rule.setGrade(grade);
            rule.setCount(count);
            rule.setTimeWindow(timeWindow);
            rule.setMinRequestAmount(5);
            rule.setStatIntervalMs(1000);
            
            // 更新规则
            List<DegradeRule> rules = new ArrayList<>();
            rules.add(rule);
            DegradeRuleManager.loadRules(rules);
            
            // 同步到Nacos
            syncDegradeRulesToNacos(resource, count, grade, timeWindow);
            
            log.info("熔断降级规则更新成功: resource={}, count={}, grade={}, timeWindow={}", 
                resource, count, grade, timeWindow);
        } catch (Exception e) {
            log.error("熔断降级规则更新失败", e);
        }
    }
    
    private void syncRulesToNacos(String resource, int count, int grade) {
        try {
            String ruleContent = String.format(
                "[{\"resource\":\"%s\",\"grade\":%d,\"count\":%d,\"strategy\":0,\"controlBehavior\":0}]",
                resource, grade, count
            );
            
            nacosConfigService.publishConfig(
                "sentinel-flow-rules.yml",
                "SENTINEL_GROUP",
                ruleContent
            );
        } catch (Exception e) {
            log.error("同步流量控制规则到Nacos失败", e);
        }
    }
    
    private void syncDegradeRulesToNacos(String resource, double count, int grade, int timeWindow) {
        try {
            String ruleContent = String.format(
                "[{\"resource\":\"%s\",\"grade\":%d,\"count\":%.2f,\"timeWindow\":%d,\"minRequestAmount\":5,\"statIntervalMs\":1000}]",
                resource, grade, count, timeWindow
            );
            
            nacosConfigService.publishConfig(
                "sentinel-degrade-rules.yml",
                "SENTINEL_GROUP",
                ruleContent
            );
        } catch (Exception e) {
            log.error("同步熔断降级规则到Nacos失败", e);
        }
    }
}

4. Seata分布式事务解决方案

4.1 Seata配置和集成

Seata配置:

yaml 复制代码
# application.yml
spring:
  cloud:
    alibaba:
      seata:
        enabled: true
        application-id: user-service
        tx-service-group: my_test_tx_group
        service:
          vgroup-mapping:
            my_test_tx_group: default
          grouplist:
            default: 127.0.0.1:8091
        client:
          rm:
            async-commit-buffer-limit: 10000
            report-retry-count: 5
            table-meta-check-enable: false
            report-success-enable: false
            saga-branch-register-enable: false
            saga-json-parser: fastjson
            lock:
              retry-policy-branch-rollback-on-conflict: true
              retry-times: 30
              retry-policy-branch-rollback-on-conflict: true
          tm:
            commit-retry-count: 5
            rollback-retry-count: 5
            default-global-transaction-timeout: 60000
            degrade-check: false
            degrade-check-allow-times: 10
            degrade-check-period: 2000
          undo:
            data-validation: true
            log-serialization: jackson
            log-table: undo_log
            only-care-update-columns: true
          log:
            exceptionRate: 100

seata:
  enabled: true
  application-id: user-service
  tx-service-group: my_test_tx_group
  service:
    vgroup-mapping:
      my_test_tx_group: default
    grouplist:
      default: 127.0.0.1:8091
  client:
    rm:
      async-commit-buffer-limit: 10000
      report-retry-count: 5
      table-meta-check-enable: false
      report-success-enable: false
      saga-branch-register-enable: false
      saga-json-parser: fastjson
      lock:
        retry-policy-branch-rollback-on-conflict: true
        retry-times: 30
    tm:
      commit-retry-count: 5
      rollback-retry-count: 5
      default-global-transaction-timeout: 60000
      degrade-check: false
      degrade-check-allow-times: 10
      degrade-check-period: 2000
    undo:
      data-validation: true
      log-serialization: jackson
      log-table: undo_log
      only-care-update-columns: true
    log:
      exceptionRate: 100

Seata配置类:

java 复制代码
// Seata配置类
@Configuration
@EnableSeata
@Slf4j
public class SeataConfig {
    
    @Bean
    public GlobalTransactionScanner globalTransactionScanner() {
        return new GlobalTransactionScanner("user-service", "my_test_tx_group");
    }
    
    @Bean
    public DataSourceProxy dataSourceProxy(DataSource dataSource) {
        return new DataSourceProxy(dataSource);
    }
    
    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSourceProxy dataSourceProxy) throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dataSourceProxy);
        factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
            .getResources("classpath*:mapper/*.xml"));
        return factoryBean.getObject();
    }
}

4.2 分布式事务实现

AT模式实现:

java 复制代码
// 订单服务 - 分布式事务
@Service
@Slf4j
public class OrderService {
    
    @Autowired
    private OrderMapper orderMapper;
    
    @Autowired
    private UserServiceClient userServiceClient;
    
    @Autowired
    private InventoryServiceClient inventoryServiceClient;
    
    @Autowired
    private PaymentServiceClient paymentServiceClient;
    
    @GlobalTransactional(rollbackFor = Exception.class)
    public Order createOrder(OrderRequest request) {
        log.info("开始创建订单: {}", request);
        
        try {
            // 1. 验证用户
            User user = validateUser(request.getUserId());
            log.info("用户验证成功: {}", user.getUsername());
            
            // 2. 检查库存
            Inventory inventory = checkInventory(request.getProductId(), request.getQuantity());
            log.info("库存检查成功: 产品ID={}, 可用库存={}", 
                request.getProductId(), inventory.getAvailableQuantity());
            
            // 3. 扣减库存
            boolean inventoryResult = inventoryServiceClient.deductInventory(
                request.getProductId(), request.getQuantity());
            if (!inventoryResult) {
                throw new InventoryInsufficientException("库存不足");
            }
            log.info("库存扣减成功");
            
            // 4. 处理支付
            PaymentResult payment = paymentServiceClient.processPayment(
                request.getPaymentMethod(), request.getAmount());
            if (!payment.isSuccess()) {
                throw new PaymentFailedException("支付失败: " + payment.getMessage());
            }
            log.info("支付处理成功: 交易ID={}", payment.getTransactionId());
            
            // 5. 创建订单
            Order order = buildOrder(request, user, payment);
            int result = orderMapper.insert(order);
            if (result <= 0) {
                throw new OrderCreationException("订单创建失败");
            }
            log.info("订单创建成功: 订单ID={}", order.getId());
            
            return order;
        } catch (Exception e) {
            log.error("订单创建失败,事务回滚", e);
            throw e;
        }
    }
    
    private User validateUser(Long userId) {
        User user = userServiceClient.getUserById(userId);
        if (user == null) {
            throw new UserNotFoundException("用户不存在");
        }
        if (user.getStatus() != UserStatus.ACTIVE) {
            throw new UserInactiveException("用户状态异常");
        }
        return user;
    }
    
    private Inventory checkInventory(Long productId, Integer quantity) {
        Inventory inventory = inventoryServiceClient.getInventory(productId);
        if (inventory == null) {
            throw new ProductNotFoundException("产品不存在");
        }
        if (inventory.getAvailableQuantity() < quantity) {
            throw new InventoryInsufficientException("库存不足");
        }
        return inventory;
    }
    
    private Order buildOrder(OrderRequest request, User user, PaymentResult payment) {
        Order order = new Order();
        order.setId(request.getOrderId());
        order.setUserId(request.getUserId());
        order.setProductId(request.getProductId());
        order.setQuantity(request.getQuantity());
        order.setAmount(request.getAmount());
        order.setStatus(OrderStatus.PENDING);
        order.setPaymentMethod(request.getPaymentMethod());
        order.setTransactionId(payment.getTransactionId());
        order.setCreatedAt(LocalDateTime.now());
        order.setUpdatedAt(LocalDateTime.now());
        return order;
    }
}

4.3 Saga模式实现

Saga事务编排:

java 复制代码
// Saga事务编排器
@Component
@Slf4j
public class OrderSagaOrchestrator {
    
    @Autowired
    private UserServiceClient userServiceClient;
    
    @Autowired
    private InventoryServiceClient inventoryServiceClient;
    
    @Autowired
    private PaymentServiceClient paymentServiceClient;
    
    @Autowired
    private OrderMapper orderMapper;
    
    public OrderResult processOrder(OrderRequest request) {
        log.info("开始Saga事务处理: {}", request);
        
        List<SagaStep> steps = new ArrayList<>();
        OrderResult result = new OrderResult();
        
        try {
            // 步骤1: 验证用户
            SagaStep userValidationStep = new SagaStep(
                "validateUser",
                () -> validateUser(request.getUserId()),
                () -> compensateUserValidation(request.getUserId())
            );
            steps.add(userValidationStep);
            User user = (User) userValidationStep.execute();
            result.setUser(user);
            
            // 步骤2: 检查库存
            SagaStep inventoryCheckStep = new SagaStep(
                "checkInventory",
                () -> checkInventory(request.getProductId(), request.getQuantity()),
                () -> compensateInventoryCheck(request.getProductId(), request.getQuantity())
            );
            steps.add(inventoryCheckStep);
            Inventory inventory = (Inventory) inventoryCheckStep.execute();
            result.setInventory(inventory);
            
            // 步骤3: 扣减库存
            SagaStep inventoryDeductStep = new SagaStep(
                "deductInventory",
                () -> deductInventory(request.getProductId(), request.getQuantity()),
                () -> compensateInventoryDeduction(request.getProductId(), request.getQuantity())
            );
            steps.add(inventoryDeductStep);
            Boolean inventoryResult = (Boolean) inventoryDeductStep.execute();
            result.setInventoryDeducted(inventoryResult);
            
            // 步骤4: 处理支付
            SagaStep paymentStep = new SagaStep(
                "processPayment",
                () -> processPayment(request.getPaymentMethod(), request.getAmount()),
                () -> compensatePayment(request.getPaymentMethod(), request.getAmount())
            );
            steps.add(paymentStep);
            PaymentResult payment = (PaymentResult) paymentStep.execute();
            result.setPayment(payment);
            
            // 步骤5: 创建订单
            SagaStep orderCreationStep = new SagaStep(
                "createOrder",
                () -> createOrder(request, user, payment),
                () -> compensateOrderCreation(request.getOrderId())
            );
            steps.add(orderCreationStep);
            Order order = (Order) orderCreationStep.execute();
            result.setOrder(order);
            
            result.setSuccess(true);
            log.info("Saga事务处理成功: 订单ID={}", order.getId());
            
        } catch (Exception e) {
            log.error("Saga事务处理失败,开始补偿", e);
            compensateSteps(steps);
            result.setSuccess(false);
            result.setErrorMessage(e.getMessage());
        }
        
        return result;
    }
    
    private void compensateSteps(List<SagaStep> steps) {
        // 逆序执行补偿操作
        for (int i = steps.size() - 1; i >= 0; i--) {
            try {
                steps.get(i).compensate();
                log.info("补偿操作执行成功: {}", steps.get(i).getName());
            } catch (Exception e) {
                log.error("补偿操作执行失败: {}", steps.get(i).getName(), e);
            }
        }
    }
    
    // 补偿方法实现
    private void compensateUserValidation(Long userId) {
        log.info("用户验证补偿: {}", userId);
        // 用户验证失败无需补偿
    }
    
    private void compensateInventoryCheck(Long productId, Integer quantity) {
        log.info("库存检查补偿: 产品ID={}, 数量={}", productId, quantity);
        // 库存检查失败无需补偿
    }
    
    private void compensateInventoryDeduction(Long productId, Integer quantity) {
        log.info("库存扣减补偿: 产品ID={}, 数量={}", productId, quantity);
        try {
            inventoryServiceClient.restoreInventory(productId, quantity);
        } catch (Exception e) {
            log.error("库存恢复失败", e);
        }
    }
    
    private void compensatePayment(String paymentMethod, BigDecimal amount) {
        log.info("支付补偿: 支付方式={}, 金额={}", paymentMethod, amount);
        try {
            paymentServiceClient.refund(paymentMethod, amount);
        } catch (Exception e) {
            log.error("支付退款失败", e);
        }
    }
    
    private void compensateOrderCreation(Long orderId) {
        log.info("订单创建补偿: 订单ID={}", orderId);
        try {
            orderMapper.deleteById(orderId);
        } catch (Exception e) {
            log.error("订单删除失败", e);
        }
    }
}

5. RocketMQ消息队列中间件

5.1 RocketMQ配置和集成

RocketMQ配置:

yaml 复制代码
# application.yml
spring:
  cloud:
    stream:
      rocketmq:
        binder:
          name-server: localhost:9876
          access-key: your-access-key
          secret-key: your-secret-key
        bindings:
          order-output:
            producer:
              group: order-producer-group
              transactional: true
          order-input:
            consumer:
              group: order-consumer-group
              subscription: order-topic
              message-model: cluster
              consume-mode: concurrently
              consume-thread-min: 20
              consume-thread-max: 64
              max-reconsume-times: 16
              consume-timeout: 15m
              pull-batch-size: 32
              pull-interval: 0
              pull-threshold-for-queue: 1000
              pull-threshold-for-topic: -1
              pull-threshold-size-for-queue: 100
              pull-threshold-size-for-topic: -1
              consume-message-batch-max-size: 1
              max-reconsume-times: 16
              consume-timeout: 15m
              pull-batch-size: 32
              pull-interval: 0
              pull-threshold-for-queue: 1000
              pull-threshold-for-topic: -1
              pull-threshold-size-for-queue: 100
              pull-threshold-size-for-topic: -1
              consume-message-batch-max-size: 1
相关推荐
Cg136269159743 小时前
Super的详解
java
毕设源码-朱学姐4 小时前
【开题答辩全过程】以 便利店库存管理系统为例,包含答辩的问题和答案
java·eclipse
Nero184 小时前
代码随想录二刷第九天 | 232.用栈实现队列、225. 用队列实现栈、20. 有效的括号、1047. 删除字符串中的所有相邻重复项
java
泉城老铁4 小时前
tomcat 部署springboot,线程经常断开导致数据库连接池关闭,如何解决
java·spring boot·后端
Nero184 小时前
代码随想录二刷第八天 | 28. 实现 strStr()、459.重复的子字符串
java
Le1Yu4 小时前
配置管理的配置与拉取、热更新的配置、动态路由
java
Seven974 小时前
剑指offer-34、第⼀次出现的字符
java
摇滚侠4 小时前
Spring Boot 3零基础教程,properties文件中配置和类的属性绑定,笔记14
java·spring boot·笔记
星光一影4 小时前
HIS系统天花板,十大核心模块,门诊/住院/医保全流程打通,医院数字化转型首选
java·spring boot·后端·sql·elementui·html·scss