第19课:Gateway过滤器、全局拦截、请求响应统一处理

文章目录

适配版本 :Spring Cloud Gateway 5.0.0、Spring Cloud 2025.1.3(Oakwood)、Spring Boot 4.0.8、Spring Cloud Alibaba 2025.1.0.0、JDK 21

课程定位:网关核心能力进阶,从局部过滤器到全局过滤器,从跨域配置到统一异常处理,构建网关层的完整拦截体系

一、开篇:过滤器是网关的"执行引擎"

第18课我们完成了路由规则的深度实战。路由解决了"请求去哪里"的问题,但请求在经过网关时,往往还需要做很多事情:验证Token是否合法、记录访问日志、添加内部调用Header、统一包装响应格式、处理跨域请求、捕获并友好展示异常。

这些跨切面关注点 ,如果分散在每个后端服务中实现,会导致大量重复代码,且难以统一维护。Gateway的过滤器(Filter) 机制,正是为了在网关层统一解决这些问题而设计的。

Gateway的过滤器体系分为两类:局部过滤器(GatewayFilter) 只对特定路由生效,全局过滤器(GlobalFilter) 对所有路由生效。两者在执行时合并为一条链,按order值排序后依次执行。这个设计与Servlet的Filter链非常相似,但基于Reactor的异步模型实现,理解其执行顺序和线程模型是掌握Gateway过滤器的关键。

本课将从过滤器的分类与执行顺序讲起,深入Pre和Post两个阶段的处理逻辑,实战跨域配置、参数校验、响应统一封装、异常统一拦截和全局日志打印,最后总结过滤器开发的最佳实践。

二、过滤器体系与执行顺序

2.1 两种过滤器的本质区别

Gateway的过滤器分为两类,核心区别在于作用范围和注册方式:

维度 GatewayFilter(局部过滤器) GlobalFilter(全局过滤器)
作用范围 仅对配置了该过滤器的路由生效 对所有路由生效
注册方式 在路由的filters列表中声明 实现GlobalFilter接口并注册为Bean
使用场景 特定路由的Header添加、路径重写 鉴权、日志、限流、异常处理
配置灵活性 高(可针对每个路由不同) 低(全局统一行为)
典型内置实现 AddRequestHeaderGatewayFilter GatewayMetricsFilter

核心理解:局部过滤器是"路由级别"的,全局过滤器是"应用级别"的。鉴权、日志、异常处理这类所有路由都需要的逻辑,应该用全局过滤器;特定路由的参数修改、路径重写,应该用局部过滤器。

2.2 过滤器链的合并与排序

当一个请求匹配到某个路由后,Gateway会将该路由的局部过滤器 和所有全局过滤器 合并为一条链,按order值从小到大排序后依次执行。

复制代码
请求进入
    │
    ▼
合并过滤器链:
    全局过滤器1 (order = -100)
    全局过滤器2 (order = -10)
    局部过滤器1 (order = 0)
    全局过滤器3 (order = 1)
    局部过滤器2 (order = 2)
    │
    ▼
按 order 升序依次执行

排序规则:

  • order值越小,优先级越高,越先执行
  • 全局过滤器实现Ordered接口或使用@Order注解指定顺序
  • 局部过滤器的order由过滤器工厂内部的OrderedGatewayFilter包装决定
  • 局部过滤器和全局过滤器混合排序,而非先执行完所有全局再执行局部

典型内置过滤器的order值:

过滤器 order 职责
RemoveCachedBodyFilter HIGHEST_PRECEDENCE 清理请求体缓存
AdaptCachedBodyGlobalFilter HIGHEST_PRECEDENCE + 1000 缓存请求体
NettyWriteResponseFilter -1 写响应回客户端
ForwardPathFilter 0 路径转发
RouteToRequestUrlFilter 10000 将路由URI转为请求URL
LoadBalancerClientFilter 10100 负载均衡选择实例
NettyRoutingFilter Integer.MAX_VALUE 发起下游请求

关键理解 :NettyRoutingFilter的order是Integer.MAX_VALUE,意味着它是最后一个执行的Pre过滤器。它之后的所有过滤器都是Post阶段------即下游响应返回后执行的逻辑。

2.3 Pre和Post两个阶段

Gateway的过滤器执行分为两个阶段:

Pre阶段(请求转发前) :过滤器链从第一个过滤器开始,依次执行filter()方法。每个过滤器可以选择:

  • 直接返回(短路),不再继续
  • 调用chain.filter(exchange),将请求传递给下一个过滤器
  • 在chain.filter(exchange)前后添加逻辑

Post阶段(响应返回后) :当NettyRoutingFilter发起下游请求并收到响应后,控制权反向回传 ,之前chain.filter()调用点之后的代码开始执行。

代码示例:

java 复制代码
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    // ===== Pre 阶段 =====
    log.info("请求进入: {}", exchange.getRequest().getPath());

    // 传递给下一个过滤器
    return chain.filter(exchange)
        .then(Mono.fromRunnable(() -> {
            // ===== Post 阶段 =====
            log.info("响应返回: {}", exchange.getResponse().getStatusCode());
        }));
}

关键理解 :chain.filter(exchange)返回的是一个Mono<Void>,.then()之后的逻辑在响应完成后执行。这就是Post阶段的实现方式。

三、局部过滤器实战

3.1 常用内置局部过滤器

Gateway内置了大量局部过滤器工厂,日常开发中最常用的包括:

过滤器 作用 配置示例
AddRequestHeader 添加请求头 AddRequestHeader=X-Request-Id, 12345
AddRequestParameter 添加请求参数 AddRequestParameter=source, gateway
AddResponseHeader 添加响应头 AddResponseHeader=X-Response-Time, 100ms
RemoveRequestHeader 删除请求头 RemoveRequestHeader=Cookie
RewritePath 路径重写 RewritePath=/api/(?<segment>.*), /${segment}
PrefixPath 路径前缀 PrefixPath=/api
StripPrefix 去除路径前缀 StripPrefix=1
Retry 自动重试 Retry=3
RequestRateLimiter 限流 RequestRateLimiter=...

3.2 StripPrefix:去除路径前缀

StripPrefix用于去除请求路径的前N段。例如前端调用/api/user/1,后端服务实际接收/user/1:

yaml 复制代码
spring:
  cloud:
    gateway:
      server:
        webflux:
          routes:
            - id: user_route
              uri: lb://service-user
              predicates:
                - Path=/api/user/**
              filters:
                - StripPrefix=1    # 去除第1段路径(/api)

StripPrefix=1表示去除路径的第1段,/api/user/1变为/user/1。

对比RewritePath :StripPrefix是按段数去除,RewritePath是按正则替换。前者更简单,后者更灵活。

3.3 AddRequestHeader:添加内部调用Header

在微服务架构中,网关是唯一的外部入口。为了安全,后端服务通常只信任来自网关的请求。网关可以在转发前添加一个内部标识Header:

yaml 复制代码
filters:
  - AddRequestHeader=X-Gateway-Source, internal

后端服务通过校验X-Gateway-Source: internal,拒绝绕过网关的直接访问。

生产实践 :这个Header的值应该是动态签名而非固定字符串,防止被伪造。签名算法可以基于时间戳和密钥生成,后端服务验证签名有效性。

3.4 局部过滤器与全局过滤器的选用

场景 推荐类型 原因
路径重写、前缀去除 局部过滤器 每个路由的路径规则不同
添加内部调用Header 局部过滤器 不同服务需要的Header不同
鉴权、日志、异常处理 全局过滤器 所有路由都需要
CORS跨域 全局配置(CorsWebFilter) 全局统一配置

四、全局过滤器实战

4.1 实现GlobalFilter接口

全局过滤器通过实现GlobalFilter和Ordered接口来定义:

java 复制代码
@Component
@Slf4j
public class AccessLogGlobalFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // ===== Pre 阶段 =====
        long startTime = System.currentTimeMillis();
        ServerHttpRequest request = exchange.getRequest();

        String path = request.getPath().value();
        String method = request.getMethod().name();
        String clientIp = getClientIp(request);

        log.info("[网关请求] {} {} from {}", method, path, clientIp);

        // ===== 传递给下一个过滤器 =====
        return chain.filter(exchange)
            .then(Mono.fromRunnable(() -> {
                // ===== Post 阶段 =====
                long cost = System.currentTimeMillis() - startTime;
                ServerHttpResponse response = exchange.getResponse();
                log.info("[网关响应] {} {} status={} cost={}ms",
                        method, path, response.getStatusCode(), cost);
            }));
    }

    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE + 100;
    }

    private String getClientIp(ServerHttpRequest request) {
        // 优先从代理Header中获取真实IP
        String ip = request.getHeaders().getFirst("X-Forwarded-For");
        if (ip == null || ip.isEmpty()) {
            ip = request.getHeaders().getFirst("X-Real-IP");
        }
        if (ip == null || ip.isEmpty()) {
            InetSocketAddress remoteAddress = request.getRemoteAddress();
            ip = remoteAddress != null ? remoteAddress.getAddress().getHostAddress() : "unknown";
        }
        return ip;
    }
}

关键规范:

  • getOrder()返回值决定过滤器在链中的位置
  • 日志类过滤器应尽早执行(order值小),确保能记录完整耗时
  • 响应状态的获取必须在Post阶段(.then()之后)

4.2 全局鉴权过滤器

鉴权是网关最核心的全局过滤器。以JWT鉴权为例:

java 复制代码
@Component
@Slf4j
public class AuthGlobalFilter implements GlobalFilter, Ordered {

    @Autowired
    private JwtUtils jwtUtils;

    private static final List<String> WHITE_LIST = List.of(
            "/api/auth/login",
            "/api/auth/register",
            "/api/public/**"
    );

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getPath().value();

        // 1. 白名单直接放行
        if (isWhiteList(path)) {
            return chain.filter(exchange);
        }

        // 2. 获取Token
        String token = request.getHeaders().getFirst("Authorization");
        if (token == null || !token.startsWith("Bearer ")) {
            return unauthorized(exchange, "缺少Token");
        }

        // 3. 验证Token
        token = token.substring(7);
        if (!jwtUtils.validate(token)) {
            return unauthorized(exchange, "Token无效或已过期");
        }

        // 4. 解析用户信息,注入到请求头中传递给下游服务
        Long userId = jwtUtils.getUserId(token);
        ServerHttpRequest mutatedRequest = request.mutate()
                .header("X-User-Id", String.valueOf(userId))
                .build();

        return chain.filter(exchange.mutate().request(mutatedRequest).build());
    }

    private boolean isWhiteList(String path) {
        return WHITE_LIST.stream().anyMatch(pattern ->
                new AntPathMatcher().match(pattern, path));
    }

    private Mono<Void> unauthorized(ServerWebExchange exchange, String message) {
        ServerHttpResponse response = exchange.getResponse();
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);

        Result<Void> result = Result.fail(401, message);
        byte[] bytes = JSON.toJSONBytes(result);
        DataBuffer buffer = response.bufferFactory().wrap(bytes);
        return response.writeWith(Mono.just(buffer));
    }

    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE + 50;    // 鉴权应尽早执行
    }
}

关键设计要点:

  • 鉴权过滤器的order应小于日志过滤器,确保未鉴权的请求不会被记录为正常访问
  • 解析出的用户信息通过修改请求头的方式传递给下游,下游服务无需重复解析JWT
  • 未授权响应必须显式设置状态码和响应体,否则返回空响应

4.3 响应结果统一封装

在网关层对响应进行统一包装,可以保证所有接口的响应格式一致:

java 复制代码
@Component
@Slf4j
public class ResponseWrapperGlobalFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpResponse originalResponse = exchange.getResponse();

        // 使用装饰器模式包装响应,拦截响应体写入
        ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
            @Override
            public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
                // 仅对200响应且Content-Type为json的响应进行包装
                if (body instanceof Flux && getStatusCode() == HttpStatus.OK) {
                    Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
                    return super.writeWith(fluxBody.buffer().map(dataBuffers -> {
                        // 合并所有DataBuffer
                        DataBufferFactory bufferFactory = originalResponse.bufferFactory();
                        byte[] content = new byte[dataBuffers.stream()
                                .mapToInt(DataBuffer::readableByteCount).sum()];
                        int offset = 0;
                        for (DataBuffer buffer : dataBuffers) {
                            int len = buffer.readableByteCount();
                            buffer.read(content, offset, len);
                            offset += len;
                            DataBufferUtils.release(buffer);
                        }
                        // 包装为统一格式
                        String originalBody = new String(content, StandardCharsets.UTF_8);
                        // 此处根据业务需求决定是否包装
                        return bufferFactory.wrap(content);
                    }));
                }
                return super.writeWith(body);
            }
        };

        return chain.filter(exchange.mutate().response(decoratedResponse).build());
    }

    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE - 100;    // 尽量靠后
    }
}

踩坑提示 :不建议在网关层做响应体包装 。网关层包装响应需要读取并修改响应流,增加了内存开销和延迟,且容易与下游服务的统一响应格式冲突。推荐的做法是:下游服务各自使用统一的Result格式 ,网关层只做透传。如果需要添加响应头(如链路追踪ID),使用AddResponseHeader即可,无需修改响应体。

4.4 全局异常拦截

网关层的异常分为两类:请求匹配前的异常 (如路由未找到)和下游调用异常(如连接超时)。

java 复制代码
@Component
@Slf4j
@Order(Ordered.HIGHEST_PRECEDENCE)
public class GlobalExceptionHandler implements ErrorWebExceptionHandler {

    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        ServerHttpResponse response = exchange.getResponse();

        if (response.isCommitted()) {
            return Mono.error(ex);
        }

        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        Result<Void> result;
        HttpStatus status;

        if (ex instanceof ResponseStatusException) {
            ResponseStatusException rse = (ResponseStatusException) ex;
            status = HttpStatus.valueOf(rse.getStatusCode().value());
            if (status == HttpStatus.NOT_FOUND) {
                result = Result.fail(404, "请求路径不存在: " + exchange.getRequest().getPath());
            } else {
                result = Result.fail(status.value(), rse.getReason());
            }
        } else if (ex instanceof ConnectException) {
            status = HttpStatus.SERVICE_UNAVAILABLE;
            result = Result.fail(503, "下游服务不可用");
        } else if (ex instanceof TimeoutException) {
            status = HttpStatus.GATEWAY_TIMEOUT;
            result = Result.fail(504, "下游服务响应超时");
        } else {
            status = HttpStatus.INTERNAL_SERVER_ERROR;
            result = Result.fail(500, "网关内部错误");
            log.error("网关未知异常", ex);
        }

        response.setStatusCode(status);
        byte[] bytes = JSON.toJSONBytes(result);
        DataBuffer buffer = response.bufferFactory().wrap(bytes);
        return response.writeWith(Mono.just(buffer));
    }
}

关键规范:

  • 必须检查response.isCommitted(),避免在响应已提交后再次写入
  • 不同异常类型返回不同状态码:404(路由未找到)、503(下游不可用)、504(下游超时)
  • 必须记录log.error日志,便于问题排查

4.5 请求耗时统计过滤器

java 复制代码
@Component
@Slf4j
public class CostTimeGlobalFilter implements GlobalFilter, Ordered {

    private static final String START_TIME = "startTime";

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        exchange.getAttributes().put(START_TIME, System.currentTimeMillis());

        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            Long startTime = exchange.getAttribute(START_TIME);
            if (startTime != null) {
                long cost = System.currentTimeMillis() - startTime;
                String path = exchange.getRequest().getPath().value();

                // 添加响应头,方便前端排查
                exchange.getResponse().getHeaders().add("X-Response-Time", cost + "ms");

                // 慢请求告警
                if (cost > 1000) {
                    log.warn("[慢请求] {} 耗时 {}ms", path, cost);
                }
            }
        }));
    }

    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }
}

五、跨域统一配置

5.1 CORS跨域问题的本质

浏览器出于安全考虑,默认禁止跨域请求。当页面域名(如http://localhost:3000)与API域名(如http://localhost:8080)不一致时,浏览器会先发送一个OPTIONS预检请求,服务器必须返回正确的CORS响应头,浏览器才会发送真实请求。

在微服务架构中,如果每个后端服务都配置CORS,会导致重复配置且容易遗漏。在网关层统一配置CORS是最佳实践。

5.2 YAML方式配置CORS

yaml 复制代码
spring:
  cloud:
    gateway:
      server:
        webflux:
          globalcors:
            cors-configurations:
              '[/**]':                                    # 所有路径
                allowed-origin-patterns: "*"              # 允许的来源(生产环境应指定具体域名)
                allowed-methods: "*"                      # 允许的方法
                allowed-headers: "*"                      # 允许的请求头
                allow-credentials: true                   # 允许携带凭证
                max-age: 3600                             # 预检请求缓存时间(秒)
                exposed-headers:                          # 暴露给前端的响应头
                  - X-Response-Time
                  - X-Trace-Id

5.3 Java配置方式

java 复制代码
@Configuration
public class CorsConfig {

    @Bean
    public CorsWebFilter corsWebFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowedOriginPatterns(List.of("*"));
        config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS"));
        config.setAllowedHeaders(List.of("*"));
        config.setAllowCredentials(true);
        config.setMaxAge(3600L);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        return new CorsWebFilter(source);
    }
}

5.4 生产环境CORS安全规范

配置项 开发环境 生产环境
allowed-origin-patterns * 指定具体域名(如https://app.example.com)
allowed-methods * 明确列出允许的方法
allow-credentials true 仅在需要时开启
max-age 3600 3600

安全警示 :allow-credentials: true与allowed-origin-patterns: "*"同时使用时,Spring会拒绝配置(因为浏览器不允许Access-Control-Allow-Origin: *与Access-Control-Allow-Credentials: true同时存在)。生产环境应指定具体的Origin。

5.5 跨域配置的常见坑

现象 :跨域配置后,仍然报CORS policy错误。

原因排查:

  1. 后端服务也配置了CORS,导致响应头重复。浏览器检测到重复的Access-Control-Allow-Origin头会拒绝。
  2. 预检请求OPTIONS被鉴权过滤器拦截(返回401),浏览器认为预检失败。

解决方案:

  • 网关配置CORS后,后端服务移除CORS配置
  • 鉴权过滤器必须放行OPTIONS请求:
java 复制代码
if (request.getMethod() == HttpMethod.OPTIONS) {
    return chain.filter(exchange);
}

六、过滤器开发最佳实践

6.1 过滤器顺序设计原则

设计原则 说明 推荐order
日志最先 记录请求进入时间,确保完整耗时统计 HIGHEST_PRECEDENCE
跨域次之 CORS预检请求需要最先处理,避免被鉴权拦截 HIGHEST_PRECEDENCE + 1
鉴权靠前 尽早拒绝非法请求,减少无效调用 HIGHEST_PRECEDENCE + 50
业务处理居中 参数校验、Header注入 0 ~ 100
响应处理靠后 添加响应头、耗时统计 LOWEST_PRECEDENCE - 100

6.2 过滤器中的线程安全问题

Gateway的过滤器会被并发调用,必须确保线程安全:

java 复制代码
// ❌ 错误:使用实例变量存储请求状态
private long startTime;    // 多个请求并发时会被覆盖

// ✅ 正确:使用 exchange.getAttributes() 存储请求级状态
exchange.getAttributes().put("startTime", System.currentTimeMillis());

ServerWebExchange的attributes是请求级别的,每个请求有独立的Map,是存储请求状态的标准方式。

6.3 过滤器中的异常处理

不要吞掉异常 。过滤器中的异常应该向上抛出,由ErrorWebExceptionHandler统一处理:

java 复制代码
// ❌ 错误:吞掉异常,返回空响应
try {
    // ...
} catch (Exception e) {
    log.error("异常", e);
    return Mono.empty();
}

// ✅ 正确:抛出异常,由全局异常处理器处理
// 或显式写入错误响应

七、踩坑指南

坑一:OPTIONS预检请求被鉴权拦截

现象 :跨域请求报CORS policy错误,但服务端日志显示OPTIONS请求返回401。

原因 :鉴权过滤器未放行OPTIONS请求。

解决 :在鉴权过滤器中,如果请求方法是OPTIONS,直接放行:if (HttpMethod.OPTIONS.equals(request.getMethod())) return chain.filter(exchange);

坑二:响应头添加失败

现象:在Post阶段添加响应头时,响应头未生效。

原因 :响应已提交(response.isCommitted()返回true),无法再添加响应头。

解决 :在Pre阶段添加响应头(此时响应未提交),或在NettyWriteResponseFilter之前添加。

坑三:全局过滤器未生效

现象 :实现了GlobalFilter但日志中没有输出。

原因:类未被Spring扫描到,或未注册为Bean。

解决 :确保类上有@Component注解,且位于@ComponentScan扫描路径下。

坑四:过滤器顺序与预期不符

现象:鉴权过滤器在日志过滤器之后执行,导致未鉴权请求也被记录了日志。

原因 :getOrder()返回值配置错误,或未实现Ordered接口。

解决 :显式实现Ordered接口,鉴权过滤器的order应小于日志过滤器。

坑五:修改请求体后下游接收为空

现象:在过滤器中读取了请求体,下游服务接收到的请求体为空。

原因:请求体是流式数据,被读取一次后无法再次读取。

解决 :使用ServerWebExchangeUtils.cacheRequestBody()缓存请求体,或使用AdaptCachedBodyGlobalFilter(Gateway内置,order为HIGHEST_PRECEDENCE + 1000,自动缓存请求体)。

八、课后作业

作业一 :实现一个AccessLogGlobalFilter,记录每个请求的路径、方法、客户端IP、响应状态码和耗时。验证日志输出完整。

作业二 :实现一个AuthGlobalFilter,对/api/**路径进行JWT鉴权,白名单包含/api/auth/**。未携带Token的请求返回401,鉴权通过后将X-User-Id注入请求头传递给下游服务。特别注意放行OPTIONS预检请求。

作业三 :配置网关的CORS跨域,允许http://localhost:3000的请求访问所有/api/**路径。使用浏览器或curl -H "Origin: http://localhost:3000"验证CORS响应头。

作业四(进阶) :实现一个GlobalExceptionHandler,处理路由未找到(404)、下游连接失败(503)、下游超时(504)三类异常,返回统一的Result格式。

九、下节预告

第20课将进入Gateway动态网关、集群高可用 & 生产安全方案。内容包括Nacos动态路由配置(无需重启更新路由)、网关集群部署、负载均衡、防刷限流基础、接口安全校验和网关生产最佳实践。本课完成了网关过滤器的深度实战,第20课将解决网关自身的生产可用性和安全性问题------如何动态更新路由而不重启、如何部署网关集群避免单点、如何防止恶意刷接口。

🔗《最新版 SpringCloud 2025 从入门到实战》系列课程导航

去订阅

第一部分:微服务前置基础 & 新版环境搭建(第1-5课)

第二部分:注册中心核心(Nacos 最新版)(第6-9课)

第三部分:配置中心核心(Nacos配置中心)(第10-12课)

第四部分:服务通信核心(OpenFeign + LoadBalancer)(第13-16课)

第五部分:网关核心(SpringCloud Gateway 新版)(第17-20课)

第六部分:熔断、限流、降级(Sentinel 新版)(第21-24课)

第七部分:微服务监控、链路追踪、日志体系(第25-28课)

第八部分:微服务高阶特性 & 分布式核心能力(第29-31课)

第九部分:企业级完整项目实战 & 架构复盘(第32-35课)

相关推荐
Wang's Blog1 天前
Java框架 SpringCloud 快速入门: Nacos 配置热更新
java·spring·spring cloud
天空鸟_时光不老1 天前
06-给AI流程加一道人工闸门
java·人工智能·spring boot·后端·spring·spring cloud·架构
Wang's Blog1 天前
Java框架 SpringCloud 快速入门: Nacos 配置管理之添加配置与 dataId 命名规范
java·开发语言·spring cloud
天空鸟_时光不老1 天前
01-我不转Python把AI塞进Java里
java·人工智能·spring boot·后端·spring·spring cloud·架构
2501_933923251 天前
SpringCloud:通过订单服务认识什么是微服务
spring boot·后端·spring cloud
天空鸟_时光不老1 天前
07-检查点与状态持久化
java·人工智能·spring boot·spring·spring cloud·kafka·maven
天空鸟_时光不老1 天前
09-RAG问答系统落地:从默认分割器的坑到Milvus召回调优
java·人工智能·spring boot·spring·spring cloud·maven·mybatis
Thomas.Sir1 天前
第18课:Gateway路由规则、内置谓词、自定义谓词实战
spring cloud·gateway
Wang's Blog1 天前
Java框架 SpringCloud 快速入门: Ribbon 饥饿加载
java·spring cloud·ribbon