Skip to content
第 221 / 250 章架构⏱ 12 分钟阅读

第 221 章:Spring Cloud 入门

学习目标

  • 理解 Spring Cloud 全家桶
  • 掌握版本选型
  • 搭建第一个 Spring Cloud 应用
  • 了解核心组件协同

一、Spring Cloud 简介

Spring Cloud 是基于 Spring Boot 的微服务框架,提供分布式系统常用模式。

1.1 核心组件

组件替代品作用
Spring Cloud GatewayZuul, KongAPI 网关
Nacos DiscoveryEureka, Consul服务注册与发现
OpenFeignRestTemplate, WebClient声明式 HTTP 客户端
Spring Cloud LoadBalancerRibbon客户端负载均衡
Spring Cloud ConfigNacos Config, Apollo配置中心
SentinelHystrix, Resilience4j熔断限流
Spring Cloud Stream直接用 MQ消息驱动
Spring Cloud BusRabbitMQ, Kafka配置广播
Spring Cloud SleuthZipkin链路追踪

1.2 与 Spring Boot 版本对应

Spring CloudSpring Boot
2023.0.x3.2.x
2022.0.x3.0.x
2021.0.x2.7.x
Hoxton2.3.x

注意:Spring Boot 3.x 后,JDK 17+。

二、版本生态

2.1 主流选择

推荐:Spring Cloud 2023.x + Nacos + Sentinel + Spring Cloud Gateway

2.2 父 POM

xml
<parent>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-parent</artifactId>
    <version>2023.0.1</version>
</parent>

2.3 Nacos 替代方案

特性NacosEurekaConsul
健康检查
配置中心
多语言
一致性协议AP/CPAPCP
推荐度⭐⭐⭐⭐⭐⚠️ 停维⭐⭐⭐

三、快速搭建

3.1 项目结构

ms-demo/
├── order-service/
│   ├── pom.xml
│   └── src/
├── payment-service/
└── inventory-service/

3.2 注册中心(Nacos)

启动 Nacos Server:

bash
docker run -d --name nacos \
  -p 8848:8848 -p 9848:9848 \
  -e MODE=standalone \
  nacos/nacos-server:v2.3.0

访问: http://localhost:8848/nacos(默认账号 nacos/nacos)

3.3 第一个微服务:订单服务

pom.xml:

xml
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
</dependencies>

application.yml:

yaml
server:
  port: 8081

spring:
  application:
    name: order-service
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics

启动类:

java
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class, args);
    }
}

启动后,Nacos 控制台 服务列表 应出现 order-service

四、服务调用:OpenFeign

4.1 客户端声明

java
@FeignClient("inventory-service")
public interface InventoryClient {

    @GetMapping("/api/inventory/{skuId}")
    InventoryDTO getStock(@PathVariable String skuId);

    @PostMapping("/api/inventory/deduct")
    Result<Void> deduct(@RequestBody DeductRequest req);
}

4.2 在 Controller 中使用

java
@RestController
@RequestMapping("/api/orders")
@RequiredArgsConstructor
public class OrderController {

    private final OrderService orderService;
    private final InventoryClient inventoryClient;

    @PostMapping
    public Result<OrderDTO> create(@RequestBody OrderRequest req) {
        // 远程调用库存服务
        InventoryDTO stock = inventoryClient.getStock(req.skuId());
        if (stock.getQuantity() < req.quantity()) {
            return Result.error(20002, "库存不足");
        }
        return Result.ok(orderService.create(req));
    }
}

4.3 Feign 配置

yaml
feign:
  client:
    config:
      default:
        connectTimeout: 5000
        readTimeout: 10000
        loggerLevel: BASIC
  compression:
    request:
      enabled: true
  sentinel:
    enabled: true

4.4 Feign + Sentinel 熔断

java
@FeignClient(name = "inventory-service", fallback = InventoryFallback.class)
public interface InventoryClient {
    @GetMapping("/api/inventory/{skuId}")
    InventoryDTO getStock(@PathVariable String skuId);
}

@Component
public class InventoryFallback implements InventoryClient {
    @Override
    public InventoryDTO getStock(String skuId) {
        return InventoryDTO.busy();  // 降级返回
    }
}

五、网关:Gateway

5.1 第一个网关

pom.xml:

xml
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

application.yml:

yaml
server:
  port: 9000

spring:
  application:
    name: api-gateway
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    gateway:
      routes:
        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/api/orders/**
        - id: inventory-service
          uri: lb://inventory-service
          predicates:
            - Path=/api/inventory/**

5.2 自定义过滤器

java
@Component
public class AuthGatewayFilter implements GlobalFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String token = request.getHeaders().getFirst("Authorization");

        if (token == null) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }

        return chain.filter(exchange);
    }
}

六、配置中心

6.1 Nacos Config 集成

xml
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

bootstrap.yml(注意不是 application.yml):

yaml
spring:
  application:
    name: order-service
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848
        file-extension: yaml
        refresh-enabled: true

6.2 Nacos 中创建配置

DataId: order-service.yaml

yaml
order:
  timeout: 5000
  maxRetry: 3
server:
  port: 8081

6.3 动态刷新

java
@RefreshScope
@RestController
public class ConfigController {

    @Value("${order.timeout}")
    private int timeout;

    @GetMapping("/config")
    public String config() {
        return "timeout=" + timeout;
    }
}

七、链路追踪

7.1 集成 Sleuth + Zipkin

xml
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
yaml
spring:
  zipkin:
    base-url: http://localhost:9411
  sleuth:
    sampler:
      probability: 1.0

启动 Zipkin:

bash
docker run -d -p 9411:9411 openzipkin/zipkin

访问: http://localhost:9411

八、消息驱动:Stream

8.1 简化 MQ 使用

java
public interface OrderEventChannel {
    String INPUT = "order-events-in";
    String OUTPUT = "order-events-out";

    @Output(OUTPUT)
    MessageChannel out();

    @Input(INPUT)
    SubscribableChannel in();
}
java
@Service
@RequiredArgsConstructor
public class OrderEventPublisher {
    private final OrderEventChannel channel;

    public void publish(OrderEvent event) {
        channel.out().send(MessageBuilder.withPayload(event).build());
    }
}
java
@Component
public class OrderEventSubscriber {

    @StreamListener(OrderEventChannel.INPUT)
    public void handle(OrderEvent event) {
        log.info("收到事件: {}", event);
    }
}

九、Spring Cloud 生态完整图

十、演进路线

十一、常见错误

错误解决
UnknownHostException注册中心未启动 / 网络不通
Load balancer does not have available server未启用 lb:// 或未引入负载均衡
Feign 404注意 @PathVariable 注解
配置不生效bootstrap.yml 优先于 application.yml
熔断器不生效没加 @SentinelResource@EnableCircuitBreaker

十二、本章小结

组件作用学习章节
Nacos注册 + 配置222
OpenFeign服务调用223
GatewayAPI 网关224
Config配置中心225
Sentinel熔断限流微服务治理章
Sleuth链路追踪见 73 章

动手练习

  1. 用 Spring Boot 3.2 + Spring Cloud 2023 创建 2 个服务,接入 Nacos
  2. 用 OpenFeign 实现服务间调用
  3. 搭建 Spring Cloud Gateway,做路由转发
  4. 用 Nacos Config 做动态配置

推荐阅读


下一章:第 222 章:Spring Cloud Gateway 网关

本站基于 VitePress 构建 · 由 Codebook 团队维护