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

RAG小工匠
2025-12-14 23:59
阅读 342

写在前面
大家好,我是一名从培训班出来的前端开发工程师。虽然我的主战场是浏览器里的 HTML、CSS 和 JavaScript,但在实际项目中,我经常需要和后端微服务打交道——调接口、看日志、联调部署……这些经历让我深刻体会到:不懂后端架构的前端,就像只会踩油门却看不懂仪表盘的司机。

我当初学的时候,一听到“微服务”“分布式”就头大,总觉得那是大厂高工才玩的东西。但后来发现,只要拆解清楚,零基础也能上手。今天我就用最直白的语言,手把手带你从一个单体 Java 应用,一步步改造成微服务架构。过程中你会看到真实的代码、配置和避坑指南,真正理解什么是“资源”,如何用“算法”优化服务,以及这背后藏着怎样的“代码人生”。


一、微服务是什么?能用来做什么?

想象你开了一家餐厅。

  • 单体架构 就像一家小馆子:一个厨师(代码)负责买菜、洗菜、炒菜、收钱、打扫卫生。所有事情都堆在一个“程序”里。
  • 微服务架构 则像一家连锁餐厅:采购部、厨房、收银台、清洁组各自独立运作,通过内部通讯(比如对讲机)协作完成一桌饭。

微服务的核心思想:把一个大应用拆成多个小服务,每个服务只做一件事,独立开发、部署、扩展。

为什么用微服务?

  • 灵活开发:不同团队可以并行开发不同服务
  • 容错性强:一个服务挂了,不影响其他服务
  • 技术自由:每个服务可以用不同的语言(比如用户服务用 Java,推荐服务用 Python)
  • 弹性伸缩:流量大的服务(如支付)可以单独加机器

📌 注意:微服务不是银弹!如果你的项目只有 3 个页面、10 个用户,别折腾微服务——单体更简单高效。微服务适合中大型、高并发、快速迭代的系统。


二、环境准备:5 分钟搭好开发环境

我们用 Java + Spring Boot 来实战(因为生态成熟、资料多)。你需要安装以下工具:

工具 版本要求 作用
JDK 17 或 21 Java 运行环境
Maven 3.8+ 项目依赖管理
IntelliJ IDEA 社区版即可 代码编辑器
Postman 最新版 测试 API
Docker 可选但推荐 容器化部署

安装步骤(以 Windows 为例):

  1. 下载 Oracle JDK 17 并安装
  2. 配置环境变量 JAVA_HOME 指向 JDK 安装目录
  3. 下载 Maven,解压后配置 MAVEN_HOME
  4. 安装 IDEA,打开时会自动识别 JDK 和 Maven

💡 新手常见问题
Q:一定要用 JDK 17 吗?
A:Spring Boot 3.x 要求 JDK 17+。如果你用旧版(如 JDK 8),请改用 Spring Boot 2.7,但本文示例基于新版本。


三、核心概念:用大白话讲清楚

1. 单体应用(Monolith)

所有功能(用户、订单、商品)写在一个项目里,打包成一个 JAR 文件运行。

// UserController.java
@RestController
public class UserController {
    @GetMapping("/users/{id}")
    public String getUser(@PathVariable Long id) {
        return "User " + id;
    }
}

// OrderController.java
@RestController
public class OrderController {
    @PostMapping("/orders")
    public String createOrder() {
        return "Order created";
    }
}

优点:简单、调试方便
缺点:代码臃肿、难以维护、部署慢


2. 微服务(Microservice)

把上面的代码拆成两个独立项目:

  • user-service:只管用户相关逻辑
  • order-service:只管订单相关逻辑

每个服务有自己的数据库、配置、端口。


3. 服务注册与发现(Service Registry)

微服务多了,怎么知道对方在哪?靠“电话簿”——注册中心。

常用工具:Nacos、Eureka、Consul

我当初学的时候以为注册中心很神秘,其实它就是一个 Web 应用,服务启动时把自己“登记”上去,调用方去“查号”。


4. 远程调用(RPC / HTTP)

服务 A 要调用服务 B,不能直接 new 对象,得发 HTTP 请求。

Java 中常用:OpenFeign(声明式 HTTP 客户端)


5. 资源(Resource)

在微服务中,“资源”指:

  • CPU、内存(服务器资源)
  • 数据库连接池(连接资源)
  • 网络带宽(通信资源)

关键点:每个微服务要合理使用资源,避免一个服务吃光所有内存导致其他服务崩溃。


6. 算法(Algorithm)在微服务中的角色

别以为算法只是刷 LeetCode!微服务中常用算法解决实际问题:

场景 算法应用
负载均衡 轮询、加权随机、最少连接数
服务熔断 滑动窗口统计失败率
缓存淘汰 LRU(最近最少使用)
分布式 ID 生成 Snowflake 算法

举个例子:当 order-service 调用 user-service 失败超过 5 次,就暂时“熔断”不再调用——这就是用计数算法保护系统。


四、实战项目:把单体拆成微服务

我们将创建一个极简电商系统,包含两个服务:

  • user-service:提供用户信息
  • order-service:创建订单,需调用用户服务验证用户是否存在

步骤 1:创建父工程(统一管理依赖)

<!-- pom.xml (父工程) -->
<groupId>com.example</groupId>
<artifactId>microservice-demo</artifactId>
<version>1.0</version>
<packaging>pom</packaging>

<modules>
    <module>user-service</module>
    <module>order-service</module>
</modules>

步骤 2:搭建 user-service

  1. 使用 Spring Initializr 创建项目,选择:

    • Spring Web
    • Nacos Discovery
  2. application.yml 配置:

server:
  port: 8081
spring:
  application:
    name: user-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848  # Nacos 地址
  1. 编写控制器:
@RestController
public class UserController {
    @GetMapping("/users/{id}")
    public Map<String, Object> getUser(@PathVariable Long id) {
        // 模拟数据库查询
        Map<String, Object> user = new HashMap<>();
        user.put("id", id);
        user.put("name", "张三");
        return user;
    }
}

步骤 3:搭建 order-service

同样方式创建项目,依赖相同。

application.yml

server:
  port: 8082
spring:
  application:
    name: order-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848

关键:使用 OpenFeign 调用 user-service

  1. 启用 Feign:
@SpringBootApplication
@EnableFeignClients
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class, args);
    }
}
  1. 声明远程接口:
@FeignClient(name = "user-service") // 对应 user-service 的 spring.application.name
public interface UserClient {
    @GetMapping("/users/{id}")
    Map<String, Object> getUser(@PathVariable("id") Long id);
}
  1. 在订单服务中调用:
@RestController
public class OrderController {

    @Autowired
    private UserClient userClient;

    @PostMapping("/orders")
    public String createOrder(@RequestParam Long userId) {
        // 先验证用户是否存在
        Map<String, Object> user = userClient.getUser(userId);
        if (user == null || user.isEmpty()) {
            return "用户不存在";
        }
        return "订单创建成功,用户:" + user.get("name");
    }
}

步骤 4:启动 Nacos 注册中心

  1. 下载 Nacos
  2. 解压后进入 bin 目录,执行:
# Linux/Mac
sh startup.sh -m standalone

# Windows
startup.cmd -m standalone
  1. 访问 http://localhost:8848/nacos(账号密码都是 nacos)

步骤 5:运行测试

  1. 启动 user-service
  2. 启动 order-service
  3. 打开 Nacos 控制台,看到两个服务已注册 ✅
  4. 用 Postman 发请求:
    POST http://localhost:8082/orders?userId=123
    
    返回:订单创建成功,用户:张三

🎉 恭喜!你完成了第一个微服务调用!


五、新手常见问题 & 解决方案

Q1:启动报错 “Connection refused to Nacos”

原因:Nacos 没启动或地址写错
解决:检查 server-addr: localhost:8848,确认 Nacos 已运行

Q2:Feign 调用返回 404

原因:路径不匹配
检查点

  • @FeignClient(name = "xxx") 中的 name 必须和服务名一致
  • 接口方法的 @GetMapping 路径要和被调用方完全一致

Q3:服务间传递用户上下文(如登录信息)怎么办?

方案:使用 RequestInterceptor 在 Feign 调用前添加 Header

@Configuration
public class FeignConfig {
    @Bean
    public RequestInterceptor requestInterceptor() {
        return requestTemplate -> {
            // 从当前请求获取 token 并传递
            String token = ServletUtil.getHeader("Authorization");
            if (token != null) {
                requestTemplate.header("Authorization", token);
            }
        };
    }
}

Q4:微服务怎么连数据库?

每个服务有自己的数据库!不要共享同一张表。

  • user-serviceuser_db
  • order-serviceorder_db

用 MyBatis 或 JPA 单独配置数据源即可。


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

微服务只是分布式系统的起点。建议按以下路径深入:

1. 必学组件

组件 作用 学习重点
Nacos 注册中心 + 配置中心 服务发现、动态配置
Sentinel 限流熔断 规则配置、降级策略
Gateway API 网关 路由、过滤、鉴权
Seata 分布式事务 AT 模式、TCC

2. 理解“资源”管理

  • 学会用 Docker 容器化每个服务
  • Prometheus + Grafana 监控 CPU、内存、请求量
  • 设置合理的 JVM 参数,避免 OOM

3. 算法实践

  • 实现一个简单的负载均衡算法(轮询)
  • Redis + Lua 实现分布式锁
  • 研究 Snowflake ID 生成器源码

4. 代码人生的思考

微服务教会我们的不仅是技术,更是拆解复杂问题的能力
就像人生:与其试图一个人扛下所有(单体),不如学会协作、专注自己的赛道(微服务)。每个服务做好一件事,整个系统才能健壮运行。

我当初从培训班出来,以为会写页面就是程序员。后来参与微服务项目,才明白:真正的代码人生,是设计、协作、权衡的艺术


结语

今天我们从零开始,把一个单体 Java 应用拆成了两个微服务,并实现了服务调用。过程中涉及了资源分配、算法应用,也窥见了代码人生的一角。

记住:微服务不是目的,而是手段。先写好单体,再优雅拆分,才是正道。

下次当你看到“分布式”“高可用”这些词,别慌——它们不过是无数个小服务,彼此信任、互相调用的故事。

祝你编码愉快,少加班,多涨薪!

评论 0

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