Spring Cloud从零开始:一个五年后端工程师的实战笔记
引言:微服务不是银弹,但它是现代架构的标配
我在五年前刚接触Spring Cloud的时候,它还是Spring Boot刚火起来时的“附属品”。而现在,微服务几乎成了中大型项目的标配。作为后端工程师,我经历过单体应用的痛苦——部署慢、修改影响大、版本管理复杂。当公司决定要将原来的ERP系统拆分重构为微服务架构时,我几乎是“被推上前线”的。
说实话,刚开始我是抗拒的。因为我知道这意味着需要重新设计架构、引入新工具、学习一堆框架组件。更重要的是,团队里没有一个人有实际的Spring Cloud项目经验。
但我很快意识到,这是一次难得的机会:我可以从0开始实践Spring Cloud生态,真正理解其核心理念和落地细节。现在回过头来看,那些踩过的坑、掉过的陷阱、深夜调试的日志,都变成了最宝贵的经验。
今天,我就以第一人称的角度,带你一起从零开始构建Spring Cloud微服务系统,聊聊我们在真实项目中的思考、决策与实现。
项目背景:为什么选择Spring Cloud?

我们当时负责的是一家传统制造业企业的ERP系统改造。原来是一个基于JSP + Struts + Hibernate的老旧单体应用,已经运行了七八年,代码臃肿、耦合严重,每次上线都像在走钢丝。
业务需求不断增长,开发效率却持续下降。技术上,我们需要解决几个关键问题:
- 模块之间高度耦合,一个小功能改动容易引发连锁反应
- 系统负载不均衡,有些模块并发量高,有些模块资源浪费严重
- 扩展性差,新需求无法快速迭代上线
- 技术栈老旧,团队成员流失严重
于是我们决定尝试微服务化改造,使用Spring Cloud作为技术选型的核心。
初期挑战:从哪里下手?


第一个问题就来了:怎么拆?
我们尝试按照业务领域划分微服务,比如订单服务、库存服务、用户服务等。但现实是残酷的:
- 原来的数据库是单库多表,拆成多个数据库怎么办?
- 各个服务之间的依赖关系错综复杂,接口调用如何管理?
- 跨服务事务如何处理?(比如下单减库存这种场景)
- 如何保证服务之间的通信可靠性和可观测性?
我们当时也走过弯路。比如一开始只用了Spring Boot搭建了几个独立的服务,但没有任何注册发现机制,服务配置写死在每个应用里,结果就是运维极其麻烦,改一个IP得重启所有服务。
后来我们意识到:必须有一套完整的微服务治理体系,不能只靠Spring Boot。
技术选型与方案设计:Spring Cloud全家桶上手

我们最后确定的技术栈如下:
| 组件 | 用途 |
|---|---|
| Spring Boot 2.7.x | 快速构建服务基础 |
| Spring Cloud 2021.x | 微服务核心组件 |
| Nacos | 服务注册与发现、配置中心 |
| OpenFeign & Ribbon | 服务间通信 |
| Gateway | API网关 |
| Sentinel | 流量控制、熔断降级 |
| Seata | 分布式事务 |
| Zipkin / SkyWalking | 链路追踪 |
| RocketMQ | 异步消息队列 |
📌 Tips:Nacos现在已经是国产开源明星项目,社区活跃度很高,而且兼容性好;而Gateway相比Zuul更轻量高效,已经成为主流API网关的选择之一。
接下来,我将分享我们的具体实现思路和技术细节。
实战演练:一步步构建你的第一个Spring Cloud微服务系统

第一步:搭建注册中心(使用Nacos)
首先安装Nacos Server(推荐用Docker):
docker run -d \
-e MODE=standalone \
-p 8848:8848 \
--name nacos nacos/nacos-server
访问 http://localhost:8848/nacos 即可看到控制台,默认账号密码均为 nacos。
然后创建一个Spring Boot项目,并添加Nacos客户端依赖:
<!-- 在pom.xml中添加 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2021.0.5.0</version>
</dependency>
并在 application.yml 中配置:
server:
port: 8080
spring:
application:
name: user-service
cloud:
nacos:
discovery:
server-addr: localhost:8848
management:
endpoints:
web:
exposure:
include: "*"
启动类加上注解:
@EnableDiscoveryClient
@SpringBootApplication
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}
这样你就有了一个注册到Nacos的服务。
第二步:服务间调用(OpenFeign + LoadBalancer)
我们有两个服务:user-service 和 order-service,order-service 需要调用 user-service 的用户信息接口。
在order-service中添加Feign依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
定义Feign Client:
@FeignClient(name = "user-service")
public interface UserFeignClient {
@GetMapping("/user/{id}")
ResponseEntity<UserDTO> getUserById(@PathVariable Long id);
}
Feign会自动集成Ribbon,实现客户端负载均衡。
需要注意:Feign 默认使用 JDK 原生的 URLConnection 发送 HTTP 请求,性能不高。我们后来换成了OkHttp并启用连接池:
feign:
client:
config:
default:
http:
connect-timeout: 3s
read-timeout: 5s
okhttp:
enabled: true
第三步:统一API网关(Spring Cloud Gateway)
引入Gateway依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
配置路由规则:
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://user-service
predicates:
- Path=/api/user/**
filters:
- StripPrefix=1
这样 /api/user/123 就会被转发到 user-service 的 /user/123 接口上。
第四步:分布式配置管理(Nacos Config)
创建 bootstrap.yml:
spring:
application:
name: user-service
cloud:
nacos:
config:
server-addr: localhost:8848
file-extension: yaml
namespace: your-namespace-id
extension-configs:
- data-id: user-service.yaml
group: DEFAULT_GROUP
refresh: true
在Nacos控制台创建一个data-id为 user-service.yaml 的配置项,内容即可动态刷新而无需重启服务。
第五步:流量防护(Sentinel)
引入依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
启动Sentinel Dashboard:
docker run --name sentinel-dashboard -p 8858:8858 -d bladex/sentinel-dashboard
在Nacos中配置流控规则(略)。也可以通过Dashboard界面手动配置实时规则。
我们还实现了自定义限流异常处理器:
@Component
public class CustomBlockHandler implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
response.setStatus(429);
response.getWriter().write("Too many requests.");
}
}
第六步:链路追踪(SkyWalking)
为了实现全链路跟踪,我们选择了SkyWalking。
安装SkyWalking OAP和UI(建议使用Docker):
docker run --name oap -d -e COLLECTOR_BACKEND_SERVICES=127.0.0.1:11800 -p 11800:11800 -p 12800:12800 apache/skywalking-oap-server
docker run --name ui -d -p 8080:8080 -e SW_HOST=127.0.0.1 apache/skywalking-ui
然后在每个微服务中加入Agent:
-javaagent:/path/to/skywalking-agent.jar
-Dskywalking.agent.service_name=your-service-name
这样就能在SkyWalking UI中看到完整的服务拓扑、接口响应时间、SQL耗时分析等内容,极大提升了定位线上问题的效率。
踩坑总结:那些你可能也会遇到的问题
1. Nacos集群部署坑太多?
初期我们图省事用了Standalone模式,但生产环境一定要部署集群。否则一旦挂掉,整个服务发现机制就会瘫痪。我们吃过亏,在一次服务器断电后,服务注册全都丢失了。
✅ 解决方法:使用Nacos集群 + 外部MySQL持久化数据。注意不要忘记配置持久化插件。
2. Feign调用超时怎么办?
曾经有一次,服务A调用服务B的某个接口频繁出现超时,但直接调用服务B又没问题。
排查下来发现,Ribbon + Feign默认的超时时间太短,而且没有重试机制。后来我们在配置中设置了合理的超时时间和重试策略:
ribbon:
ConnectTimeout: 3000
ReadTimeout: 5000
OkToRetryOnAllOperations: true
MaxAutoRetriesNextServer: 2
3. 微服务启动慢如蜗牛?
Spring Boot启动本身就不算快,再加上各种Spring Cloud组件,动辄十几秒甚至几十秒的启动时间让人崩溃。
✅ 优化技巧:
使用懒加载(Lazy Initialization):
spring: main: lazy-initialization: true排除不必要的自动注入组件
使用GraalVM Native Image(如果你愿意接受更高成本)
4. 分布式事务Seata不好用?
Seata在最初确实给我们带来了很多困扰,尤其是在事务回滚日志过多、性能瓶颈等问题。
✅ 最终折中方案:
- 对于非强一致性要求的场景,采用最终一致性的异步补偿机制(如RocketMQ事务消息)
- Seata仅用于核心交易场景
- 使用Saga模式替代AT模式,减少锁竞争
成果展示:架构升级后的收益
经过半年的重构和灰度迁移,我们成功将原有单体系统逐步拆分为十几个微服务,取得了不错的成果:
| 指标 | 拆分前 | 拆分后 |
|---|---|---|
| 上线频率 | 每月1~2次 | 每周1~2次 |
| 平均部署时间 | 30分钟以上 | 5分钟以内 |
| 故障隔离效果 | 一处故障影响全局 | 仅影响相关服务 |
| 系统扩展能力 | 固定部署 | 动态扩缩容 |
| 开发协同难度 | 高 | 中低 |
| 运维复杂度 | 低 | 稍高 |
| 性能监控能力 | 差 | 完善(链路+日志+指标) |
我的一些建议:从血泪教训中学到的
✅ 不要一开始就追求“高大上”的架构
我见过不少新手一上来就想用 Istio、Kubernetes,结果最后连最基本的Feign调用都没搞明白。
微服务不是灵丹妙药。先想清楚业务是否真的需要拆分、数据模型是否能支撑,再决定是否要用这套体系。
✅ 做好运维准备
微服务意味着更多的节点、更多的服务实例、更多潜在的故障点。如果没有完善的监控告警系统,你会陷入无尽的debug地狱。
我们后期上了Prometheus + Grafana + ELK做监控,每天定时巡检日志,发现问题及时通知。
✅ 关注数据库的设计
微服务拆分不仅仅是代码层面的拆分,数据层面的去中心化才是难点。每个服务要有自己独立的数据源,避免共享数据库。
可以考虑使用 Event Sourcing 或 CQRS 模式,把数据同步问题转化为事件驱动的异步流程。
结语:微服务之路才刚刚开始
这篇文章除了教你如何从零开始搭建Spring Cloud微服务系统外,更重要的是一种工程思维的转变:从“我只需要完成这个接口”转向“我需要确保这个服务长期稳定地运转”。
微服务并不是终点,未来也许会有更好的架构方式,比如Service Mesh、边缘计算等方向。但不管怎样,Spring Cloud仍然是当下最适合大多数公司的微服务解决方案。
希望这篇文章能够帮助你少走一些弯路。记住一句话:
“微服务不是写出来的,是演进出来的。”
愿你在微服务的世界里,越走越远,越走越稳。
如果你在学习过程中遇到了什么问题,欢迎留言或私信交流。咱们程序员之间,就是要相互照应。

评论 0