Skip to content

06-SpringCloud(Nacos / Feign / Gateway)

对应原始资料:微服务框架课件/02-SpringCloud0103-SpringCloud02

一、微服务架构

把单体应用按业务拆分成多个独立部署的小服务,每个服务:

  • 独立技术栈、独立数据库。
  • 通过 HTTP/RPC 互相通信。
  • 独立部署、扩容。

带来的问题与解决方案

问题组件
服务怎么管(注册发现)Nacos / Eureka
服务怎么调OpenFeign
请求入口/路由Gateway
配置怎么统一Nacos Config
雪崩怎么防Sentinel
跨服务事务Seata
调用链追踪SkyWalking / Zipkin

二、SpringCloud Alibaba 生态

  • Nacos:注册中心 + 配置中心。
  • Sentinel:熔断限流。
  • Seata:分布式事务。
  • RocketMQ:消息队列。
  • Dubbo:RPC(可选)。

三、Nacos 注册中心

1. 启动 Nacos

bash
docker run -d --name nacos -p 8848:8848 -e MODE=standalone nacos/nacos-server

访问 http://localhost:8848/nacos,默认 nacos/nacos

2. 服务注册

xml
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
yaml
spring:
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
  application:
    name: user-service

启动后服务自动注册到 Nacos。

3. 服务发现

java
@Autowired private DiscoveryClient discoveryClient;
List<ServiceInstance> instances = discoveryClient.getInstances("order-service");

四、OpenFeign(声明式远程调用)

像调本地方法一样调远程服务。

1. 开启

java
@EnableFeignClients
@SpringBootApplication
public class App { }

2. 定义接口

java
@FeignClient(name = "order-service")
public interface OrderClient {
    @GetMapping("/orders/{id}")
    Order getById(@PathVariable Long id);

    @PostMapping("/orders")
    Order create(@RequestBody Order order);
}

3. 使用

java
@Autowired private OrderClient orderClient;
Order o = orderClient.getById(1L);

Feign 自动做:服务发现 → 负载均衡(Ribbon/LoadBalancer)→ HTTP 调用。

4. 性能优化

  • 替换默认 URLConnection 为 OkHttp / Apache HttpClient(连接池)。
  • 合理设置超时、重试。
  • 日志级别 BASIC 即可。

五、Nacos 配置中心

1. 引依赖

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

2. bootstrap.yml

yaml
spring:
  application:
    name: user-service
  profiles:
    active: dev
  cloud:
    nacos:
      config:
        server-addr: localhost:8848
        file-extension: yaml

Nacos 中创建 user-service-dev.yaml,启动后自动拉取。

3. 配置热更新

java
@RestController
@RefreshScope
public class ConfigController {
    @Value("${my.prop}")
    private String prop;
}

Nacos 中改配置 → 服务无需重启。

4. 配置共享

  • application.yaml:所有环境共享。
  • user-service.yaml:所有该服务共享。
  • user-service-dev.yaml:特定环境。

六、SpringCloud Gateway 网关

1. 作用

  • 统一入口、路由转发。
  • 鉴权、限流、日志。
  • 跨域处理。

2. 依赖(注意不能引 web starter)

xml
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

3. 路由配置

yaml
spring:
  cloud:
    gateway:
      routes:
        - id: user
          uri: lb://user-service              # 负载均衡
          predicates:
            - Path=/user/**                    # 断言
          filters:
            - StripPrefix=1                    # 去掉第一段路径前缀
        - id: order
          uri: lb://order-service
          predicates:
            - Path=/order/**

访问 http://gateway:10010/user/1 → 转发到 user-service/1

4. 断言 Predicate

PathMethodHeaderQueryHostAfter/Before/BetweenWeight

5. 过滤器 Filter

  • 内置:AddRequestHeaderStripPrefixRewritePathRequestRateLimiter(限流)。
  • GlobalFilter:自定义全局过滤器(鉴权常用):
java
@Component
public class AuthFilter implements GlobalFilter, Ordered {
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getHeaders().getFirst("token");
        if (token == null) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }
    public int getOrder() { return -1; }
}

6. 跨域配置

yaml
spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            allowedOriginPatterns: "*"
            allowedMethods: "*"
            allowedHeaders: "*"
            allowCredentials: true

七、负载均衡

SpringCloud 2020+ 用 Spring Cloud LoadBalancer 替代 Ribbon。Feign/Gateway 集成它做客户端负载均衡。

八、微服务调用链路图

浏览器 → Gateway(10010) → user-service(8081) → Feign → order-service(8082)
                              ↓ 注册/发现
                            Nacos(8848)

练习建议

  1. 用 Nacos + 两个微服务(user/order)完成一次跨服务调用。
  2. 在 user-service 中用 Feign 调用 order-service 的接口。
  3. 加 Gateway,统一从网关进入。
  4. 把数据库配置放到 Nacos,改配置热更新生效。
  5. 写一个鉴权 GlobalFilter。