从单体到微服务:一个电商产品的架构演进实战
大家好,我是小林,一名211高校的计算机研究生,也是个爱写技术博客的后端开发者。最近在带实习生时发现,很多同学对“微服务”这个词耳熟能详,却不知道它到底解决了什么问题,更别说如何动手实践了。我当初学的时候也踩过不少坑——光看书《微服务设计》《Spring Cloud微服务实战》这些经典书籍,概念一堆,但一上手就懵。所以今天,我想用一个真实的产品案例,带你从零开始,把一个单体应用一步步拆成微服务,真正理解“为什么拆”和“怎么拆”。
为什么我们要从单体走向微服务?
想象一下,你正在开发一个小型电商系统,初期功能简单:用户注册、商品浏览、下单、支付。所有代码都塞在一个项目里,部署也只要一个JAR包。这叫单体架构(Monolithic Architecture)。
但随着业务增长,问题来了:
- 团队变大,10个人同时改同一个代码库,合并冲突不断
- 商品模块频繁更新,但每次都要全量发布整个系统
- 订单服务崩溃,整个网站都挂了
- 技术栈被锁定,想用新语言重写某个模块?难!
而微服务架构的核心思想就是:把一个大产品拆成多个独立的小服务,每个服务专注一个业务能力(比如用户服务、商品服务、订单服务),可以独立开发、部署、扩展。
📚 小贴士:如果你刚接触这个概念,推荐阅读 Sam Newman 的《微服务设计》。这本书不讲代码,只讲思想,特别适合建立认知框架。
环境准备:5分钟搭建开发基础
我们用 Java + Spring Boot 来演示(你也可以用其他语言,思路相通)。确保你已安装:
| 工具 | 版本要求 | 验证命令 |
|---|---|---|
| JDK | 17+ | java -version |
| Maven | 3.6+ | mvn -v |
| IDE | IntelliJ IDEA 或 VS Code | — |
| Docker | 20.10+(可选,用于后续部署) | docker --version |
💡 新手注意:别一上来就装 Nacos、Sentinel、Seata 这些中间件!先理解核心逻辑,再加治理组件。
核心概念:微服务不是魔法,而是分工
微服务听起来高大上,其实本质很简单。我们用一个表格对比单体和微服务的区别:
| 维度 | 单体架构 | 微服务架构 |
|---|---|---|
| 代码结构 | 所有模块在一个项目 | 每个服务独立项目 |
| 部署方式 | 一次部署整个应用 | 每个服务独立部署 |
| 技术栈 | 统一(如全 Java) | 可异构(用户服务用 Go,订单用 Java) |
| 故障影响 | 一处崩溃,全站瘫痪 | 局部故障,其他服务可用 |
| 扩展性 | 整体扩容,资源浪费 | 按需扩容(如秒杀时只扩订单服务) |
关键术语解释:
- 服务注册与发现:服务A要调用服务B,得知道B在哪。于是有个“通讯录”(如 Eureka、Nacos)记录所有服务地址。
- 远程调用:服务之间通过 HTTP/gRPC 通信,不再是函数调用。
- API 网关:所有外部请求先经过网关,统一鉴权、路由、限流。
⚠️ 常见误区:微服务 ≠ 多个 Spring Boot 项目!如果它们之间还是强耦合、共享数据库,那只是“分布式单体”,反而更糟。
实战项目:把一个电商单体拆成3个微服务
我们以一个简化版电商产品为例,包含三个核心功能:
- 用户管理(注册/登录)
- 商品浏览
- 创建订单
第一步:原始单体结构(Before)
假设你已有如下单体项目结构:
ecommerce-monolith/
├── src/main/java
│ └── com.example.ecommerce
│ ├── controller
│ │ ├── UserController.java
│ │ ├── ProductController.java
│ │ └── OrderController.java
│ ├── service
│ │ ├── UserService.java
│ │ ├── ProductService.java
│ │ └── OrderService.java
│ └── EcommerceApplication.java
└── pom.xml
所有逻辑都在一起,数据库也共用一张 users、products、orders 表。
第二步:拆分服务(After)
我们按业务边界拆成三个独立项目:
user-service/ → 负责用户注册登录
product-service/ → 负责商品查询
order-service/ → 负责创建订单
1. 创建 user-service
// UserController.java
@RestController
public class UserController {
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
// 模拟返回用户
return new User(id, "张三", "zhangsan@example.com");
}
}
启动类加上 @EnableDiscoveryClient(后续注册到服务中心)。
2. 创建 product-service
// ProductController.java
@RestController
public class ProductController {
@GetMapping("/products/{id}")
public Product getProduct(@PathVariable Long id) {
return new Product(id, "iPhone 15", 5999.0);
}
}
3. 创建 order-service(关键:远程调用)
订单服务需要调用用户服务和商品服务来验证信息:
// OrderService.java
@Service
public class OrderService {
// 使用 RestTemplate 远程调用
@Autowired
private RestTemplate restTemplate;
public Order createOrder(Long userId, Long productId) {
// 调用 user-service
User user = restTemplate.getForObject(
"http://user-service/users/" + userId, User.class);
// 调用 product-service
Product product = restTemplate.getForObject(
"http://product-service/products/" + productId, Product.class);
if (user == null || product == null) {
throw new RuntimeException("用户或商品不存在");
}
return new Order(userId, productId, product.getPrice());
}
}
🔧 配置 RestTemplate Bean:
@Bean
@LoadBalanced // 启用负载均衡(配合服务发现)
public RestTemplate restTemplate() {
return new RestTemplate();
}
第三步:加入服务注册中心(Nacos)
- 下载 Nacos:https://github.com/alibaba/nacos/releases
- 启动:
sh startup.sh -m standalone(Linux/Mac)或startup.cmd -m standalone(Windows) - 在每个服务的
application.yml中配置:
spring:
application:
name: user-service # 服务名
cloud:
nacos:
discovery:
server-addr: localhost:8848
现在,三个服务启动后会自动注册到 Nacos。order-service 调用 http://user-service/... 时,会通过 Nacos 自动解析真实 IP 和端口。
✅ 验证步骤:
- 启动 Nacos
- 分别启动 user、product、order 服务
- 访问
http://localhost:8848/nacos,查看服务列表- 调用订单接口:
POST /orders?userId=1&productId=1001
新手常见问题解答
Q1:微服务一定要用 Spring Cloud 吗?
不一定!Spring Cloud 是 Java 生态的解决方案,但核心思想通用。Go 可用 go-micro,Node.js 可用 NestJS + Consul。关键是理解“服务拆分 + 通信 + 治理”的逻辑。
Q2:数据库要不要拆?
强烈建议拆! 每个服务应有自己独立的数据库(甚至不同数据库类型)。否则数据耦合会导致“拆了等于没拆”。例如:
- user-service → users_db
- product-service → products_db
- order-service → orders_db
Q3:本地怎么调试多个服务?
- 方案1:IDE 多开窗口,分别运行
- 方案2:用 Docker Compose 一键启停(推荐学完基础后尝试)
Q4:性能会不会变差?(网络调用 vs 函数调用)
会!这是微服务的代价。但可通过以下方式优化:
- 缓存(Redis 缓存商品信息)
- 异步(订单创建后发消息通知库存服务)
- 合理聚合(避免前端多次调用,用 BFF 层聚合)
学习建议:下一步该学什么?
深入服务治理
学习熔断(Hystrix/Sentinel)、限流、链路追踪(SkyWalking)。推荐书籍:《Spring Cloud微服务实战》。掌握 API 网关
用 Spring Cloud Gateway 统一入口,做认证、路由、日志。尝试容器化部署
把每个服务打包成 Docker 镜像,用 docker-compose 编排。理解事件驱动
用 RabbitMQ/Kafka 解耦服务,比如“订单创建成功”后发消息给积分服务。不要盲目拆分!
如果你的产品只有3个功能、2个开发者,单体完全够用。微服务是为复杂度买单的,不是银弹。
最后的话
微服务不是终点,而是应对业务复杂度的一种手段。我见过太多团队为了“上微服务”而拆分,结果运维成本飙升,开发效率反而下降。记住:架构是演进而非设计出来的。
希望这篇从真实产品出发的实战教程,能帮你避开我当年踩过的坑。如果你跟着做了一遍,恭喜你,已经跨过了微服务入门的最大障碍——动手实践!
📖 延伸阅读清单:
- 《微服务设计》Sam Newman(思想奠基)
- 《凤凰项目》Gene Kim(小说形式讲 DevOps)
- Spring 官方文档:https://spring.io/projects/spring-cloud
有问题欢迎在评论区留言,我会一一回复。下期我们聊聊“如何用 Docker 一键部署你的微服务全家桶”!

评论 0