学习目标
掌握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