从单体到微服务:Java程序员的第一步分布式实战
大家好,我是掘金上经常写入门教程的全栈工程师。最近在带实习生的时候发现,很多同学虽然会写 Java,但一提到「微服务」就一脸懵——什么是服务拆分?为什么要用 Spring Cloud?面试官问“单体架构有什么问题”时,他们只能支支吾吾。
我当初学的时候也是一头雾水。那时候公司正从一个巨大的单体系统往微服务迁移,我连“注册中心”是啥都不知道,更别说动手搭建了。所以今天,我想用最简单的方式,带你亲手把一个单体 Java 项目改造成微服务架构。不讲大道理,只做能跑起来的代码。
这篇文章专为零基础的同学设计。只要你学过一点 Java、会用 IDEA、知道怎么运行一个 Spring Boot 项目,就能跟着做下去。
为什么我们要学微服务?
先说人话:微服务就是把一个大程序拆成多个小程序,每个小程序独立运行、独立开发、独立部署。
想象你开了一家餐厅:
- 单体架构:你一个人负责买菜、切菜、炒菜、洗碗、收银……所有事都堆在一个“厨房”里。
- 微服务架构:你请了厨师、服务员、收银员、清洁工,每个人各司其职,通过传菜口、对讲机协作。
当餐厅只有10个客人时,单体模式效率高;但当客人暴增到1000人,一个人肯定忙不过来,还容易出错。这时候,拆分团队(微服务)就成了必然选择。
面试题高频考点
“单体架构有哪些缺点?”
标准答案:
- 随着业务增长,代码越来越臃肿,编译慢、启动慢
- 一个模块出问题可能拖垮整个系统
- 技术栈被锁定,难以引入新技术
- 团队协作困难,多人改同一个代码库容易冲突
环境准备:5分钟搭好开发环境
我们要用到以下工具(全部免费):
| 工具 | 版本要求 | 作用 |
|---|---|---|
| JDK | 17 或 21 | Java 运行环境 |
| Maven | 3.8+ | 项目依赖管理 |
| IntelliJ IDEA | 最新版 | 开发 IDE |
| Spring Boot | 3.x | 快速构建 Java 应用 |
| Spring Cloud | 2023.x | 微服务全家桶 |
步骤 1:安装 JDK 和 Maven
步骤 2:创建第一个 Spring Boot 项目
打开 IDEA → New Project → 选择 Spring Initializr
填写:
- Project SDK: JDK 17
- Language: Java
- Spring Boot: 3.2.x
- Dependencies: Spring Web, Spring Boot DevTools
点击 Next,项目名为 user-service,包名 com.example.userservice
核心概念:微服务三大件
微服务不是魔法,它靠三个核心组件协同工作:
服务注册与发现(比如 Eureka / Nacos)
→ 所有服务启动后要“报到”,其他服务才能找到它服务调用(比如 OpenFeign / RestTemplate)
→ A 服务怎么调用 B 服务的接口配置中心(比如 Nacos Config / Apollo)
→ 统一管理所有服务的配置文件
📌 小贴士:我们这次用 Nacos,因为它同时支持注册中心 + 配置中心,国内用得最多!
实战:把单体用户系统拆成两个微服务
假设我们原来有个单体项目,包含用户管理和订单功能。现在要拆成:
user-service:提供用户信息查询order-service:提供订单创建,需要调用 user-service 获取用户姓名
第一步:启动 Nacos 服务
- 去 Nacos GitHub Releases 下载最新版(如 nacos-server-2.3.0.zip)
- 解压后进入
bin目录 - Windows 双击
startup.cmd,Mac/Linux 执行sh startup.sh -m standalone - 浏览器访问
http://localhost:8848/nacos,账号密码都是nacos
✅ 成功标志:看到 Nacos 控制台首页
第二步:改造 user-service(服务提供者)
- 在
pom.xml添加 Nacos 依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2022.0.0.0</version>
</dependency>
- 修改
application.yml:
server:
port: 8081
spring:
application:
name: user-service
cloud:
nacos:
discovery:
server-addr: localhost:8848
- 创建用户实体和控制器:
// User.java
public class User {
private Long id;
private String name;
// 构造函数、getter/setter 省略
}
// UserController.java
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
// 模拟数据库查询
return new User(id, "张三");
}
}
- 启动
UserApplication,刷新 Nacos 控制台 → 你会看到user-service出现在服务列表!
第三步:创建 order-service(服务消费者)
新建一个 Spring Boot 项目,名为 order-service,同样添加 Nacos 依赖,配置 application.yml:
server:
port: 8082
spring:
application:
name: order-service
cloud:
nacos:
discovery:
server-addr: localhost:8848
然后添加 OpenFeign 依赖(用于服务间调用):
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
开启 Feign:
// OrderApplication.java
@SpringBootApplication
@EnableFeignClients
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
}
定义 Feign 接口:
// UserClient.java
@FeignClient(name = "user-service")
public interface UserClient {
@GetMapping("/user/{id}")
User getUser(@PathVariable("id") Long id);
}
创建订单逻辑:
// OrderController.java
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private UserClient userClient;
@PostMapping("/create")
public String createOrder(@RequestParam Long userId) {
User user = userClient.getUser(userId);
return "为用户 [" + user.getName() + "] 创建了订单!";
}
}
第四步:测试端到端调用
- 启动
user-service - 启动
order-service - 调用订单接口:
curl -X POST "http://localhost:8082/order/create?userId=1" - 返回结果:
为用户 [张三] 创建了订单!
🎉 恭喜!你已经完成了第一个微服务调用!
新手常见问题 & 避坑指南
❌ 问题1:启动报错 No qualifying bean of type 'UserClient'
原因:忘记加 @EnableFeignClients 注解。
解决:在主启动类加上该注解。
❌ 问题2:order-service 找不到 user-service
排查步骤:
- 检查两个服务是否都注册到了 Nacos(看控制台)
- 检查
@FeignClient(name = "xxx")中的xxx是否和spring.application.name完全一致 - 确保两个服务的 Spring Boot 和 Spring Cloud 版本兼容(推荐用 Spring Boot 3.2 + Spring Cloud 2023.0.0)
❌ 问题3:中文乱码
现象:返回 "为用户 [å¼ ä¸‰] 创建了订单!"
解决:在 Feign 接口中指定编码:
@FeignClient(name = "user-service")
public interface UserClient {
@GetMapping(value = "/user/{id}", produces = "application/json; charset=utf-8")
User getUser(@PathVariable("id") Long id);
}
或者全局配置:
spring:
http:
encoding:
charset: UTF-8
enabled: true
⚠️ 避坑提醒:不要过早拆分!
很多新手一学微服务就想把所有功能拆成10个服务,结果维护成本爆炸。记住:
单体架构不是原罪,过度工程才是。
建议:
- 初期用单体 + 模块化(如 user-module、order-module)
- 当团队超过10人、部署频率高、技术栈需要多样化时,再考虑微服务
- 拆分原则:按业务边界,而不是按技术层(比如不要拆出一个“common-service”)
面试题延伸:微服务真的万能吗?
当然不是!面试官常问:
“微服务有哪些挑战?”
你可以这样答:
| 挑战 | 解决方案 |
|---|---|
| 分布式事务 | 使用 Saga 模式、TCC、或最终一致性 |
| 服务雪崩 | 熔断(Hystrix/Sentinel)、限流 |
| 日志分散 | ELK / Loki 收集日志 |
| 链路追踪难 | SkyWalking / Zipkin |
| 配置混乱 | Nacos Config / Apollo |
💡 提示:如果你能在回答中提到“CAP 理论”或“BASE 理论”,加分!
下一步学习建议
你已经迈出了关键一步!接下来可以:
- 深入 Nacos:学习配置中心、集群部署
- 加入网关:用 Spring Cloud Gateway 做统一入口
- 实现熔断:集成 Sentinel 防止级联失败
- 链路追踪:接入 SkyWalking 查看调用链
- 容器化:用 Docker 打包服务,用 Kubernetes 编排
📚 推荐资源:
- 官方文档:Spring Cloud Alibaba
- 书籍:《微服务架构设计模式》
- 视频:B站“狂神说微服务”系列
写在最后
微服务不是银弹,但它确实是现代 Java 后端开发的必备技能。我见过太多同学死记硬背“Eureka 是注册中心”,却没亲手跑过一行代码。今天这个小项目虽然简单,但它包含了微服务最核心的协作逻辑。
真正的理解,来自于亲手敲下的每一行代码。
下次面试官再问:“你们项目怎么做的服务拆分?” 你就可以自信地说:“我从单体开始,一步步拆出了用户服务和订单服务,并用 Nacos 实现了注册发现……”
加油!你离成为真正的后端工程师,又近了一步。

评论 0