基于 Spring Cloud 的 Java 微服务实战:从单体到微服务迁移
对于 Java 项目而言,引入 Spring Cloud 实现微服务架构能显著提升技术含量和答辩印象分,更是一次非常好的学习实践。本文将结合实战经验,介绍如何从零开始,把一个单体应用平滑迁移成基于 Spring Cloud 的微服务项目。
1. 为什么需要从单体走向微服务?
毕设的目的不仅仅是'完成功能',更是'展示能力'和'学习新知'。
单体应用的局限性:
- 技术栈单一:难以体现对分布式系统、服务治理等现代后端架构的理解。
- 扩展性差:面对用户量激增时,单体架构很难给出有说服的扩展方案。
- 耦合度高:所有功能模块在一起,修改一处可能影响全局,代码结构容易混乱。
引入微服务的必要性:
- 技术亮点:使用 Spring Cloud 本身是一项重要技能,能让你在众多项目中脱颖而出。
- 架构清晰:通过服务拆分(如用户服务、订单服务),项目结构清晰,模块职责分明。
- 接触工程化实践:实际接触到服务注册发现、配置管理、负载均衡、容错处理等生产环境概念。

2. Spring Cloud 技术选型建议
对于新手,推荐以下主流且易用的选型组合:
- 服务注册与发现:Nacos
- 放弃 Eureka:Spring Cloud 官方已停止对其迭代。
- 选择 Nacos:支持服务注册发现及配置中心,社区活跃,中文资料多。
- 服务网关:Spring Cloud Gateway
- 放弃 Zuul 1.x:基于阻塞 IO,性能一般。
- 选择 Gateway:Spring 官方亲儿子,基于响应式编程,性能更好。
- 服务间调用:OpenFeign
- 放弃 RestTemplate:需要自己拼接 URL。
- 选择 OpenFeign:声明式的 HTTP 客户端,代码简洁,像调用本地方法一样调用远程服务。
- 熔断降级:Resilience4j 或 Sentinel
- 放弃 Hystrix:已停止开发。
- 选择 Resilience4j:轻量级,功能专注;或 Sentinel:阿里开源,可视化效果好。
总结技术栈:Spring Boot + Spring Cloud + Nacos + Gateway + OpenFeign + Resilience4j。
3. 手把手搭建最小化微服务集群
假设毕设为简单'电商平台',拆分为三个服务:nacos-server、user-service、order-service。
第一步:搭建 Nacos Server
去 Nacos 官网下载最新稳定版(建议 2.x),解压后在 bin 目录下执行启动命令(单机模式):
# Linux/Mac
sh startup.sh -m standalone
# Windows
cmd startup.cmd -m standalone
访问 http://localhost:8848/nacos,默认账号密码均为 nacos。
第二步:创建父工程管理依赖
创建一个 Maven 父工程,在 pom.xml 中统一管理版本。
<!-- 父工程 pom.xml 关键部分 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.18</version>
</parent>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>2021.0.8</spring-cloud.version>
<spring-cloud-alibaba.version>2021.0.5.0</spring-cloud-alibaba.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- Spring Cloud 依赖管理 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Spring Cloud Alibaba 依赖管理 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
第三步:开发 user-service(服务提供者)
- 创建子模块
user-service。 - 引入关键依赖:
spring-boot-starter-web,spring-cloud-starter-alibaba-nacos-discovery。 - 主类添加
@EnableDiscoveryClient注解。
编写 REST 控制器:
@RestController
@RequestMapping("/users")
public class UserController {
@GetMapping("/{id}")
public String getUser(@PathVariable Long id) {
// 模拟查询数据库
return "用户信息:User_" + id;
}
}
配置文件 application.yml:
server:
port: 8081
spring:
application:
name: user-service
cloud:
nacos:
discovery:
server-addr: localhost:8848
第四步:开发 order-service(服务消费者,使用 OpenFeign)
- 创建子模块
order-service。 - 引入依赖:
spring-boot-starter-web,spring-cloud-starter-alibaba-nacos-discovery,spring-cloud-starter-openfeign。 - 主类添加
@EnableFeignClients注解。
在 OrderController 中注入并使用 UserServiceClient:
@RestController
@RequestMapping("/orders")
public class OrderController {
@Autowired
private UserServiceClient userServiceClient;
@GetMapping("/{orderId}")
public String getOrderWithUser(@PathVariable Long orderId) {
String orderInfo = "订单 ID: " + orderId;
String userInfo = userServiceClient.getUserById(1001L);
return orderInfo + " | " + userInfo;
}
}
关键步骤:声明 Feign 客户端接口
@FeignClient(name = "user-service")
public interface UserServiceClient {
@GetMapping("/users/{id}")
String getUserById(@PathVariable("id") Long id);
}
启动 order-service。访问 http://localhost:8082/orders/1,你会看到返回结果中包含了从 user-service 获取的用户信息。

4. 本地开发调试与基础安全
调试技巧:
- 服务多实例启动:在 IDEA 的'Edit Configurations'中,复制一个服务启动项,修改
VM options为-Dserver.port=8083,可测试负载均衡。 - Feign 日志:在
application.yml中配置logging.level.<你的 Feign 客户端接口全路径名>: DEBUG,查看详细请求信息。
基础安全配置(接口鉴权):
对于毕设,可使用 Spring Cloud Gateway 的过滤器进行简单的令牌校验。所有通过 Gateway 的请求都必须携带正确的 X-Token 头。
在 Gateway 服务的配置中添加全局过滤器:
@Component
public class AuthFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String token = exchange.getRequest().getHeaders().getFirst("X-Token");
if (token != null && "valid-token".equals(token)) {
return chain.filter(exchange);
}
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
@Override
public int getOrder() {
return -1;
}
}
5. 生产环境避坑指南
- 版本兼容性!
Spring Boot、Spring Cloud、Spring Cloud Alibaba 的版本必须严格匹配。随意组合会导致
ClassNotFoundException或配置失效。 - YAML 缩进错误 YAML 文件对缩进极其敏感。建议使用智能编辑器提示缩进错误。
- 服务启动成功,但 Nacos 上看不到
检查
application.yml中spring.cloud.nacos.discovery.server-addr配置是否正确,Nacos 服务器是否真的启动了。 - Feign 调用报错:UnknownHostException
确保服务提供者已成功注册,消费者
@FeignClient中的name与服务提供者的spring.application.name完全一致。
跨域问题(CORS) 当前端页面尝试访问后端微服务时,建议在 Gateway 服务中统一配置跨域:
spring:
cloud:
gateway:
globalcors:
cors-configurations:
'[/**]':
allowedOrigins: "*"
allowedMethods: "*"
allowedHeaders: "*"
6. 结尾与思考
按照上面的步骤,你应该已经拥有了一个虽然简单但'五脏俱全'的微服务毕设骨架。
扩展思考: 如何为你的毕设增加链路追踪?你可以去了解一下 Spring Cloud Sleuth 和 Zipkin(或 SkyWalking)。集成它们后,你可以在日志中看到唯一的 TraceId,或者在 Zipkin 的 UI 上看到漂亮的调用链图。
微服务的学习之路很长,最重要的是动手去试,遇到问题多查文档。祝你毕设顺利!
