微服务架构设计实战:从单体到分布式

曹文
2025-06-20 14:29
阅读 385

开篇:微服务到底是什么?为什么我们需要它?

开篇:微服务到底是什么?为什么我们需要它?

你有没有遇到过这样的情况:

“我们开发了一个小商城网站,功能不多。但每次一改代码,整个系统都要重新部署一遍,而且有时候一个模块出问题了,整个网站都瘫痪。”

这就是**传统单体应用(Monolithic)**的典型问题。

而今天我们要讲的 “微服务”,就是为了解决这些问题而诞生的技术方案。

什么是微服务?

简单来说,微服务就是把原本集中在一起的大程序拆分成多个独立的小程序,每个小程序专门做一件事,并且可以独立运行、独立部署。

比如,一个商城系统原来是一个大项目,里面包含用户管理、商品展示、订单处理等功能。而在微服务架构下,这些功能会被拆成三个独立的服务:

  • 用户服务(User Service)
  • 商品服务(Product Service)
  • 订单服务(Order Service)

它们之间通过网络互相通信(一般是 HTTP 协议),共同协作完成一个完整的业务流程。

为什么要用微服务?

  1. 易维护:每个服务只负责一件事,结构清晰。
  2. 灵活性高:你想更新某个功能时,只需要部署那个服务,不需要动其他部分。
  3. 扩展性强:如果某个服务访问量突然上升,我们可以单独给这个服务加机器。
  4. 容错性好:如果一个服务出问题,不会影响到整个系统。

当然,微服务也有一些缺点,比如部署复杂、需要考虑服务间通信等问题。不过没关系,我们一步步来,先学会怎么用它!


环境准备:搭建你的微服务开发环境

环境准备:搭建你的微服务开发环境

在开始编码之前,我们先来准备好开发环境。你需要安装以下工具(以 Java 语言为例):

所需软件(Windows/macOS/Linux通用)

  1. JDK 17+
    下载地址:https://adoptium.net/zh-CN/temurin/releases/
    安装后,在命令行输入 java -version 验证是否安装成功。

  2. Maven 3.x
    Maven 是 Java 中用来管理依赖和构建项目的工具。
    下载地址:https://maven.apache.org/download.cgi
    安装完成后输入 mvn -v 查看版本。

  3. IDE(推荐 IDEA 或 VS Code)
    IDEA 社区版完全免费,下载地址:https://www.jetbrains.com/idea/download/

  4. Postman(用于测试接口)
    下载地址:https://www.postman.com/downloads/

  5. Docker(可选)
    用于后续部署多个微服务容器。
    Windows 推荐使用 Docker Desktop;Linux 可安装 Docker CE。

新手建议:不要着急一步到位,先把 JDK 和 IDE 搭建好,能跑通示例再逐步完善环境。


核心概念:理解微服务的关键术语

数据库设计模型-1

核心概念:理解微服务的关键术语

我们来看看几个核心术语,我会用最简单的方式解释。

1. 微服务(Microservice)

前面已经提到了,就是一个“小功能模块”,例如上面提到的用户服务、订单服务等。

2. API 接口(Application Programming Interface)

通俗说就是“两个系统之间沟通的语言”。

举个例子:

  • 用户服务提供一个 API:GET /user/{id},你可以通过这个地址获取用户信息。
  • 订单服务要查询某个用户的信息,就可以通过调用这个 API 来获取。

所以,API 是服务之间的“对话方式”。

3. 服务注册与发现(Service Registration & Discovery)

想象一下你有几十个微服务,你怎么知道哪个服务叫什么名字、在哪台服务器上运行呢?

这就需要有个“电话簿”一样的东西,记录所有服务的位置——这个功能叫做 服务注册与发现

常用的工具是:Eureka(Spring Cloud) 或者 Consul

4. 负载均衡(Load Balancing)

当一个服务有很多实例在运行时(比如 3 个相同的订单服务),客户端请求进来应该发给哪一个?

负载均衡器就会决定把请求分配到哪一台服务上。

常用的是:RibbonLoadBalancer(Spring Cloud 2020以后)

5. 网关(API Gateway)

网关就像一个“总入口”,所有的请求都要经过网关才能访问具体的微服务。

它可以做权限控制、路由转发、限流等工作。

常用网关:Zuul(老)Gateway(新)


实战项目:从零开始搭建一个简单的微服务系统

实战项目:从零开始搭建一个简单的微服务系统

我们以一个最简单的商城系统为例,搭建一个包含用户服务和订单服务的微服务系统。

项目结构如下:

microservices-demo/
├── user-service      // 用户服务
└── order-service     // 订单服务

我们将让订单服务通过 HTTP 请求调用用户服务,来获取用户的详细信息。


第一步:创建 Spring Boot 项目(使用 Spring Initializr)

打开 https://start.spring.io/ 创建一个新的 Spring Boot 项目。

配置如下:

  • Project: Maven
  • Language: Java
  • Spring Boot Version: 3.x(比如 3.1.4)
  • Group: com.example
  • Artifact: user-service
  • Dependencies:
    • Spring Web(用于构建 RESTful API)
    • Spring Boot DevTools(热加载,修改代码不重启服务)
    • Spring Data JPA + H2 Database(可选,做数据库操作)

点击 Generate Project 下载 zip 包,解压后用 IDEA 打开。

重复以上步骤,创建第二个项目:order-service


第二步:编写 User 服务

进入 user-service,我们先写一个最简单的接口:根据用户 ID 获取用户名。

1. 修改启动类 UserServiceApplication.java

@SpringBootApplication
public class UserServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }
}

2. 创建 Controller 文件 UserController.java

@RestController
@RequestMapping("/user")
public class UserController {

    @GetMapping("/{id}")
    public String getUserById(@PathVariable Long id) {
        return "用户ID:" + id + " 姓名:张三";
    }
}

3. 运行项目并测试

启动项目,访问地址:http://localhost:8080/user/123,你会看到:

用户ID:123 姓名:张三

第三步:编写 Order 服务

现在我们在订单服务中调用用户服务。

1. 修改配置文件 application.yml

默认端口是 8080,为了避免冲突,我们改为 8081:

server:
  port: 8081

2. 创建订单 Controller OrderController.java

@RestController
@RequestMapping("/order")
public class OrderController {

    private final WebClient webClient;

    public OrderController() {
        this.webClient = WebClient.builder()
                .baseUrl("http://localhost:8080")
                .build();
    }

    @GetMapping("/detail")
    public String getOrderDetail() {
        String result = webClient.get()
                .uri("/user/123")
                .retrieve()
                .bodyToMono(String.class)
                .block(); // 注意:正式项目中应避免阻塞操作

        return "订单详情:用户信息 - " + result;
    }
}

这段代码的作用就是:从订单服务发起对用户服务 /user/123 的请求。

3. 启动 order-service 并测试

启动订单服务后,访问:http://localhost:8081/order/detail

你会看到输出:

订单详情:用户信息 - 用户ID:123 姓名:张三

🎉 成功!你已经实现了第一个跨服务调用!


第四步:添加服务注册中心(Eureka Server)

目前我们是“硬编码”地调用了用户服务的 URL。实际生产环境不可能这样写,因为 IP 和端口可能变化。

所以我们引入 Eureka,让服务自动注册自己,并允许其他服务动态查找。

1. 创建新的项目:eureka-server

同样去 https://start.spring.io/ 创建一个 Spring Boot 项目,名称 eureka-server,依赖项选择:

  • Spring Web
  • Eureka Server

2. 修改启动类 EurekaServerApplication.java

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}

3. 修改配置文件 application.yml

server:
  port: 8761

spring:
  application:
    name: eureka-server

eureka:
  instance:
    hostname: localhost
  client:
    register-with-eureka: false
    fetch-registry: false
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

4. 启动服务

访问 http://localhost:8761,你会看到 Eureka 控制台。


第五步:将 User Service 注册到 Eureka

1. 在 user-service/pom.xml 中加入:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

2. 修改 application.yml

spring:
  application:
    name: user-service

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

3. 重启 user-service

刷新 Eureka 控制台页面,你应该能看到一个名为 USER-SERVICE 的服务注册进来了。


第六步:让 Order Service 自动发现 User Service

同样的方法:

1. 在 order-service/pom.xml 添加 Eureka 客户端依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

2. 修改配置文件 application.yml

spring:
  application:
    name: order-service

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

3. 使用 LoadBalancer 替换硬编码 URL

修改 OrderController.java,使用 RestTemplateWebClient 结合服务名调用。

private final WebClient webClient;

public OrderController() {
    this.webClient = WebClient.builder()
            .baseUrl("http://user-service")  // 注意这里不再是IP+端口,而是服务名
            .build();
}

⚠️ 此处还需要在主类中启用负载均衡:

@SpringBootApplication
@EnableDiscoveryClient
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class, args);
    }
}

现在再次访问 /order/detail,你会发现依然可以正常调用!


常见问题解答(FAQ)

Q1:我调用服务时报错,连接不上 user-service,怎么办?

A:可能是没有正确注册服务。请检查:

  • 服务名是否拼写正确(比如 user-service 和 UserService 是否一致)
  • Eureka Server 是否正常运行
  • 网络是否通顺,防火墙是否放行端口

Q2:WebClient 和 RestTemplate 有什么区别?

A:两者都能发送 HTTP 请求,但 WebClient 更现代化,支持响应式编程风格。RestTemplate 则更简单直接,适合初学者使用。

Q3:我能不能不用 Eureka,自己维护服务列表?

A:当然可以,但这被称为“静态配置”,不适合大规模微服务系统。随着服务数量增加,维护起来非常麻烦。


学习建议:下一步你该学什么?

恭喜你完成了第一阶段的微服务学习!接下来你可以沿着以下路径继续深入:

第一阶段(基础篇):

  • ✅ 已掌握:服务拆分、HTTP 通信、服务注册发现

第二阶段(增强篇):

  1. 引入 API Gateway(推荐 Spring Cloud Gateway)
  2. 实现统一配置中心(Spring Cloud Config)
  3. 添加服务链路追踪(Sleuth + Zipkin)
  4. 设置断路器(Hystrix,现已较少使用,可用 Resilience4j)
  5. 学习日志聚合(ELK Stack)

第三阶段(进阶篇):

  1. 消息队列(如 RabbitMQ、Kafka)实现异步通信
  2. 持续集成与持续部署(CI/CD)自动化部署微服务
  3. 容器化部署(Docker + Kubernetes)

结语

数据库设计模型-2

本教程带你从零开始,了解了什么是微服务,搭建了本地开发环境,实现了两个服务的通信,还引入了服务注册中心 Eureka。这只是一个起点,后面还有更多精彩内容等着你。

记住一句话:

“微服务不是银弹,但它是一把强大的锤子。”

只要你掌握了基础原理,不断实践,就能灵活应对各种复杂业务场景。加油,未来你也能成为微服务高手!

如果你觉得这篇教程对你有帮助,欢迎关注我的博客或视频课程,我们将继续深入更多后端开发实战技巧。

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝