从零开始搭建微服务:我的Spring Cloud实战之路
开篇:为什么是 Spring Cloud?

事情得从去年初说起。那时候我们团队负责一个电商平台的重构项目,原本的单体架构已经扛不住业务增长了。订单服务、用户服务、库存服务混在一起,代码臃肿,部署缓慢,出问题时定位困难。面对越来越高的并发请求和更频繁的需求变更,我们意识到必须拆分服务、拥抱微服务架构。
作为后端负责人,我带着团队开始了微服务化改造,而我们的选择正是 Spring Cloud。
为什么选它?因为它生态完善、社区活跃、文档齐全,而且团队成员大多熟悉 Spring Boot,转型成本低。更重要的是,我们希望快速搭建起一套高可用、易维护的服务架构,而不是重新造轮子。
背景与挑战:从0到1搭建微服务体系

项目背景
这次重构的目标是将原有的大单体拆分成四个核心服务:
- 用户服务(User Service)
- 商品服务(Product Service)
- 订单服务(Order Service)
- 库存服务(Inventory Service)
这些服务之间存在复杂的调用关系,比如下单需要查询商品信息、扣减库存、记录订单、通知用户等操作,同时还要考虑认证、限流、日志追踪等问题。
初期挑战
- 如何管理多个服务之间的通信?
- 如何统一配置和服务发现?
- 如何实现统一的权限控制和API网关?
- 开发效率如何保证?调试是否复杂?
- 生产环境如何运维?服务挂掉怎么办?
这些问题如果不解决好,微服务反而会成为“分布式地狱”。
解决方案:基于 Spring Cloud 的微服务架构搭建


我们选择了 Spring Cloud Alibaba 套件作为基础技术栈,因为它在国内生态中非常成熟,配合 Nacos 做注册中心和配置中心特别顺手。
整体架构图大致如下:
+-----------------+ +--------------------+
| API Gateway | --> | Authentication |
| (Spring Cloud | | (OAuth2/JWT) |
| Gateway + JWT) | +--------------------+
+-----------------+
|
v
+-----------------+ +------------------+
| Service A | <-> | Service B |
| User Service | | Product Service |
+-----------------+ +------------------+
| |
v v
+---------------------------------------------+
| Common Component |
| - FeignClient / LoadBalancer / Config/Nacos |
| - Sleuth/Zipkin |
| - Sentinel |
+---------------------------------------------+
这套体系帮助我们很好地解决了上述几个问题。
实践细节:一步步搭建起来的微服务架构
第一步:搭建服务注册中心 —— Nacos
我们选用 Nacos 作为注册中心和配置中心。它是阿里巴巴开源的一个动态服务发现、配置管理和服务管理平台,非常适配 Spring Cloud Alibaba。
在启动类上加个 @EnableDiscoveryClient 注解,服务就能自动注册到 Nacos:
@SpringBootApplication
@EnableDiscoveryClient
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}
在 application.yml 中配置 Nacos 地址即可:
spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848
这样,其他服务就可以通过服务名来调用你的服务,比如:
@GetMapping("/user/{id}")
public User getUser(@PathVariable Long id) {
// 其他服务调用这个接口时,只需要传入服务名即可
return userService.getUserById(id);
}
第二步:服务间通信 —— OpenFeign + Ribbon
为了让服务之间能相互调用,我们选择了 OpenFeign 搭配 Ribbon 做客户端负载均衡。
定义一个 FeignClient 接口就完成了远程调用:
@FeignClient(name = "product-service")
public interface ProductServiceClient {
@GetMapping("/products/{id}")
Product getProductById(@PathVariable("id") Long id);
}
然后直接注入使用即可:
@Autowired
private ProductServiceClient productServiceClient;
@GetMapping("/order/{id}")
public OrderDetail getOrderDetail(@PathVariable Long id) {
Order order = orderService.getOrderById(id);
Product product = productServiceClient.getProductById(order.getProductId());
return new OrderDetail(order, product);
}
是不是很简洁?不过背后也有不少踩坑的地方,后面会讲到。
第三步:统一配置管理 —— Nacos Config
为了方便维护不同环境的配置,我们把所有配置都迁移到了 Nacos Config 上。
在 Spring Boot 项目中引入依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
然后在 bootstrap.yml 中指定 config server 地址:
spring:
application:
name: user-service
cloud:
nacos:
config:
server-addr: localhost:8848
extension-configs:
- data-id: user-service.yaml
group: DEFAULT_GROUP
refresh: true
这样我们就可以在 Nacos 页面上管理每个服务的 YAML 配置,并且可以区分 dev/test/prod 环境。
第四步:API 网关 —— Spring Cloud Gateway + JWT
网关是对外暴露服务的统一入口,我们用了 Spring Cloud Gateway,并集成了 JWT 进行身份验证。
关键配置如下:
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://user-service
predicates:
- Path=/api/users/**
filters:
- StripPrefix=1
- AuthFilter
自定义了一个 AuthFilter,用于校验 Token 是否合法:
@Component
public class AuthFilter implements GlobalFilter, Ordered {
private final JwtUtil jwtUtil;
public AuthFilter(JwtUtil jwtUtil) {
this.jwtUtil = jwtUtil;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String token = extractToken(exchange.getRequest());
if (token == null || !jwtUtil.validateToken(token)) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
// 提取token的方法略...
}
第五步:链路追踪 —— Sleuth + Zipkin
为了排查分布式系统中的调用问题,我们集成 Sleuth 和 Zipkin,实现了全链路追踪。
添加依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>
配置 zipkin server 地址:
spring:
zipkin:
base-url: http://localhost:9411
启动本地 zipkin server 很简单:
docker run -d -p 9411:9411 openzipkin/zipkin
这样我们在 Zipkin UI 中就能看到完整的调用链了。
第六步:熔断限流 —— Sentinel
最后我们加了 Sentinel 来做服务熔断和流量控制,防止雪崩效应。
引入依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
然后配置:
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080
我们还写了一个简单的 fallback 类来处理服务降级逻辑:
public class OrderServiceFallback {
public static Order getDefaultOrder(Long id) {
return new Order(id, 0L, 0L, BigDecimal.ZERO, "Service Unavailable");
}
}
并在 Feign Client 中启用 fallback:
@FeignClient(name = "order-service", fallback = OrderServiceFallback.class)
这样当某服务不可用时,可以返回默认值,避免整个系统崩溃。
踩过的坑:开发过程中的真实问题与解决
坑一:FeignClient 在 Gateway 中无法使用
起初我们在 Gateway 层尝试直接使用 FeignClient 发起调用,结果一直报错,提示找不到 service instance。
后来才意识到:Gateway 不应该直接调用其他服务,而是应该通过 route 配置转发请求。
所以正确的做法是在 Gateway 内部不使用 Feign,而是在实际业务服务中使用。
坑二:Nacos 忘记配置 namespace 导致环境混乱
我们在测试环境和预发布环境共用了同一个 Nacos 服务器,结果因为没有设置 namespace,导致配置互相干扰,出了不少 bug。
教训就是:多环境部署时一定要给每个环境单独分配 namespace。
配置方法很简单,在 yaml 里加一行:
namespace: test-env-namespace
坑三:Zipkin 数据没保留,排查困难
一开始 Zipkin 用的是内存存储,默认只保存 100 条链路数据,导致很多历史问题查不到。
于是我们改成了 MySQL 存储:
docker run -d \
-e MYSQL_HOST=localhost \
-e MYSQL_TCP_PORT=3306 \
-e MYSQL_USER=root \
-e MYSQL_PASSWORD=yourpassword \
-e STORAGE=mysql \
-p 9411:9411 \
openzipkin/zipkin
同时建表语句可以从官方 GitHub 获取。
这下不仅链路数据持久化了,还能通过 SQL 查询分析调用情况。
坑四:Sentinel 规则未持久化导致重启失效
Sentinel 控制台设置的限流规则如果不持久化,一旦应用重启就会丢失。
为此,我们采用了 Alibaba Sentinel 的 file 动态规则持久化机制,结合 Zookeeper 或 Apollo 可以做到集中式配置。
虽然当时时间有限,但我们还是先临时用文件保存规则:
sentinel:
datasource:
ds1:
file:
file: ./sentinel-rules.json
data-type: json
rule-type: flow
这样即使重启,规则也能加载回来。
效果总结:微服务改造后的收益
经过半年的微服务化实践,整个系统的架构变得更加清晰,主要收获如下:
- 服务解耦明显,模块职责更加清晰
- 部署效率提升,单个服务迭代更快
- 线上问题定位变得容易,通过链路追踪迅速发现问题点
- 通过熔断限流,稳定性显著提高,不再出现因某个服务异常导致全局瘫痪的情况
- 配置统一管理,环境切换更灵活,上线流程更加规范
最重要的是,团队的技术氛围和协作方式也发生了变化——大家开始真正思考服务设计、性能优化、容错机制,而不是只关注 CRUD。
经验分享:送给正在起步的你

如果你也正准备从头搭建一个微服务系统,这里是我的一些经验建议:
✅ 1. 技术选型要稳,不要追求新技术
Spring Cloud 生态很大,但并不意味着你要全部用上。根据实际需求,选成熟稳定的组件,例如 Nacos 比 Eureka 更适合国内场景,Sentinel 比 Hystrix 更新更活跃。
✅ 2. 微服务不是银弹,先想清楚再动
很多人认为微服务就是拆分服务,其实最难的部分是服务治理。如果没有服务发现、熔断限流、链路追踪等机制,微服务反而会更难维护。
✅ 3. 先搭基础设施,再上业务功能
建议花一周时间先把服务注册、配置中心、网关、监控等搭起来,然后再开始开发具体功能,否则后面补救成本太高。
✅ 4. 做好服务边界划分
服务划分不能过细也不能太粗,最好是按照业务领域来拆分,比如订单、用户、支付等独立服务。遵循单一职责原则,避免一个服务干太多事。
✅ 5. 多环境配置管理非常重要
推荐使用 Nacos 或 Apollo,让配置从代码中分离出来,方便管理和切换不同环境。
✅ 6. 日志、链路、监控都要有
微服务一大痛点就是看不到内部状态。因此建议尽早接入日志收集(ELK)、链路追踪(Sleuth + Zipkin)和监控报警(Prometheus + Grafana)。
✅ 7. 线上运维也要跟上
微服务上线后,运维也要相应升级。比如健康检查、自动化部署、灰度发布、滚动更新等功能都需要逐步具备。
小结与展望
这一路走下来,有困惑,有踩坑,也有成就感。从一开始对微服务概念的理解模糊,到逐渐建立起一整套可落地的架构,我深刻体会到:微服务并不是单纯的技术问题,更是工程能力、团队协作和架构思维的综合考验。
未来我们会继续往云原生方向演进,比如接入 Kubernetes、Service Mesh 等,进一步提升系统的弹性能力和自动化水平。
如果你也在微服务这条路上摸索前行,不妨停下来回顾一下自己的架构设计是否合理,是否真的服务于业务发展。别忘了,技术始终为业务服务,架构也应为团队和产品服务。
希望这篇文章能给你一些启发和参考,少走些弯路。如果你们在实践中遇到什么问题,也欢迎留言交流,我们一起成长。
如果你喜欢这样的实战分享,欢迎订阅我的公众号【码农进化论】,每周持续输出一线开发者的成长经验和技术干货。

评论 0