微服务架构设计实战:从单体到分布式
写在前面
大家好,我是一名从培训班出来的前端开发工程师。虽然我的主战场是浏览器里的 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 为例):
- 下载 Oracle JDK 17 并安装
- 配置环境变量
JAVA_HOME指向 JDK 安装目录 - 下载 Maven,解压后配置
MAVEN_HOME - 安装 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
使用 Spring Initializr 创建项目,选择:
- Spring Web
- Nacos Discovery
application.yml配置:
server:
port: 8081
spring:
application:
name: user-service
cloud:
nacos:
discovery:
server-addr: localhost:8848 # Nacos 地址
- 编写控制器:
@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
- 启用 Feign:
@SpringBootApplication
@EnableFeignClients
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
}
- 声明远程接口:
@FeignClient(name = "user-service") // 对应 user-service 的 spring.application.name
public interface UserClient {
@GetMapping("/users/{id}")
Map<String, Object> getUser(@PathVariable("id") Long id);
}
- 在订单服务中调用:
@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 注册中心
- 下载 Nacos
- 解压后进入
bin目录,执行:
# Linux/Mac
sh startup.sh -m standalone
# Windows
startup.cmd -m standalone
- 访问
http://localhost:8848/nacos(账号密码都是 nacos)
步骤 5:运行测试
- 启动
user-service - 启动
order-service - 打开 Nacos 控制台,看到两个服务已注册 ✅
- 用 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-service→user_dborder-service→order_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