微服务架构设计模式 · 第一部分:基础篇
引言:为什么需要微服务架构
在软件工程的早期,单体架构(Monolithic Architecture) 是大多数企业的首选:
- 所有功能模块打包成一个可部署单元
- 部署、测试、扩展都相对简单
- 对于小规模应用,开发效率很高
但是随着业务复杂度和用户规模的增长,单体架构逐渐暴露出以下问题:
- 耦合严重:一个模块的改动可能影响整个系统
- 扩展受限:无法按需扩展某个热点功能,只能整体扩展
- 交付周期变长:小的修改也需要重新打包和部署整个系统
- 技术债务累积:不同功能难以采用适合自身的技术栈
在这种背景下,微服务架构(Microservices Architecture) 应运而生。它的核心思想是:
👉 将应用拆分为一组小而独立的服务,每个服务围绕特定业务能力构建,并能独立部署和扩展。
微服务带来的优势:
- 独立部署:降低部署风险,提高交付频率
- 技术多样性:不同服务可使用最适合的技术栈
- 弹性伸缩:针对不同模块的负载特点进行扩展
- 团队自治:服务与团队高度对应,提升开发效率
当然,微服务也引入了新的挑战:分布式系统的复杂性、服务通信、数据一致性、运维与监控的难度等。
服务拆分模式
微服务的第一步就是 如何拆分服务。常见的拆分方式包括:
1. 按业务能力拆分
每个服务负责一个相对独立的业务能力(Business Capability)。
例如:
- 订单服务
- 支付服务
- 用户服务
这种方式贴近业务领域,有利于团队围绕业务目标展开工作。
2. 按子域拆分(DDD 指导)
领域驱动设计(Domain-Driven Design, DDD)提出了 限界上下文(Bounded Context) 的概念。
我们可以根据 核心域、支撑域、通用域 来拆分:
- 核心域(Core Domain):如推荐算法服务
- 支撑域(Supporting Domain):如库存管理
- 通用域(Generic Domain):如日志与监控
这种方式能帮助业务架构和技术架构保持一致。
3. 按团队组织方式拆分(Conway 定律)
Conway 定律指出:
👉 系统的设计架构往往与组织结构高度耦合。
因此,在大规模组织中,通常让一个团队负责一个服务。这样能够确保团队自治、减少跨团队沟通成本。
服务注册与发现模式
当服务数量增多后,如何让服务之间找到对方 成为新的问题。
1. Client-Side Discovery
客户端在调用服务前,会先从 服务注册中心(如 Eureka、Consul、Zookeeper)查询服务实例地址,然后再直接调用。
特点:
- 客户端负责负载均衡逻辑
- 适合客户端能处理服务发现逻辑的场景
2. Server-Side Discovery
客户端只需向一个固定入口(如 API Gateway 或负载均衡器)发请求,由服务端(或中间层)负责从注册中心查询可用实例,再路由请求。
特点:
- 简化客户端逻辑
- 常见于云服务(如 AWS ELB、NGINX + Consul)
3. Service Registry 的角色
无论哪种模式,服务注册中心 都是核心:
- 保存所有服务实例的健康状态
- 提供心跳检测和下线机制
- 与服务通信框架结合(如 Spring Cloud、Dubbo、gRPC)
小结
在 微服务架构设计模式 的基础篇中,我们重点介绍了:
- 为什么要从单体转向微服务
- 服务拆分的常见模式(业务能力、子域、团队组织)
- 服务注册与发现的实现方式(Client-Side vs Server-Side)
可以看到,微服务并不是一个“银弹”,而是用拆分和分布式的方式来解决单体架构的痛点。
接下来,在 通信篇 中,我们将深入探讨服务之间的通信模式,包括同步 REST/gRPC、异步消息队列,以及 API Gateway 模式的应用。
代码演示:从单体到微服务
一、单体架构版本
在单体应用中,所有模块共享同一个代码库和数据库。
monolith-app/
├── src/main/java/com/example/monolith/
│ ├── MonolithApplication.java
│ ├── controller/
│ │ └── AppController.java
│ ├── model/
│ │ ├── User.java
│ │ └── Order.java
│ └── service/
│ ├── UserService.java
│ └── OrderService.java
└── pom.xml
MonolithApplication.java
@SpringBootApplication
public class MonolithApplication {
public static void main(String[] args) {
SpringApplication.run(MonolithApplication.class, args);
}
}
AppController.java
@RestController
public class AppController {
private final UserService userService;
private final OrderService orderService;
public AppController(UserService userService, OrderService orderService) {
this.userService = userService;
this.orderService = orderService;
}
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
return userService.findById(id);
}
@GetMapping("/orders/{id}")
public Order getOrder(@PathVariable Long id) {
return orderService.findById(id);
}
}
运行方式:
mvn spring-boot:run
这里 用户 和 订单 服务在同一个进程内,耦合度高。
二、微服务架构版本
我们把它拆成 用户服务 和 订单服务。
microservices-demo/
├── user-service/
│ ├── src/main/java/com/example/user/
│ │ ├── UserServiceApplication.java
│ │ └── controller/UserController.java
│ └── pom.xml
│
├── order-service/
│ ├── src/main/java/com/example/order/
│ │ ├── OrderServiceApplication.java
│ │ └── controller/OrderController.java
│ └── pom.xml
│
└── pom.xml (parent)
user-service
UserServiceApplication.java
@SpringBootApplication
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}
UserController.java
@RestController
@RequestMapping("/users")
public class UserController {
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
return new User(id, "User-" + id);
}
}
启动:
mvn spring-boot:run -pl user-service -Dspring-boot.run.arguments="--server.port=8081"
order-service
OrderServiceApplication.java
@SpringBootApplication
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
}
在微服务架构中,服务之间通过 REST API / RPC 交互。例如,订单服务可能需要调用用户服务获取下单人信息:
OrderController.java
@RestController
@RequestMapping("/orders")
public class OrderController {
private final RestTemplate restTemplate = new RestTemplate();
@GetMapping("/{id}")
public OrderWithUser getOrder(@PathVariable Long id) {
Order order = new Order(id, "Order-" + id, 100.0);
User user = restTemplate.getForObject(
"http://localhost:8081/users/" + id, User.class);
return new OrderWithUser(order, user);
}
}
启动:
mvn spring-boot:run -pl order-service -Dspring-boot.run.arguments="--server.port=8082"
父级 pom.xml
microservices-demo/
├── pom.xml # 父级 POM
├── user-service/
│ └── pom.xml
└── order-service/
└── pom.xml
<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>microservices-demo</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<modules>
<module>user-service</module>
<module>order-service</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.0</version>
<relativePath/> <!-- 使用 Spring Boot 官方父 POM -->
</parent>
<properties>
<java.version>17</java.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
子模块 pom.xml(user-service 与 order-service 类似)
以 user-service/pom.xml 为例:
<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>
<parent>
<groupId>com.example</groupId>
<artifactId>microservices-demo</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>user-service</artifactId>
<version>1.0.0</version>
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
order-service/pom.xml 只需要改 <artifactId>,依赖基本一致。
查询订单服务
curl http://localhost:8082/orders/1
{"order":{"id":1},"user":{"id":1}
更多推荐



所有评论(0)