引言:为什么需要微服务架构

在软件工程的早期,单体架构(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}
Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐