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

活泼的旅行者
2025-06-19 03:49
阅读 677

开篇:什么是微服务?它用来做什么?

开篇:什么是微服务?它用来做什么?

你有没有见过一座摩天大楼?它看起来又高又大,但其实是由很多小房间、走廊和楼梯组成的。微服务架构就像是这栋大楼的设计方式 —— 它不是把所有的功能都放在一个“大盒子”里(也就是传统常说的“单体应用”),而是把每个功能独立成一个个小的服务。

比如,如果你做一个网上商城系统,传统的做法是:一个程序负责用户注册、商品展示、下单、支付等所有功能。而微服务的做法是:

  • 用户管理是一个单独的服务
  • 商品信息是另一个服务
  • 订单处理又是第三个服务
  • 支付系统又是一个服务

这些服务之间可以互相通信,但它们各自运行,各自开发、部署、维护。这样一来,团队协作更方便了,系统也更容易扩展。

在本教程中,我们将带你从零开始,逐步实践搭建一个简单的微服务项目。即使你是完全的新手,也能轻松上手!


环境准备:搭建你的开发环境

环境准备:搭建你的开发环境

所需工具清单:

工具 作用 下载链接
Java JDK 11+ 编写后端服务的基础语言 https://openjdk.java.net
Maven 依赖管理工具,帮助你快速加载代码库 https://maven.apache.org
Spring Boot CLI (可选) 快速创建Spring Boot项目 https://spring.io/projects/spring-boot#cli
IntelliJ IDEA 或 VSCode 编写Java代码的IDE推荐 https://www.jetbrains.com/idea/download/
Docker 运行微服务容器(后期用) https://www.docker.com/get-started

步骤一:安装JDK

我们使用 OpenJDK,它是免费且被广泛使用的版本。

  1. 打开浏览器访问OpenJDK官网

  2. 根据你的操作系统下载对应版本(建议选择JDK 11或更高)

  3. 安装完成后打开终端(Windows用cmd),输入:

    java -version
    

    如果看到类似输出表示安装成功:

    openjdk version "11.0.16" 2022-07-19
    OpenJDK Runtime Environment Adoptium-11.0.16+8 (build 11.0.16+8)
    

步骤二:安装Maven

  1. 打开Maven官网
  2. 下载 Binary zip archive
  3. 解压到任意目录,例如:C:\dev\apache-maven-3.8.6
  4. 配置环境变量:
    • 新建系统变量 MAVEN_HOME: 值为解压路径
    • Path 中添加 %MAVEN_HOME%\bin
  5. 检查安装是否成功,在终端中输入:
    mvn -v
    
    成功显示版本号即可。

步骤三:安装IDE(推荐IntelliJ IDEA)

  1. 下载社区版即可(完全免费)
  2. 安装过程中勾选与Java和Spring相关的组件
  3. 启动IDEA,选择新建项目,选择Spring Initializr,填写基础信息即可创建项目

步骤四:安装Docker(用于后面部署)

Windows用户推荐安装Docker Desktop
Mac用户也可以直接通过命令行安装

brew install --cask docker

安装完成后启动Docker应用,并在终端执行:

docker run hello-world

如果输出一段英文欢迎语,说明Docker已经正常运行。


核心概念解析:用最简单的话解释关键术语

数据库设计模型-1

核心概念解析:用最简单的话解释关键术语

在学习微服务之前,我们要先理解几个核心的概念。别担心,我会尽量用比喻来帮你理解。

1. 单体应用 vs 微服务

对比项 单体应用 微服务
结构 一个大的应用程序包含所有功能 多个小型服务,每个只负责一部分功能
部署 修改一个功能要重新部署整个程序 只需要更新涉及的部分
维护 越大越难维护 更灵活,容易拆分
团队合作 一组人一起修改一个文件 不同团队各自开发自己的服务

举个例子:假如你在做生日蛋糕,单体就是一个人做完全部工作;微服务就像分成多个小组:一个做奶油、一个做装饰、一个写祝福卡。


2. REST API 和 HTTP 请求

REST API 就是一种让不同服务之间能够互相打招呼的方式。

你可以把它想象成两个人之间的对话:

  • A服务问:“嘿,你知道用户ID=1的信息吗?”
  • B服务回答:“当然知道,给你看这个用户的名字叫张三。”

具体来说,我们可以用 GET /user/1 来请求用户信息,B服务返回JSON数据:

{
  "id": 1,
  "name": "张三"
}

3. Eureka 服务发现(Service Discovery)

在微服务中,服务数量变多,A服务怎么知道B服务在哪呢?这就需要用到 Eureka

想象一下,公司里的电话总机:你想联系技术部的人,就打个电话给总机,告诉他们你要找谁。

同样地,我们的服务在启动时会向Eureka注册自己,其他服务就可以通过Eureka找到它。


4. Feign 远程调用

Feign 是一种让你在微服务之间远程调用的方法。

它就像打电话一样简单:

@FeignClient(name = "product-service")
public interface ProductServiceClient {
    @GetMapping("/products/{id}")
    Product getProductById(@PathVariable("id") Long id);
}

这段代码的意思是:我想要连接名为“product-service”的服务,并调用它的 /products/{id} 接口。


5. Spring Cloud Gateway

当你有多个服务时,用户应该去哪个地址访问?这时候我们就需要一个统一的入口,这就是 API网关(Gateway)

比如:

  • 用户访问:http://api.example.com/user/1 → 路由到 user-service
  • 用户访问:http://api.example.com/product/1 → 路由到 product-service

这样用户只需要记住一个网址,内部由网关自动分配。


实战项目:一步步构建两个微服务并实现通信

实战项目:一步步构建两个微服务并实现通信

现在,我们将动手完成一个完整的微服务项目!目标是搭建两个服务:

  • user-service:用来管理用户信息
  • product-service:用来管理商品信息
  • 最终实现:用户调用API获取某个商品信息(模拟跨服务调用)

第一步:创建两个Spring Boot项目

使用IntelliJ IDEA 或者访问 Spring Initializr

创建 user-service

  • Group: com.example
  • Artifact: user-service
  • Dependencies:
    • Spring Web
    • Spring Cloud Discovery (Eureka Client)

创建 product-service

  • Group: com.example
  • Artifact: product-service
  • Dependencies:
    • Spring Web
    • Spring Cloud Discovery (Eureka Client)

将这两个项目分别导入IDE。


第二步:配置Eureka服务注册中心

我们需要先启动一个Eureka Server。

创建一个新的Spring Boot项目:eureka-server

  • Dependencies:
    • Spring Cloud Discovery (Eureka Server)

打开 application.yml 文件,添加如下配置:

server:
  port: 8761

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

然后在主类上加上注解启用Eureka:

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

启动后访问 http://localhost:8761 应该能看到Eureka控制台界面。


第三步:配置两个微服务注册到Eureka

user-serviceproduct-serviceapplication.yml 中添加以下内容:

spring:
  application:
    name: user-service  # 或 product-service
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

并在主类加上注解启用Eureka客户端:

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

重启服务后,再次进入Eureka控制台,你就能看到两个服务注册进来了。


第四步:编写产品服务接口

product-service 中创建一个控制器 ProductController.java

@RestController
@RequestMapping("/products")
public class ProductController {

    @GetMapping("/{id}")
    public Map<String, Object> getProductById(@PathVariable Long id) {
        Map<String, Object> product = new HashMap<>();
        product.put("id", id);
        product.put("name", "iPhone 15");
        product.put("price", 6999);
        return product;
    }
}

测试访问 http://localhost:8081/products/1001 是否能正常返回商品信息。


第五步:用户服务调用产品服务(Feign)

user-service 中添加Feign依赖:

pom.xml 中加上:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

然后启用Feign,在主类上加上:

@EnableFeignClients

创建 ProductServiceClient.java

@FeignClient(name = "product-service")
public interface ProductServiceClient {
    @GetMapping("/products/{id}")
    Map<String, Object> getProductById(@PathVariable("id") Long id);
}

最后在 UserController.java 中注入并调用:

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

    @Autowired
    private ProductServiceClient productServiceClient;

    @GetMapping("/product/{id}")
    public Map<String, Object> getUserAndProduct(@PathVariable Long id) {
        Map<String, Object> response = new HashMap<>();
        response.put("user", "张三");
        response.put("product", productServiceClient.getProductById(id));
        return response;
    }
}

测试访问 http://localhost:8080/users/product/1001,你应该可以看到:

{
  "user": "张三",
  "product": {
    "id": 1001,
    "name": "iPhone 15",
    "price": 6999
  }
}

✅ 到此为止,两个服务已经完成了通信!


常见问题解答(FAQ)

Q1:为什么启动Eureka的时候报错 “No instances available for service”?

这是因为你的微服务没有正确注册到Eureka。检查以下几点:

  • 确保Eureka已先于其他服务启动
  • 检查 application.yml 中的 spring.application.nameeureka.client.service-url 是否正确
  • 查看日志是否有错误提示,如网络不通、端口占用等

Q2:Feign调用失败怎么办?

常见的原因有:

  • 目标服务未启动或者没有注册到Eureka
  • Feign接口中的URL路径写错了
  • Feign没有启用(忘记加 @EnableFeignClients
  • 没有添加Feign依赖

建议先直接访问目标服务的API,确保没问题后再接入Feign。


Q3:微服务运行很慢,怎么优化?

你可以尝试:

  • 使用缓存(如Redis)减轻数据库压力
  • 异步调用(如RabbitMQ)
  • 服务限流与熔断(Hystrix)

这些高级功能将在后续学习中展开。


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

恭喜你,你已经迈出了学习微服务的第一步!

接下来建议按照以下路径继续学习:


✅ 第一阶段:掌握微服务核心组件

技术 用途
Spring Cloud Config 集中管理各个服务的配置文件
Hystrix 服务熔断,防止雪崩效应
Zuul / Gateway API网关统一入口
Sleuth & Zipkin 分布式链路追踪,方便排查问题

✅ 第二阶段:深入生产级技能

技术 用途
Docker + Kubernetes 服务编排与自动化部署
Prometheus + Grafana 服务监控与可视化
ELK Stack(Elasticsearch + Logstash + Kibana) 日志分析与查询
Kafka / RabbitMQ 异步消息通信,提升系统性能与解耦

✅ 推荐学习顺序图示:

单体应用 ➔ REST API ➔ Eureka 注册中心 ➔ Feign 远程调用 ➔ 网关 ➔ 配置中心 ➔ 熔断机制 ➔ 服务编排(Docker/K8s)

结尾语:编程是一门“做中学”的艺术

微服务并不是一开始就复杂的,它是随着业务需求一点点演化出来的。你现在写的每一行代码,每一个小Demo,都是你通往强大后端工程师之路的基石。

遇到不懂的地方不要怕,多查文档、多敲代码、多提问。你会越来越熟练!

如果你希望获得更多实战案例,欢迎关注我的系列教程《微服务架构进阶实战》,我们会从“小玩具”变成“真家伙”,一步步打造属于你自己的微服务平台!


文末彩蛋:源码托管地址(GitHub 示例)

点击链接即可查看完整工程结构与源码,欢迎大家Star和Fork学习!


评论 0

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