Spring Cloud 概述
什么是 Spring Cloud
Spring Cloud 是基于 Spring Boot 的微服务架构开发工具集,为开发者提供了在分布式系统(如配置管理、服务发现、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话、集群状态)中快速构建一些常见模式的工具。
- 核心功能
- 服务注册与发现:自动管理服务实例
- 配置中心:集中管理配置文件
- 负载均衡:客户端负载均衡
- 熔断器:服务容错和降级
- API 网关:统一入口和路由
- 消息驱动:事件驱动架构
- 主要优势
- 开箱即用:基于 Spring Boot,快速启动
- 生态完善:涵盖微服务开发的各个方面
- 社区活跃:大量生产实践案例
- 灵活扩展:可替换各个组件的实现
Spring Cloud 的核心概念
微服务架构
将单体应用拆分为多个小型、独立部署的服务,每个服务专注于单一职责。
1 2 3
| 传统单体架构 vs 微服务架构: 单体: 所有功能在一个应用中,耦合度高,扩展困难 微服务: 功能拆分为多个服务,独立部署,易于扩展和维护
|
服务治理
管理和协调微服务之间的通信和依赖关系。
| 组件 |
功能 |
代表实现 |
| 服务注册与发现 |
管理服务实例的注册和发现 |
Eureka, Nacos, Consul |
| 配置中心 |
集中管理配置信息 |
Config Server, Nacos Config |
| 负载均衡 |
分散请求到多个服务实例 |
Ribbon, LoadBalancer |
| 熔断器 |
防止雪崩效应,服务降级 |
Hystrix, Sentinel, Resilience4j |
| API 网关 |
统一入口,路由转发 |
Zuul, Gateway |
| 消息总线 |
配置刷新通知 |
Bus, RocketMQ |
Spring Cloud 的工作原理
服务调用流程
1 2 3 4 5 6
| 1. 服务提供者启动时向注册中心注册 2. 服务消费者从注册中心获取服务列表 3. 通过负载均衡选择具体实例 4. 发起远程调用(REST/RPC) 5. 熔断器监控调用状态 6. 异常时触发降级逻辑
|
配置刷新流程
1 2 3 4 5
| 1. 修改配置中心的配置 2. 发送刷新通知到消息总线 3. 各服务实例监听消息总线 4. 接收到通知后重新加载配置 5. 无需重启服务即可生效
|
环境搭建
版本对应关系
Spring Cloud 与 Spring Boot 有严格的版本对应关系。
| Spring Cloud |
Spring Boot |
| 2022.0.x (Kilburn) |
3.0.x |
| 2021.0.x (Jubilee) |
2.6.x |
| 2020.0.x (Ilford) |
2.4.x |
| Hoxton |
2.2.x, 2.3.x |
| Greenwich |
2.1.x |
最新稳定版:推荐使用 Spring Cloud 2022.0.x + Spring Boot 3.0.x
父工程配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>cloud-parent</artifactId> <version>1.0.0</version> <packaging>pom</packaging> <properties> <java.version>17</java.version> <spring-boot.version>3.0.0</spring-boot.version> <spring-cloud.version>2022.0.0</spring-cloud.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
|
服务注册与发现
Eureka
添加依赖
1 2 3 4 5 6 7 8 9 10 11
| <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency>
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
|
Eureka Server
启动类
1 2 3 4 5 6 7
| @SpringBootApplication @EnableEurekaServer public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } }
|
配置文件
1 2 3 4 5 6 7 8 9 10 11
| server: port: 8761
eureka: instance: hostname: localhost client: register-with-eureka: false fetch-registry: false server: enable-self-preservation: false
|
Eureka Client
启动类
1 2 3 4 5 6 7
| @SpringBootApplication @EnableDiscoveryClient public class UserServiceApplication { public static void main(String[] args) { SpringApplication.run(UserServiceApplication.class, args); } }
|
配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13
| server: port: 8081
spring: application: name: user-service
eureka: client: service-url: defaultZone: http://localhost:8761/eureka/ instance: prefer-ip-address: true
|
Nacos(推荐)
添加依赖
1 2 3 4 5
| <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <version>2022.0.0.0</version> </dependency>
|
启动类
1 2 3 4 5 6 7
| @SpringBootApplication @EnableDiscoveryClient public class UserServiceApplication { public static void main(String[] args) { SpringApplication.run(UserServiceApplication.class, args); } }
|
配置文件
1 2 3 4 5 6 7 8 9 10 11 12
| server: port: 8081
spring: application: name: user-service cloud: nacos: discovery: server-addr: localhost:8848 namespace: dev group: DEFAULT_GROUP
|
安装 Nacos
1 2 3 4 5 6 7 8 9 10 11 12 13
| wget https://github.com/alibaba/nacos/releases/download/2.2.0/nacos-server-2.2.0.tar.gz
tar -xzf nacos-server-2.2.0.tar.gz
cd nacos/bin sh startup.sh -m standalone
|
服务调用
RestTemplate + LoadBalancer
配置 RestTemplate
1 2 3 4 5 6 7 8 9
| @Configuration public class RestTemplateConfig { @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } }
|
服务调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @Service public class OrderService { @Autowired private RestTemplate restTemplate; public Order createOrder(Order order) { String url = "http://user-service/users/" + order.getUserId(); User user = restTemplate.getForObject(url, User.class); order.setUserName(user.getName()); return orderRepository.save(order); } }
|
OpenFeign(推荐)
添加依赖
1 2 3 4
| <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
|
启用 Feign
1 2 3 4 5 6 7
| @SpringBootApplication @EnableFeignClients public class OrderServiceApplication { public static void main(String[] args) { SpringApplication.run(OrderServiceApplication.class, args); } }
|
定义 Feign 接口
1 2 3 4 5 6 7 8 9
| @FeignClient(name = "user-service") public interface UserClient { @GetMapping("/users/{id}") User getUserById(@PathVariable("id") Integer id); @PostMapping("/users") User createUser(@RequestBody User user); }
|
使用 Feign 客户端
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Service public class OrderService { @Autowired private UserClient userClient; public Order createOrder(Order order) { User user = userClient.getUserById(order.getUserId()); order.setUserName(user.getName()); return orderRepository.save(order); } }
|
Feign 配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| feign: client: config: user-service: connectTimeout: 5000 readTimeout: 5000 loggerLevel: FULL compression: request: enabled: true mime-types: text/xml,application/xml,application/json min-request-size: 2048 response: enabled: true
|
配置中心
Spring Cloud Config
Config Server
添加依赖
1 2 3 4
| <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency>
|
启动类
1 2 3 4 5 6 7
| @SpringBootApplication @EnableConfigServer public class ConfigServerApplication { public static void main(String[] args) { SpringApplication.run(ConfigServerApplication.class, args); } }
|
配置文件
1 2 3 4 5 6 7 8 9 10 11 12
| server: port: 8888
spring: cloud: config: server: git: uri: https://github.com/example/config-repo.git search-paths: configs username: your-username password: your-password
|
Config Client
添加依赖
1 2 3 4
| <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency>
|
配置文件(bootstrap.yml)
1 2 3 4 5 6 7 8
| spring: application: name: user-service cloud: config: uri: http://localhost:8888 profile: dev label: main
|
动态刷新配置
1 2 3 4 5 6 7 8 9 10 11 12
| @RestController @RefreshScope public class ConfigController { @Value("${app.message:Hello}") private String message; @GetMapping("/message") public String getMessage() { return message; } }
|
Nacos Config(推荐)
添加依赖
1 2 3 4 5
| <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> <version>2022.0.0.0</version> </dependency>
|
配置文件(bootstrap.yml)
1 2 3 4 5 6 7 8 9 10
| spring: application: name: user-service cloud: nacos: config: server-addr: localhost:8848 file-extension: yaml namespace: dev group: DEFAULT_GROUP
|
动态刷新
1 2 3 4 5 6 7 8 9 10 11 12
| @RestController @RefreshScope public class ConfigController { @Value("${app.message:Hello}") private String message; @GetMapping("/message") public String getMessage() { return message; } }
|
负载均衡
Spring Cloud LoadBalancer
添加依赖
1 2 3 4
| <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency>
|
负载均衡策略
1 2 3 4 5 6 7 8 9 10 11 12 13
| @Configuration public class LoadBalancerConfig { @Bean public ReactorLoadBalancer<ServiceInstance> randomLoadBalancer( Environment environment, LoadBalancerClientFactory loadBalancerClientFactory) { String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME); return new RandomLoadBalancer( loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name ); } }
|
内置策略
| 策略 |
说明 |
| RoundRobinLoadBalancer |
轮询(默认) |
| RandomLoadBalancer |
随机 |
| WeightedResponseTimeLoadBalancer |
加权响应时间 |
熔断器
Sentinel(推荐)
添加依赖
1 2 3 4 5
| <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> <version>2022.0.0.0</version> </dependency>
|
配置文件
1 2 3 4 5 6 7 8 9 10 11 12
| spring: cloud: sentinel: transport: dashboard: localhost:8080 datasource: ds1: nacos: server-addr: localhost:8848 data-id: ${spring.application.name}-sentinel-rules group-id: DEFAULT_GROUP rule-type: flow
|
流控规则
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @Service public class UserService { @SentinelResource(value = "getUserById", blockHandler = "handleBlock") public User getUserById(Integer id) { return userRepository.findById(id) .orElseThrow(() -> new RuntimeException("用户不存在")); } public User handleBlock(Integer id, BlockException ex) { log.warn("触发限流或降级: {}", id); return new User(); } }
|
安装 Sentinel
1 2 3 4 5 6 7 8 9
| wget https://github.com/alibaba/Sentinel/releases/download/1.8.6/sentinel-dashboard-1.8.6.jar
java -jar sentinel-dashboard-1.8.6.jar
|
Resilience4j
添加依赖
1 2 3 4 5
| <dependency> <groupId>io.github.resilience4j</groupId> <artifactId>resilience4j-spring-boot2</artifactId> <version>1.7.1</version> </dependency>
|
熔断器配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Service public class UserService { @CircuitBreaker(name = "userService", fallbackMethod = "fallback") public User getUserById(Integer id) { return userRepository.findById(id) .orElseThrow(() -> new RuntimeException("用户不存在")); } public User fallback(Integer id, Throwable t) { log.error("服务调用失败: {}", t.getMessage()); return new User(); } }
|
1 2 3 4 5 6 7 8
| resilience4j: circuitbreaker: instances: userService: sliding-window-size: 10 failure-rate-threshold: 50 wait-duration-in-open-state: 10s permitted-number-of-calls-in-half-open-state: 5
|
API 网关
Spring Cloud Gateway
添加依赖
1 2 3 4
| <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>
|
基本配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| server: port: 8080
spring: cloud: gateway: routes: - id: user-service uri: lb://user-service predicates: - Path=/api/users/** filters: - StripPrefix=1 - id: order-service uri: lb://order-service predicates: - Path=/api/orders/** filters: - StripPrefix=1
|
自定义过滤器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| @Component public class AuthFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); String token = request.getHeaders().getFirst("Authorization"); if (token == null || !token.startsWith("Bearer ")) { exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().setComplete(); } return chain.filter(exchange); } @Override public int getOrder() { return -1; } }
|
限流配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| spring: cloud: gateway: routes: - id: user-service uri: lb://user-service predicates: - Path=/api/users/** filters: - name: RequestRateLimiter args: redis-rate-limiter.replenishRate: 10 redis-rate-limiter.burstCapacity: 20 key-resolver: "#{@ipKeyResolver}"
|
1 2 3 4 5 6 7 8 9 10
| @Configuration public class RateLimiterConfig { @Bean public KeyResolver ipKeyResolver() { return exchange -> Mono.just( exchange.getRequest().getRemoteAddress().getAddress().getHostAddress() ); } }
|
最佳实践
服务拆分原则
1 2 3 4 5
| 1. 单一职责:每个服务只负责一个业务领域 2. 独立部署:服务可以独立部署和升级 3. 数据隔离:每个服务有自己的数据库 4. 轻量通信:使用 REST 或 gRPC 进行通信 5. 容错设计:考虑服务失败的情况
|
配置管理
1 2 3 4 5 6 7 8 9
| spring: datasource: password: ${DB_PASSWORD}
spring: profiles: active: ${SPRING_PROFILES_ACTIVE:dev}
|
日志追踪
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @Component public class TraceIdFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { String traceId = UUID.randomUUID().toString(); MDC.put("traceId", traceId); ServerHttpResponse response = exchange.getResponse(); response.getHeaders().add("X-Trace-Id", traceId); return chain.filter(exchange).doFinally(signalType -> MDC.clear()); } @Override public int getOrder() { return -1; } }
|
监控告警
1 2 3 4 5
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
|
1 2 3 4 5 6 7 8
| management: endpoints: web: exposure: include: health,info,metrics,prometheus endpoint: health: show-details: always
|
常见问题
服务注册失败
1 2 3 4 5 6 7 8 9 10 11
| 问题:服务无法注册到注册中心
错误原因: 1. 注册中心未启动 2. 网络不通 3. 配置错误
解决方案: 1. 检查注册中心是否正常运行 2. 确认网络连接正常 3. 检查 server-addr 配置是否正确
|
服务调用超时
1 2 3 4 5 6 7 8 9
| 问题:Feign 调用超时
解决方案: 1. 增加超时时间 feign.client.config.default.connectTimeout=5000 feign.client.config.default.readTimeout=5000
2. 优化服务性能 3. 使用异步调用
|
报错处理
💗💗 Spring Cloud 报错:No instances available
1 2 3 4 5 6 7 8 9 10 11 12
| 错误信息: No instances available for xxx-service
错误原因: 1. 服务未注册 2. 服务名不匹配 3. 注册中心连接失败
解决方案: 1. 检查服务是否正常启动并注册 2. 确认服务名与注册中心一致 3. 检查注册中心配置
|
💗💗 Spring Cloud 报错:ConnectTimeoutException
1 2 3 4 5 6 7 8 9 10 11 12
| 错误信息: ConnectTimeoutException: Connect to xxx timed out
错误原因: 1. 目标服务未启动 2. 网络问题 3. 超时时间设置过短
解决方案: 1. 确认目标服务正常运行 2. 检查网络连接 3. 增加超时时间配置
|
学习资源
- 视频
- 尚硅谷 SpringCloud 教程:
https://www.bilibili.com/video/BV1UJc2ezEFU
- 官方文档
- Spring Cloud 官方文档:
https://spring.io/projects/spring-cloud
- Spring Cloud Alibaba:
https://spring-cloud-alibaba-group.github.io/github-pages/hoxton/zh-cn/index.html
- 书籍
- 《Spring Cloud 微服务实战》:翟永超著
- 《深入理解 Spring Cloud 与微服务构建》:方志朋著
- 教程
- Spring Cloud 入门教程:
https://www.baeldung.com/category/spring-cloud/
- Baeldung Spring Cloud 教程:
https://www.baeldung.com/category/spring-cloud/
- 社区
- Stack Overflow Spring Cloud 标签:
https://stackoverflow.com/questions/tagged/spring-cloud
- Spring 中文社区:
https://spring.io/projects