跳到主要内容
分布式系统设计与实战:Java 微服务架构落地 | 极客日志
Java java
分布式系统设计与实战:Java 微服务架构落地 分布式系统与微服务架构的核心概念及设计原则,重点讲解基于 Spring Cloud Alibaba 生态的实战落地。内容包括 DDD 领域驱动设计的服务拆分,Nacos 服务注册与配置中心,Sentinel 熔断限流,OpenFeign 同步通信,RocketMQ 异步消息等核心组件应用。通过电商微服务案例演示订单创建全流程、库存扣减及分布式事务解决方案,帮助开发者掌握高可用、高扩展的微服务系统设计方法。
DebugKing 发布于 2026/2/7 更新于 2026/6/2 31 浏览分布式系统设计与实战:Java 微服务架构落地
一、章节学习目标与重点
1.1 学习目标
理解分布式系统的核心概念、优势与挑战,掌握微服务架构的设计原则。
熟练使用 Spring Cloud Alibaba 生态组件实现服务注册与发现、配置中心、服务熔断与限流等核心功能。
能够独立设计并开发一个简单的分布式微服务系统,解决分布式场景下的常见问题(如服务通信、数据一致性等)。
1.2 学习重点
微服务架构的核心设计思想与拆分原则(领域驱动设计 DDD 实战)。
Spring Cloud Alibaba 核心组件(Nacos、Sentinel、OpenFeign)的实战应用。
分布式系统中的服务熔断、限流、降级机制的原理与实现。
微服务间通信方式(同步 HTTP、异步消息)的选型与实战。
二、分布式系统与微服务架构基础
2.1 分布式系统核心概念
💡 分布式系统是由多个独立的计算机(节点)通过网络连接,协同完成一个共同任务的系统。每个节点都有自己的硬件和软件,节点间通过网络进行通信和数据交换,对外呈现为一个统一的整体。
2.1.1 分布式系统的优势
高可用性 :单个节点故障不会导致整个系统崩溃,通过冗余设计实现故障转移。例如电商平台的订单服务部署在多个节点,某一节点宕机后,其他节点可继续提供服务。
高扩展性 :可根据业务需求横向扩展节点数量,提升系统处理能力。例如双十一期间,电商平台通过增加服务器节点应对流量峰值。
高性能 :将任务拆分到多个节点并行处理,缩短整体响应时间。例如大数据计算任务通过分布式框架(Hadoop)拆分到多个节点执行。
容错性 :通过数据备份、故障检测与恢复机制,减少单个节点故障对系统的影响。
2.1.2 分布式系统的挑战
网络延迟与不可靠 :节点间通信依赖网络,存在延迟、丢包、网络分区等问题,可能导致数据一致性问题。
数据一致性 :多个节点共享数据时,需保证数据在不同节点间的一致性(如分布式事务问题)。
分布式协调 :需要协调多个节点的行为,确保协同工作(如分布式锁、服务发现)。
复杂性提升 :系统架构、部署、监控、调试难度远高于单体应用。
2.2 微服务架构核心思想
💡 微服务架构是分布式系统的一种具体实现方式,它将一个大型应用拆分为多个小型、独立的服务,每个服务聚焦于完成一个特定的业务功能(如用户服务、订单服务、支付服务),服务间通过轻量级通信协议(如 HTTP、RPC)交互。
2.2.1 微服务架构的设计原则
单一职责原则 :每个微服务只负责一个核心业务领域,避免功能堆砌。例如用户服务仅处理用户注册、登录、信息查询等相关功能。
自治性原则 :每个微服务拥有独立的开发、测试、部署、运行周期,可独立升级和扩展,不依赖其他服务的部署。
轻量级通信原则 :服务间采用简单、通用的通信协议(如 RESTful API、gRPC),避免复杂的分布式通信框架。
数据去中心化原则 :每个微服务拥有自己独立的数据库,避免多个服务共享同一数据库,减少服务间耦合。例如订单服务使用订单数据库,用户服务使用用户数据库。
容错性设计原则 :服务间通过熔断、降级、限流等机制,避免单个服务故障扩散到整个系统。
2.2.2 微服务与单体架构的对比
架构复杂度 低(所有功能集成在一个应用) 高(多个独立服务协同)
开发效率(初期) 高(无需关注服务拆分与通信) 低(需设计服务拆分、通信等)
开发效率(后期) 低(代码量庞大,维护困难) 高(服务独立维护,迭代灵活)
扩展性 差(只能垂直扩展,成本高) 好(支持横向扩展,按需扩容)
可用性 差(单个模块故障导致整个应用崩溃) 好(单个服务故障不影响其他服务)
部署成本 低(一次部署整个应用) 高(需部署多个服务,依赖 DevOps 支持)
2.3 微服务拆分实战:领域驱动设计(DDD) 💡 微服务拆分的核心是按业务领域划分 ,而 DDD(Domain-Driven Design,领域驱动设计)是实现这一目标的最佳实践。DDD 通过将业务领域拆分为多个限界上下文(Bounded Context),每个限界上下文对应一个微服务。
2.3.1 DDD 核心概念
领域 :业务所涉及的范围(如电商领域包括用户、商品、订单、支付等)。
限界上下文 :领域中一个相对独立的业务模块,内部概念统一,与外部通过明确的接口交互(如订单上下文、支付上下文)。
聚合根 :限界上下文中的核心实体,作为数据操作的入口(如订单聚合根包含订单明细、收货地址等子实体)。
领域事件 :领域中发生的重要事件,用于跨限界上下文通信(如订单创建事件触发支付服务发起支付)。
2.3.2 微服务拆分步骤(以电商系统为例) ① 梳理业务领域 :明确电商系统的核心业务流程,如用户注册→商品浏览→加入购物车→下单→支付→物流配送。
② 划分限界上下文 :根据业务独立性拆分限界上下文,电商系统可拆分为:
用户上下文(用户注册、登录、信息管理)
商品上下文(商品发布、查询、库存管理)
订单上下文(订单创建、修改、查询)
支付上下文(支付发起、支付结果回调)
购物车上下文(添加商品、删除商品、结算)
物流上下文(物流信息录入、查询)
③ 映射微服务 :每个限界上下文对应一个微服务,如用户上下文→用户服务、订单上下文→订单服务。
④ 定义服务接口 :明确每个服务对外提供的 API(如订单服务提供'创建订单''查询订单详情'接口)。
⚠️ 注意:微服务拆分不可过细或过粗。拆分过细会导致服务间通信频繁、系统复杂度飙升;拆分过粗则退化为'分布式单体',无法发挥微服务优势。
三、Spring Cloud Alibaba 生态核心组件实战
3.1 生态介绍 💡 Spring Cloud Alibaba 是阿里巴巴基于 Spring Cloud 开发的微服务生态组件,兼容 Spring Cloud 标准,提供了服务注册发现、配置中心、熔断限流、分布式事务等一站式解决方案,目前已成为国内最主流的微服务开发框架。
Nacos :服务注册与发现中心 + 配置中心(替代 Eureka、Config)。
Sentinel :服务熔断、限流、降级组件(替代 Hystrix)。
OpenFeign :声明式服务调用组件(基于 HTTP 协议,简化服务间通信)。
Seata :分布式事务解决方案(解决跨服务数据一致性问题)。
RocketMQ :消息队列(用于异步通信、解耦服务)。
3.2 环境准备
3.2.1 技术栈选型
开发语言:Java 11
构建工具:Maven 3.6+
框架:Spring Boot 2.7.x、Spring Cloud Alibaba 2021.0.4.0
核心组件:Nacos 2.2.3、Sentinel 1.8.6
数据库:MySQL 8.0
开发工具:IntelliJ IDEA
3.2.2 环境搭建步骤
3.3 服务注册与发现(Nacos) 💡 Nacos 同时提供服务注册发现和配置管理功能,支持基于 DNS 和 RPC 的服务发现,适配各种场景下的服务注册与调用。
3.3.1 搭建服务提供者(user-service)
<parent >
<groupId > org.springframework.boot</groupId >
<artifactId > spring-boot-starter-parent</artifactId >
<version > 2.7.15</version >
<relativePath />
</parent >
<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 >
<dependency >
<groupId > org.springframework.boot</groupId >
<artifactId > spring-boot-starter-web</artifactId >
</dependency >
<dependency >
<groupId > com.alibaba.cloud</groupId >
<artifactId > spring-cloud-starter-alibaba-nacos-discovery</artifactId >
</dependency >
<dependency >
<groupId > org.projectlombok</groupId >
<artifactId > lombok</artifactId >
<optional > true</optional >
</dependency >
</dependencies >
② 编写配置文件 application.yml :
spring:
application:
name: user-service
cloud:
nacos:
discovery:
server-addr: localhost:8848
server:
port: 8081
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
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 已成功注册。
3.3.2 搭建服务消费者(order-service) ① 创建 Maven 项目 ,引入与 user-service 相同的核心依赖(新增 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
server:
port: 8082
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients
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;
@FeignClient(name = "user-service")
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;
}
}
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;
@GetMapping("/order/{userId}")
public Order createOrder (@PathVariable Long userId) {
UserFeignClient.User user = userFeignClient.getUserById(userId);
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" : "已创建" }
3.4 配置中心(Nacos Config) 💡 在微服务架构中,每个服务都有自己的配置文件,当服务数量较多时,配置管理变得复杂。Nacos Config 提供集中式配置管理功能,支持动态配置更新(无需重启服务)、配置版本控制、多环境配置等。
3.4.1 集成 Nacos Config(以 user-service 为例)
<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
cloud:
nacos:
config:
server-addr: localhost:8848
file-extension: yaml
namespace: public
group: DEFAULT_GROUP
访问 Nacos 控制台→配置管理→配置列表→点击'+'新增配置。
配置信息:
Data ID:user-service.yaml(格式:服务名。文件扩展名,与 bootstrap.yml 配置一致)。
配置格式:YAML。
配置内容(示例:用户服务自定义配置):
user:
config:
default-age: 18
welcome-msg: "欢迎使用用户服务!"
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
public class ConfigController {
@Value("${user.config.default-age}")
private Integer defaultAge;
@Value("${user.config.welcome-msg}")
private String welcomeMsg;
@GetMapping("/config")
public String getConfig () {
return "默认年龄:" + defaultAge + ",欢迎语:" + welcomeMsg;
}
}
3.5 服务熔断与限流(Sentinel) 💡 在微服务架构中,服务间依赖关系复杂,若某个服务故障(如响应超时、宕机),会导致调用方线程阻塞,进而引发'雪崩效应'。Sentinel 通过熔断、限流、降级机制保护系统稳定运行。
3.5.1 核心概念
限流 :限制服务的 QPS(每秒请求数),避免服务因流量峰值被压垮(如限制订单服务每秒最多处理 100 个请求)。
熔断 :当服务调用失败率达到阈值时,暂时断开调用链路,直接返回降级结果,避免故障扩散(如用户服务故障时,订单服务不再调用用户服务,直接返回'当前服务繁忙,请稍后再试')。
降级 :当服务压力过大或故障时,关闭非核心功能,返回简化的响应(如电商促销时,关闭商品评论功能,优先保证下单流程)。
3.5.2 集成 Sentinel(以 order-service 为例)
<dependency >
<groupId > com.alibaba.cloud</groupId >
<artifactId > spring-cloud-starter-alibaba-sentinel</artifactId >
</dependency >
<dependency >
<groupId > com.alibaba.cloud</groupId >
<artifactId > spring-cloud-alibaba-sentinel-feign</artifactId >
</dependency >
② 修改 application.yml 配置 Sentinel :
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080
port: 8719
feign:
enabled: true
③ 编写熔断降级处理类 (Feign 调用失败时的降级逻辑):
import org.springframework.stereotype.Component;
@Component
public class UserFeignFallback implements UserFeignClient {
@Override
public User getUserById (Long id) {
User user = new User ();
user.setId(id);
user.setUsername("默认用户" );
user.setPhone("13800000000" );
user.setAddress("默认地址" );
return user;
}
}
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@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;
}
}
3.5.3 配置限流规则(Sentinel 控制台)
访问 Sentinel 控制台→簇点链路→找到 /order/{userId} 接口→点击'流控'。
配置限流规则:
阈值类型:QPS。
单机阈值:2(每秒最多允许 2 个请求)。
其他默认,点击'新增'。
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":"当前请求过于频繁,请稍后再试!"}。
3.5.4 配置熔断规则(Sentinel 控制台)
访问 Sentinel 控制台→簇点链路→找到 user-service(Feign 调用的服务)→点击'熔断'。
配置熔断规则:
熔断策略:慢调用比例。
最大 RT(响应时间):500ms(超过 500ms 视为慢调用)。
慢调用比例阈值:0.5(慢调用占比超过 50%)。
熔断时长:10s(熔断后 10 秒内直接返回降级结果)。
最小请求数:5(需满足 5 个请求才触发熔断判断)。
点击'新增'。
故意修改 user-service 的 getUserById 接口,添加延迟(模拟服务响应缓慢):
@GetMapping("/user/{id}")
public User getUserById (@PathVariable Long id) throws InterruptedException {
Thread.sleep(600 );
User user = new User ();
user.setId(id);
user.setUsername("张三" + id);
user.setPhone("1380013800" + id % 10 );
user.setAddress("北京市朝阳区" );
return user;
}
四、微服务通信实战:同步与异步
4.1 同步通信:OpenFeign 进阶 💡 OpenFeign 是基于 HTTP 的声明式服务调用组件,默认使用 JDK 的 HttpURLConnection 发送请求,可通过配置优化性能(如使用 OKHttp 客户端),支持请求超时、重试、拦截器等功能。
4.1.1 配置 OpenFeign 超时与重试 feign:
client:
config:
default:
connect-timeout: 5000
read-timeout: 5000
httpclient:
enabled: false
okhttp:
enabled: true
spring:
cloud:
loadbalancer:
retry:
enabled: true
user-service:
ribbon:
ConnectTimeout: 5000
ReadTimeout: 5000
MaxAutoRetries: 1
MaxAutoRetriesNextServer: 1
OkToRetryOnAllOperations: false
<dependency >
<groupId > io.github.openfeign</groupId >
<artifactId > feign-okhttp</artifactId >
</dependency >
<dependency >
<groupId > org.springframework.retry</groupId >
<artifactId > spring-retry</artifactId >
</dependency >
4.2 异步通信:RocketMQ 实战 💡 同步通信(如 OpenFeign)适用于需要即时响应的场景,但会导致服务间强耦合,且可能因等待响应造成线程阻塞。异步通信(如消息队列)通过'生产者 - 消费者'模式解耦服务,支持异步处理、流量削峰、最终一致性等场景。
4.2.1 RocketMQ 环境准备
从 RocketMQ 官网 下载 RocketMQ(推荐 4.9.4 版本)。
解压后进入 bin 目录,启动 NameServer:start mqnamesrv.cmd(Windows)或 sh mqnamesrv.sh(Linux/Mac)。
启动 Broker:start mqbroker.cmd -n localhost:9876 autoCreateTopicEnable=true(Windows),Linux/Mac 执行 sh mqbroker.sh -n localhost:9876 autoCreateTopicEnable=true。
访问 RocketMQ 控制台(需单独部署,参考 RocketMQ Console ),确认服务正常。
4.2.2 集成 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
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;
@EnableBinding(Source.class)
@Component
public class OrderMessageProducer {
private final MessageChannel 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) {
UserFeignClient.User user = userFeignClient.getUserById(userId);
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("已创建" );
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;
@EnableBinding(Sink.class)
@Component
public class PayMessageConsumer {
@StreamListener(Sink.INPUT)
public void handlePayResult (PayResultMsg msg) {
System.out.println("收到支付结果消息:" + msg);
}
@lombok .Data
public static class PayResultMsg {
private Long orderId;
private String payStatus;
private Long payTime;
private String tradeNo;
}
}
五、分布式系统实战:电商微服务系统设计与实现
5.1 系统整体架构设计
5.1.1 架构图 ┌─────────────────────────────────────────────────────────────┐
│ 客户端(Web/APP) │
└───────────────────────────────┬─────────────────────────────┘
│
┌───────────────────────────────▼─────────────────────────────┐
│ 网关(Spring Cloud Gateway) │
└─┬───────────────┬───────────────┬───────────────┬───────────┘
│ │ │ │
┌─▼───────┐ ┌───▼───────┐ ┌───▼───────┐ ┌───▼───────┐
│用户服务 │ │商品服务 │ │订单服务 │ │支付服务 │
└─┬───────┘ └───┬───────┘ └───┬───────┘ └───┬───────┘
│ │ │ │
┌─▼───────┐ ┌───▼───────┐ ┌───▼───────┐ ┌───▼───────┐
│用户数据库│ │商品数据库│ │订单数据库│ │支付数据库│
└─────────┘ └───────────┘ └───────────┘ └───────────┘
│ │ │ │
┌─▼───────────────▼───────────────▼───────────────▼───────┐
│ 中间件层(Nacos/Sentinel/RocketMQ) │
└─────────────────────────────────────────────────────────┘
5.1.2 核心服务职责
用户服务 :用户注册、登录、信息管理、权限控制。
商品服务 :商品发布、查询、库存管理、分类管理。
订单服务 :订单创建、修改、查询、取消,调用用户服务、商品服务。
支付服务 :支付发起、支付结果回调、退款,调用订单服务更新订单状态。
网关服务 :路由转发、统一认证、限流、日志记录(后续章节详细讲解)。
5.2 核心功能实现:订单创建全流程
5.2.1 流程说明
用户浏览商品(商品服务提供商品查询接口)。
用户下单(订单服务调用商品服务扣减库存,调用用户服务验证用户状态)。
订单服务创建订单,发送订单创建消息(RocketMQ)。
支付服务监听订单创建消息,生成支付链接。
用户支付成功后,支付服务发送支付成功消息。
订单服务监听支付成功消息,更新订单状态为'已支付'。
物流服务监听支付成功消息,创建物流单(示例中省略,可参考订单服务实现)。
5.2.2 商品服务核心代码(库存扣减) @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;
}
}
5.2.3 订单服务整合商品服务(扣减库存) @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) {
Long productId = 1L ;
Integer count = 1 ;
ProductFeignClient.Product product = productFeignClient.getProductById(productId);
if (product == null ) {
throw new RuntimeException ("商品不存在" );
}
ProductFeignClient.DeductStockReq deductReq = new ProductFeignClient .DeductStockReq();
deductReq.setProductId(productId);
deductReq.setCount(count);
boolean deductSuccess = productFeignClient.deductStock(deductReq);
if (!deductSuccess) {
throw new RuntimeException ("库存不足" );
}
UserFeignClient.User user = userFeignClient.getUserById(userId);
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("已创建" );
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;
}
@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;
}
5.3 分布式事务问题与解决方案 💡 在订单创建流程中,存在分布式事务问题:订单服务创建订单后,调用商品服务扣减库存,若扣减库存成功但订单服务保存订单失败,会导致库存减少但订单不存在;若订单创建成功但库存扣减失败,会导致超卖。
5.3.1 最终一致性方案:基于消息队列的可靠消息投递
订单服务创建订单(本地事务),同时将'扣减库存消息'存入本地消息表(与订单表同一事务)。
启动定时任务,扫描本地消息表中未发送的消息,发送到 RocketMQ。
商品服务消费消息,扣减库存(本地事务),消费成功后向 RocketMQ 发送确认消息。
订单服务收到确认消息,更新本地消息表状态为'已发送'。
若商品服务消费失败,RocketMQ 会重试发送消息,直到消费成功(保证最终一致性)。
5.3.2 集成 Seata 实现分布式事务(可选) 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:
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)的核心功能,最终通过电商微服务系统案例,完整呈现了微服务架构的落地流程。
微服务拆分的核心原则(DDD 领域驱动设计)。
服务注册发现、配置中心、熔断限流的实战应用。
微服务间同步(OpenFeign)与异步(RocketMQ)通信方式。
分布式系统中常见问题(如事务一致性、服务雪崩)的解决方案。
下一章将重点讲解微服务网关(Spring Cloud Gateway)的设计与实现,包括路由转发、统一认证、限流熔断、日志监控等核心功能,进一步完善微服务架构体系。
相关免费在线工具 Keycode 信息 查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
Escape 与 Native 编解码 JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
JavaScript / HTML 格式化 使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
JavaScript 压缩与混淆 Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online