分布式系统设计与实战:Java 微服务架构落地
分布式系统与微服务架构的核心概念及设计原则,重点讲解基于 Spring Cloud Alibaba 生态的实战落地。内容包括 DDD 领域驱动设计的服务拆分,Nacos 服务注册与配置中心,Sentinel 熔断限流,OpenFeign 同步通信,RocketMQ 异步消息等核心组件应用。通过电商微服务案例演示订单创建全流程、库存扣减及分布式事务解决方案,帮助开发者掌握高可用、高扩展的微服务系统设计方法。

分布式系统与微服务架构的核心概念及设计原则,重点讲解基于 Spring Cloud Alibaba 生态的实战落地。内容包括 DDD 领域驱动设计的服务拆分,Nacos 服务注册与配置中心,Sentinel 熔断限流,OpenFeign 同步通信,RocketMQ 异步消息等核心组件应用。通过电商微服务案例演示订单创建全流程、库存扣减及分布式事务解决方案,帮助开发者掌握高可用、高扩展的微服务系统设计方法。

💡 分布式系统是由多个独立的计算机(节点)通过网络连接,协同完成一个共同任务的系统。每个节点都有自己的硬件和软件,节点间通过网络进行通信和数据交换,对外呈现为一个统一的整体。
💡 微服务架构是分布式系统的一种具体实现方式,它将一个大型应用拆分为多个小型、独立的服务,每个服务聚焦于完成一个特定的业务功能(如用户服务、订单服务、支付服务),服务间通过轻量级通信协议(如 HTTP、RPC)交互。
| 特性 | 单体架构 | 微服务架构 |
|---|---|---|
| 架构复杂度 | 低(所有功能集成在一个应用) | 高(多个独立服务协同) |
| 开发效率(初期) | 高(无需关注服务拆分与通信) | 低(需设计服务拆分、通信等) |
| 开发效率(后期) | 低(代码量庞大,维护困难) | 高(服务独立维护,迭代灵活) |
| 扩展性 | 差(只能垂直扩展,成本高) | 好(支持横向扩展,按需扩容) |
| 可用性 | 差(单个模块故障导致整个应用崩溃) | 好(单个服务故障不影响其他服务) |
| 部署成本 | 低(一次部署整个应用) | 高(需部署多个服务,依赖 DevOps 支持) |
💡 微服务拆分的核心是按业务领域划分,而 DDD(Domain-Driven Design,领域驱动设计)是实现这一目标的最佳实践。DDD 通过将业务领域拆分为多个限界上下文(Bounded Context),每个限界上下文对应一个微服务。
① 梳理业务领域:明确电商系统的核心业务流程,如用户注册→商品浏览→加入购物车→下单→支付→物流配送。 ② 划分限界上下文:根据业务独立性拆分限界上下文,电商系统可拆分为:
⚠️ 注意:微服务拆分不可过细或过粗。拆分过细会导致服务间通信频繁、系统复杂度飙升;拆分过粗则退化为'分布式单体',无法发挥微服务优势。
💡 Spring Cloud Alibaba 是阿里巴巴基于 Spring Cloud 开发的微服务生态组件,兼容 Spring Cloud 标准,提供了服务注册发现、配置中心、熔断限流、分布式事务等一站式解决方案,目前已成为国内最主流的微服务开发框架。
核心组件包括:
① 安装 Nacos:
startup.cmd -m standalone(单机模式),Linux/Mac 执行 sh startup.sh -m standalone。② 安装 Sentinel Dashboard:
java -jar sentinel-dashboard-1.8.6.jar 启动控制台(默认端口 8080)。💡 Nacos 同时提供服务注册发现和配置管理功能,支持基于 DNS 和 RPC 的服务发现,适配各种场景下的服务注册与调用。
① 创建 Maven 项目,引入核心依赖:
<!-- Spring Boot 父依赖 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.15</version>
<relativePath/>
</parent>
<!-- Spring Cloud Alibaba 依赖管理 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2021.0.4.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Spring Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Nacos 服务注册发现 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
② 编写配置文件 application.yml:
spring:
application:
name: user-service # 服务名称(注册到 Nacos 的服务名)
cloud:
nacos:
discovery:
server-addr: localhost:8848 # Nacos 服务地址
server:
port: 8081 # 服务端口
③ 编写启动类:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient // 开启服务注册发现功能(Spring Cloud 2020+ 可省略)
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}
④ 编写业务接口(用户查询接口):
import lombok.Data;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
// 模拟数据库查询用户信息
@GetMapping("/user/{id}")
public User getUserById(@PathVariable Long id) {
// 实际开发中应从数据库查询,此处模拟数据
User user = new User();
user.setId(id);
user.setUsername("张三" + id);
user.setPhone("1380013800" + id % 10);
user.setAddress("北京市朝阳区");
return user;
}
// 用户实体类
@Data
static class User {
private Long id;
private String username;
private String phone;
private String address;
}
}
⑤ 启动服务:运行 UserServiceApplication,访问 Nacos 控制台→服务管理→服务列表,可看到 user-service 已成功注册。
① 创建 Maven 项目,引入与 user-service 相同的核心依赖(新增 OpenFeign 依赖用于服务调用):
<!-- OpenFeign 依赖(服务调用) -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
② 编写配置文件 application.yml:
spring:
application:
name: order-service # 服务名称
cloud:
nacos:
discovery:
server-addr: localhost:8848 # Nacos 服务地址
server:
port: 8082 # 服务端口
③ 编写启动类(开启 Feign 功能):
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients // 开启 Feign 声明式调用
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
}
④ 编写 Feign 客户端(调用 user-service 接口):
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
// name:目标服务名称(Nacos 中注册的服务名)
@FeignClient(name = "user-service")
public interface UserFeignClient {
// 与 user-service 的接口路径、请求方式一致
@GetMapping("/user/{id}")
User getUserById(@PathVariable("id") Long id);
// 与 user-service 中的 User 实体类结构一致
@lombok.Data
class User {
private Long id;
private String username;
private String phone;
private String address;
}
}
⑤ 编写订单接口(调用用户服务获取用户信息):
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class OrderController {
@Autowired
private UserFeignClient userFeignClient;
// 创建订单(模拟:根据用户 ID 查询用户信息,生成订单)
@GetMapping("/order/{userId}")
public Order createOrder(@PathVariable Long userId) {
// 1. 调用 user-service 获取用户信息
UserFeignClient.User user = userFeignClient.getUserById(userId);
// 2. 生成订单(模拟数据)
Order order = new Order();
order.setOrderId(System.currentTimeMillis());
order.setUserId(userId);
order.setUsername(user.getUsername());
order.setProductName("Java 编程思想");
order.setPrice(89.0);
order.setStatus("已创建");
return order;
}
// 订单实体类
@lombok.Data
static class Order {
private Long orderId;
private Long userId;
private String username;
private String productName;
private Double price;
private String status;
}
}
⑥ 测试服务调用:
{"orderId":1695888888888,"userId":1,"username":"张三 1","productName":"Java 编程思想","price":89.0,"status":"已创建"}
💡 在微服务架构中,每个服务都有自己的配置文件,当服务数量较多时,配置管理变得复杂。Nacos Config 提供集中式配置管理功能,支持动态配置更新(无需重启服务)、配置版本控制、多环境配置等。
① 引入 Nacos Config 依赖:
<!-- Nacos 配置中心依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
② 创建配置文件 bootstrap.yml(优先级高于 application.yml,用于加载 Nacos 配置):
spring:
application:
name: user-service # 服务名称(与 Nacos 配置的 Data ID 关联)
cloud:
nacos:
config:
server-addr: localhost:8848 # Nacos 配置中心地址
file-extension: yaml # 配置文件格式(yaml/xml/properties)
namespace: public # 命名空间(默认 public,用于隔离环境)
group: DEFAULT_GROUP # 配置分组(默认 DEFAULT_GROUP)
③ 在 Nacos 控制台创建配置:
user-service.yaml(格式:服务名。文件扩展名,与 bootstrap.yml 配置一致)。user:
config:
default-age: 18
welcome-msg: "欢迎使用用户服务!"
④ 在代码中读取 Nacos 配置:
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RefreshScope // 开启动态刷新配置(修改 Nacos 配置后无需重启服务)
public class ConfigController {
// 读取 Nacos 中的配置
@Value("${user.config.default-age}")
private Integer defaultAge;
@Value("${user.config.welcome-msg}")
private String welcomeMsg;
@GetMapping("/config")
public String getConfig() {
return "默认年龄:" + defaultAge + ",欢迎语:" + welcomeMsg;
}
}
⑤ 测试动态配置:
💡 在微服务架构中,服务间依赖关系复杂,若某个服务故障(如响应超时、宕机),会导致调用方线程阻塞,进而引发'雪崩效应'。Sentinel 通过熔断、限流、降级机制保护系统稳定运行。
① 引入 Sentinel 依赖:
<!-- Sentinel 核心依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- Sentinel 与 OpenFeign 整合依赖(支持 Feign 调用熔断) -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-feign</artifactId>
</dependency>
② 修改 application.yml 配置 Sentinel:
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080 # Sentinel 控制台地址
port: 8719 # 与 Sentinel 控制台通信的端口(默认 8719,若被占用自动递增)
feign:
enabled: true # 开启 Sentinel 对 Feign 的支持(熔断功能)
③ 编写熔断降级处理类(Feign 调用失败时的降级逻辑):
import org.springframework.stereotype.Component;
// Feign 客户端降级处理类(需实现对应的 FeignClient 接口)
@Component
public class UserFeignFallback implements UserFeignClient {
// 当调用 user-service 的 getUserById 接口失败时,执行此降级方法
@Override
public User getUserById(Long id) {
User user = new User();
user.setId(id);
user.setUsername("默认用户");
user.setPhone("13800000000");
user.setAddress("默认地址");
return user;
}
}
④ 修改 Feign 客户端,指定降级处理类:
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
// fallback:指定降级处理类
@FeignClient(name = "user-service", fallback = UserFeignFallback.class)
public interface UserFeignClient {
@GetMapping("/user/{id}")
User getUserById(@PathVariable("id") Long id);
@lombok.Data
class User {
private Long id;
private String username;
private String phone;
private String address;
}
}
① 触发 Sentinel 监控:启动 order-service 后,访问 http://localhost:8082/order/1(至少访问 1 次),Sentinel 控制台会自动注册 order-service 服务。
② 配置限流规则:
/order/{userId} 接口→点击'流控'。③ 测试限流效果:
Blocked by Sentinel (flow limiting)。import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class SentinelBlockHandler implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws IOException {
response.setContentType("application/json;charset=utf-8");
String msg = "";
if (e instanceof FlowException) {
msg = "{\"code\":429,\"msg\":\"当前请求过于频繁,请稍后再试!\"}";
}
response.getWriter().write(msg);
}
}
{"code":429,"msg":"当前请求过于频繁,请稍后再试!"}。① 配置熔断规则:
user-service(Feign 调用的服务)→点击'熔断'。② 测试熔断效果:
@GetMapping("/user/{id}")
public User getUserById(@PathVariable Long id) throws InterruptedException {
// 模拟 600ms 延迟(超过熔断规则的 500ms)
Thread.sleep(600);
User user = new User();
user.setId(id);
user.setUsername("张三" + id);
user.setPhone("1380013800" + id % 10);
user.setAddress("北京市朝阳区");
return user;
}
💡 OpenFeign 是基于 HTTP 的声明式服务调用组件,默认使用 JDK 的 HttpURLConnection 发送请求,可通过配置优化性能(如使用 OKHttp 客户端),支持请求超时、重试、拦截器等功能。
① 修改 application.yml 配置:
feign:
client:
config:
default: # 全局配置(若需针对单个服务,将 default 改为服务名,如 user-service)
connect-timeout: 5000 # 连接超时时间(5 秒)
read-timeout: 5000 # 读取超时时间(5 秒)
httpclient:
enabled: false # 关闭默认 HttpClient
okhttp:
enabled: true # 启用 OKHttp 客户端(需引入依赖)
# 重试配置(Spring Retry)
spring:
cloud:
loadbalancer:
retry:
enabled: true # 开启负载均衡重试
# 针对 user-service 的重试配置
user-service:
ribbon:
ConnectTimeout: 5000
ReadTimeout: 5000
MaxAutoRetries: 1 # 同一服务实例的重试次数
MaxAutoRetriesNextServer: 1 # 切换服务实例的重试次数
OkToRetryOnAllOperations: false # 仅对 GET 请求重试(POST 请求可能导致重复提交)
② 引入 OKHttp 依赖:
<!-- OpenFeign OKHttp 客户端依赖 -->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
</dependency>
<!-- Spring Retry 依赖(重试功能) -->
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
💡 同步通信(如 OpenFeign)适用于需要即时响应的场景,但会导致服务间强耦合,且可能因等待响应造成线程阻塞。异步通信(如消息队列)通过'生产者 - 消费者'模式解耦服务,支持异步处理、流量削峰、最终一致性等场景。
① 安装 RocketMQ:
start mqnamesrv.cmd(Windows)或 sh mqnamesrv.sh(Linux/Mac)。start mqbroker.cmd -n localhost:9876 autoCreateTopicEnable=true(Windows),Linux/Mac 执行 sh mqbroker.sh -n localhost:9876 autoCreateTopicEnable=true。① 引入 RocketMQ 依赖:
<!-- Spring Cloud Alibaba RocketMQ 依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rocketmq</artifactId>
</dependency>
② 配置 RocketMQ(application.yml):
spring:
cloud:
stream:
rocketmq:
binder:
name-server: localhost:9876 # RocketMQ NameServer 地址
bindings:
# 生产者配置(订单创建消息)
order-output:
destination: order_topic # 主题名称
content-type: application/json # 消息格式
# 消费者配置(订单支付消息)
pay-input:
destination: pay_topic # 主题名称
content-type: application/json
group: pay_consumer_group # 消费者组
③ 编写消息生产者(订单创建后发送消息):
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Source;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;
// 绑定 Source 接口(默认输出通道 output,此处自定义为 order-output)
@EnableBinding(Source.class)
@Component
public class OrderMessageProducer {
private final MessageChannel output;
// 注入输出通道(对应配置中的 order-output)
public OrderMessageProducer(Source source) {
this.output = source.output();
}
// 发送订单创建消息
public boolean sendOrderCreatedMsg(OrderCreatedMsg msg) {
return output.send(MessageBuilder.withPayload(msg).build());
}
// 订单创建消息实体
@lombok.Data
public static class OrderCreatedMsg {
private Long orderId;
private Long userId;
private Double amount;
private Long createTime;
}
}
④ 修改 OrderController,发送消息:
@RestController
public class OrderController {
@Autowired
private UserFeignClient userFeignClient;
@Autowired
private OrderMessageProducer orderMessageProducer;
@GetMapping("/order/{userId}")
public Order createOrder(@PathVariable Long userId) {
// 1. 调用用户服务获取用户信息
UserFeignClient.User user = userFeignClient.getUserById(userId);
// 2. 生成订单
Order order = new Order();
Long orderId = System.currentTimeMillis();
order.setOrderId(orderId);
order.setUserId(userId);
order.setUsername(user.getUsername());
order.setProductName("Java 编程思想");
order.setPrice(89.0);
order.setStatus("已创建");
// 3. 发送订单创建消息(异步通知其他服务,如物流服务、积分服务)
OrderMessageProducer.OrderCreatedMsg msg = new OrderMessageProducer.OrderCreatedMsg();
msg.setOrderId(orderId);
msg.setUserId(userId);
msg.setAmount(89.0);
msg.setCreateTime(System.currentTimeMillis());
orderMessageProducer.sendOrderCreatedMsg(msg);
return order;
}
// 订单实体类(略,同前)
}
⑤ 编写消息消费者(接收支付结果消息):
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Sink;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.stereotype.Component;
// 绑定 Sink 接口(默认输入通道 input,对应配置中的 pay-input)
@EnableBinding(Sink.class)
@Component
public class PayMessageConsumer {
// 监听 pay-input 通道的消息
@StreamListener(Sink.INPUT)
public void handlePayResult(PayResultMsg msg) {
// 处理支付结果(如更新订单状态)
System.out.println("收到支付结果消息:" + msg);
// 实际开发中应更新数据库中的订单状态
}
// 支付结果消息实体
@lombok.Data
public static class PayResultMsg {
private Long orderId;
private String payStatus; // SUCCESS/FAIL
private Long payTime;
private String tradeNo;
}
}
⑥ 测试异步通信:
┌─────────────────────────────────────────────────────────────┐
│ 客户端(Web/APP) │
└───────────────────────────────┬─────────────────────────────┘
│
┌───────────────────────────────▼─────────────────────────────┐
│ 网关(Spring Cloud Gateway) │
└─┬───────────────┬───────────────┬───────────────┬───────────┘
│ │ │ │
┌─▼───────┐ ┌───▼───────┐ ┌───▼───────┐ ┌───▼───────┐
│用户服务 │ │商品服务 │ │订单服务 │ │支付服务 │
└─┬───────┘ └───┬───────┘ └───┬───────┘ └───┬───────┘
│ │ │ │
┌─▼───────┐ ┌───▼───────┐ ┌───▼───────┐ ┌───▼───────┐
│用户数据库│ │商品数据库│ │订单数据库│ │支付数据库│
└─────────┘ └───────────┘ └───────────┘ └───────────┘
│ │ │ │
┌─▼───────────────▼───────────────▼───────────────▼───────┐
│ 中间件层(Nacos/Sentinel/RocketMQ) │
└─────────────────────────────────────────────────────────┘
① 商品服务实体类:
@lombok.Data
public class Product {
private Long id;
private String name;
private Double price;
private Integer stock; // 库存
private String category;
}
② 商品服务接口:
@RestController
public class ProductController {
// 模拟商品库存(实际开发中从数据库查询)
private final Map<Long, Product> productMap = new HashMap<>();
public ProductController() {
// 初始化商品数据
Product product = new Product();
product.setId(1L);
product.setName("Java 编程思想");
product.setPrice(89.0);
product.setStock(100);
product.setCategory("图书");
productMap.put(1L, product);
}
// 查询商品信息
@GetMapping("/product/{id}")
public Product getProductById(@PathVariable Long id) {
return productMap.get(id);
}
// 扣减库存(订单创建时调用)
@PostMapping("/product/stock/deduct")
public boolean deductStock(@RequestBody DeductStockReq req) {
Product product = productMap.get(req.getProductId());
if (product == null || product.getStock() < req.getCount()) {
return false; // 库存不足
}
product.setStock(product.getStock() - req.getCount());
return true;
}
// 扣减库存请求实体
@lombok.Data
static class DeductStockReq {
private Long productId;
private Integer count;
}
}
① 新增商品服务 Feign 客户端:
@FeignClient(name = "product-service", fallback = ProductFeignFallback.class)
public interface ProductFeignClient {
@GetMapping("/product/{id}")
Product getProductById(@PathVariable("id") Long id);
@PostMapping("/product/stock/deduct")
boolean deductStock(@RequestBody DeductStockReq req);
@lombok.Data
class Product {
private Long id;
private String name;
private Double price;
private Integer stock;
private String category;
}
@lombok.Data
class DeductStockReq {
private Long productId;
private Integer count;
}
}
// 商品服务降级处理类
@Component
class ProductFeignFallback implements ProductFeignClient {
@Override
public Product getProductById(Long id) {
Product product = new Product();
product.setId(id);
product.setName("默认商品");
product.setPrice(0.0);
return product;
}
@Override
public boolean deductStock(DeductStockReq req) {
return false; // 库存扣减失败
}
}
② 修改 OrderController,添加库存扣减逻辑:
@GetMapping("/order/{userId}")
public Order createOrder(@PathVariable Long userId) {
// 1. 选择商品(模拟用户购买商品 ID=1,数量=1)
Long productId = 1L;
Integer count = 1;
// 2. 调用商品服务查询商品信息
ProductFeignClient.Product product = productFeignClient.getProductById(productId);
if (product == null) {
throw new RuntimeException("商品不存在");
}
// 3. 调用商品服务扣减库存
ProductFeignClient.DeductStockReq deductReq = new ProductFeignClient.DeductStockReq();
deductReq.setProductId(productId);
deductReq.setCount(count);
boolean deductSuccess = productFeignClient.deductStock(deductReq);
if (!deductSuccess) {
throw new RuntimeException("库存不足");
}
// 4. 调用用户服务获取用户信息
UserFeignClient.User user = userFeignClient.getUserById(userId);
// 5. 生成订单
Order order = new Order();
Long orderId = System.currentTimeMillis();
order.setOrderId(orderId);
order.setUserId(userId);
order.setUsername(user.getUsername());
order.setProductName(product.getName());
order.setPrice(product.getPrice());
order.setCount(count);
order.setTotalAmount(product.getPrice() * count);
order.setStatus("已创建");
// 6. 发送订单创建消息
OrderMessageProducer.OrderCreatedMsg msg = new OrderMessageProducer.OrderCreatedMsg();
msg.setOrderId(orderId);
msg.setUserId(userId);
msg.setAmount(order.getTotalAmount());
msg.setCreateTime(System.currentTimeMillis());
orderMessageProducer.sendOrderCreatedMsg(msg);
return order;
}
// 订单实体类添加 count 和 totalAmount 字段
@lombok.Data
static class Order {
private Long orderId;
private Long userId;
private String username;
private String productName;
private Double price;
private Integer count;
private Double totalAmount;
private String status;
}
💡 在订单创建流程中,存在分布式事务问题:订单服务创建订单后,调用商品服务扣减库存,若扣减库存成功但订单服务保存订单失败,会导致库存减少但订单不存在;若订单创建成功但库存扣减失败,会导致超卖。
核心思想:
Seata 是阿里巴巴开源的分布式事务解决方案,支持 AT、TCC、SAGA 等模式,其中 AT 模式(自动事务模式)对业务代码侵入性最低,适合大多数场景。集成步骤如下:
① 安装 Seata Server(参考 Seata 官网)。 ② 引入 Seata 依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
③ 配置 Seata(application.yml):
seata:
application-id: ${spring.application.name}
tx-service-group: my_test_tx_group # 事务组名称
registry:
type: nacos # 注册中心类型(与 Nacos 集成)
nacos:
server-addr: localhost:8848
group: SEATA_GROUP
namespace: ""
config:
type: nacos
nacos:
server-addr: localhost:8848
group: SEATA_GROUP
namespace: ""
④ 在订单服务的创建订单方法上添加 @GlobalTransactional 注解(开启全局事务):
@GetMapping("/order/{userId}")
@GlobalTransactional(name = "create-order-transaction", rollbackFor = Exception.class)
public Order createOrder(@PathVariable Long userId) {
// 订单创建、库存扣减逻辑(同前)
}
✅ 本章详细讲解了分布式系统与微服务架构的核心概念、设计原则,重点实战了 Spring Cloud Alibaba 生态组件(Nacos、Sentinel、OpenFeign、RocketMQ)的核心功能,最终通过电商微服务系统案例,完整呈现了微服务架构的落地流程。
通过本章学习,读者应掌握:
下一章将重点讲解微服务网关(Spring Cloud Gateway)的设计与实现,包括路由转发、统一认证、限流熔断、日志监控等核心功能,进一步完善微服务架构体系。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online