从零开始搭建Spring Cloud微服务:踩坑路上的成长与实战经验分享
引言:为什么我们要用Spring Cloud?

去年,我加入了一个刚起步的技术项目,目标是重构一个原本单体架构的电商平台。随着业务增长,单体应用越来越臃肿,维护成本陡增,每次上线都要提心吊胆。为了提高系统的可维护性、可扩展性和发布效率,我们决定采用微服务架构,而 Spring Cloud 成为了我们的首选方案。
这篇文章不是一份教科书式的Spring Cloud教程,而是我在实际项目中,从0到1搭建微服务过程中的真实经历和踩坑记录。希望通过我的分享,能给刚开始接触Spring Cloud的朋友一些启发和避坑建议。
项目背景与初期挑战

项目是一个电商后台系统,涉及订单、库存、用户、支付等多个模块。原来的系统使用的是Spring Boot + MyBatis 的单体架构,部署在几台Tomcat上。随着新功能不断叠加,代码库已经膨胀到50万行以上,团队协作变得困难,部署也变得越来越痛苦。
我们需要:
- 将原有业务拆分为多个独立微服务
- 实现服务注册发现机制
- 支持服务间通信(RPC)
- 提供配置中心管理多环境配置
- 实现统一网关路由
- 集成日志收集和监控
- 最小化对现有业务的影响
听起来是不是还挺简单的?别急,接下来才是真正的挑战。
技术选型与整体架构设计
我们最终选择了以下技术栈:
- Spring Boot 2.6.x
- Spring Cloud 2021.0.3
- Nacos 作为注册中心和配置中心
- OpenFeign + LoadBalancer 做服务调用
- Gateway 做API网关
- Sentinel 做熔断限流
- Mysql + Druid + MyBatis Plus
- SkyWalking 做分布式追踪
- Nginx + Docker + Jenkins + Harbor 做CI/CD
架构图大致如下:
+--------------+
| Gateway |
+--------------+
|
+-----------+------------+
| |
+-------+-----+ +---------+-------+
| Order Service | | User Service |
+---------------+ +-----------------+
| |
+-------+-----+ +---------+-------+
| Inventory Ser.| | Payment Service |
+--------------+ +-----------------+

实战踩坑记

踩坑一:服务注册不上去了怎么办?
项目初期一切顺利,各个微服务跑起来,注册中心也能看到界面。但某天突然发现几个服务怎么都注册不上去,控制台也没有报错。经过排查,原来是本地hosts文件配置错误导致无法解析nacos地址……
教训:
微服务之间依赖关系复杂,基础网络环境必须稳定可靠。尤其是在测试环境中,不要随便改hosts或者docker网络模式,否则很容易陷入“连不上”的怪圈。
踩坑二:Feign调用超时、降级失效
我们在订单服务中调用了库存服务,一开始Feign没有开启负载均衡,直接写死了IP和端口。后来改为基于服务名的调用,但在高并发下频繁出现超时问题,Sentinel的降级规则也没生效。
最后发现是因为Feign的超时设置默认值太短,而且Sentinel的自动适配规则没打开。于是我们做了如下调整:
feign:
client:
config:
default:
http-read-timeout: 5000
connect-timeout: 5000
并且加上了启动参数:
-Dcsp.sentinel.api.port=8719 -Dproject.name=order-service
踩坑三:数据库连接池不够用了
当服务开始压测后,陆续出现连接池爆满的问题。虽然我们使用了Druid连接池,但初始连接池大小配置得太小,在突发流量下根本不够用。
解决方法:
- 动态扩容连接池大小,并合理设置maxActive和minIdle
- 使用Druid的监控面板实时查看状态
- 设置慢SQL监控,找出性能瓶颈
spring:
datasource:
druid:
initial-size: 5
min-idle: 5
max-active: 50
stat-view-servlet:
enabled: true
url-pattern: /druid/*
踩坑四:线上环境配置混乱
最开始我们每个服务都在自己本地写了application.yml,不同环境(dev、test、prod)靠手动修改来切换配置。上线前经常出错,比如把测试数据库地址误写进生产环境。
后来引入了Nacos作为配置中心,通过DataID的方式实现了配置的集中管理和动态刷新。
spring:
cloud:
nacos:
config:
server-addr: 192.168.1.100:8848
extension-configs:
- data-id: user-service.yaml
group: DEFAULT_GROUP
refresh: true
从此告别了配置混乱的时代,再也不怕上线改错了配置!
代码实践示例
这里给出一段核心的服务调用示例,使用Feign进行远程调用并配合Sentinel实现熔断降级。
定义Feign客户端接口:
@FeignClient(name = "inventory-service", path = "/api/inventory", fallback = InventoryServiceFallback.class)
public interface InventoryServiceClient {
@PostMapping("/deduct")
ResponseDTO deduct(@RequestBody DeductRequest request);
}
定义降级类:
@Component
public class InventoryServiceFallback implements InventoryServiceClient {
@Override
public ResponseDTO deduct(DeductRequest request) {
return ResponseDTO.fail("库存服务不可用,请稍后再试");
}
}
在启动类添加Feign支持:
@SpringBootApplication
@EnableFeignClients
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
}
效果与收益总结
经过几个月的努力,整个微服务架构基本成型,效果非常显著:
- 模块拆分清晰,代码结构更易维护
- 各个服务可以独立部署、升级、回滚
- 接口调用链清晰,SkyWalking帮助我们快速定位问题
- 配置中心大大提升了运维效率
- 熔断机制有效避免了雪崩效应
- 团队协作更加顺畅,研发迭代速度明显提升
当然,也带来了一些新的挑战,例如链路追踪复杂、跨服务事务处理等问题,但这些都可以通过后续引入Seata等分布式事务框架逐步解决。
给读者的建议
如果你也在尝试从零搭建Spring Cloud微服务,我有几点建议想分享给你:
从简单做起:先搭起最小可用系统,逐步完善功能模块。不要一开始就追求“高大上”,先把服务注册、调用、网关跑通再说。
重视基础设施建设:包括网络、域名、配置中心、日志收集、监控告警等。这些看似不起眼的东西,一旦线上出问题就至关重要。
注意版本兼容性:Spring Boot 和 Spring Cloud 对版本要求非常严格。建议参考官方文档或社区推荐的版本组合,避免因版本不匹配引发各种奇怪问题。
尽早集成链路追踪:哪怕只是SkyWalking或Zipkin,也可以帮你省下很多排查时间。
合理划分服务边界:服务不是越细越好,要根据业务领域模型做聚合。初期可以适当合并,后面再细化。
关注线上稳定性:微服务不是银弹,它会暴露更多细节。一定要做好异常处理、监控报警、容量评估等工作。
结语:踩过的坑都是成长的阶梯
回顾这段微服务改造之路,有过焦虑,也有过沮丧,但更多的是一步步解决问题后的成就感。现在每次看监控面板上的服务指标图,心里都会有一种踏实感——这是系统健康运行的最好证明。
其实技术从来都不是最难的部分,难的是如何将这些技术落地,真正服务于业务、支撑团队成长。希望我的分享能帮你在Spring Cloud这条路上少走些弯路。
如果你也在微服务实践中遇到难题,欢迎留言交流。我们一起踩坑、一起成长!

评论 0