最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring?Cloud?Gateway?WebFlux?模式架構(gòu)場(chǎng)景分析

 更新時(shí)間:2025年12月05日 08:47:06   作者:wasp  
本文詳細(xì)介紹了Spring Cloud Gateway WebFlux模式的架構(gòu),包括入口類(lèi)、關(guān)鍵類(lèi)關(guān)系、核心組件和關(guān)鍵流程描述,Spring Cloud Gateway通過(guò)響應(yīng)式編程模型和非阻塞I/O,提供了高性能的API網(wǎng)關(guān)解決方案,感興趣的朋友跟隨小編一起看看吧

1. 入口類(lèi)及關(guān)鍵類(lèi)關(guān)系

1.1 入口類(lèi)

Spring Cloud Gateway WebFlux 模式的入口類(lèi)是 GatewayAutoConfiguration,這是整個(gè) WebFlux 模式的"總指揮"。它負(fù)責(zé)配置所有 Gateway 需要的組件。

@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(name = "spring.cloud.gateway.server.webflux.enabled", matchIfMissing = true)
@EnableConfigurationProperties
@AutoConfigureBefore({ HttpHandlerAutoConfiguration.class, WebFluxAutoConfiguration.class })
@AutoConfigureAfter({ GatewayReactiveLoadBalancerClientAutoConfiguration.class,
        GatewayClassPathWarningAutoConfiguration.class })
@ConditionalOnClass(DispatcherHandler.class)
public class GatewayAutoConfiguration {
    // 核心 Bean 定義
}

關(guān)鍵特性說(shuō)明

  • @AutoConfigureBefore({ HttpHandlerAutoConfiguration.class, WebFluxAutoConfiguration.class })
    • 這個(gè)很關(guān)鍵!Gateway 必須在 WebFlux 的默認(rèn)配置之前加載
    • 為什么?因?yàn)?Gateway 需要注冊(cè)自己的 HandlerMappingRoutePredicateHandlerMapping
    • 如果 WebFlux 的默認(rèn)配置先加載,可能會(huì)注冊(cè)其他的 HandlerMapping,導(dǎo)致路由沖突
    • Gateway 的 HandlerMapping 優(yōu)先級(jí)更高,會(huì)優(yōu)先處理請(qǐng)求
  • @ConditionalOnClass(DispatcherHandler.class)
    • 這個(gè)注解確保只有在 WebFlux 存在時(shí)才加載 Gateway
    • DispatcherHandler 是 WebFlux 的核心組件,類(lèi)似于 WebMVC 的 DispatcherServlet
    • 如果沒(méi)有 WebFlux,Gateway WebFlux 模式就無(wú)法工作
  • @ConditionalOnProperty
# 可以通過(guò)配置控制是否啟用
spring:
  cloud:
    gateway:
      server:
        webflux:
          enabled: true  # 默認(rèn)啟用,可以設(shè)置為 false 禁用

配置的核心組件

  • RouteLocator:路由定位器,負(fù)責(zé)提供路由列表
  • FilteringWebHandler:過(guò)濾器處理器,負(fù)責(zé)執(zhí)行過(guò)濾器鏈
  • RoutePredicateHandlerMapping:路由匹配器,負(fù)責(zé)匹配請(qǐng)求到路由
  • GatewayProperties:Gateway 配置屬性

1.2 關(guān)鍵類(lèi)關(guān)系圖

1.3 核心組件說(shuō)明

RoutePredicateHandlerMapping

這是 Gateway 的路由匹配器,負(fù)責(zé)找到匹配的路由。它繼承自 Spring WebFlux 的 AbstractHandlerMapping

工作原理

@Override
protected Mono<?> getHandlerInternal(ServerWebExchange exchange) {
    // 1. 查找匹配的路由(異步操作)
    return lookupRoute(exchange)
        .map(route -> {
            // 2. 把路由信息存儲(chǔ)到 Exchange 的屬性中
            exchange.getAttributes().put(GATEWAY_ROUTE_ATTR, route);
            // 3. 返回 FilteringWebHandler 作為處理器
            return webHandler;
        });
}

實(shí)際例子

// 假設(shè)有這些路由配置
routes = [
    { id: "user-service", path: "/api/users/**", uri: "http://user-service" },
    { id: "order-service", path: "/api/orders/**", uri: "http://order-service" }
]
// 請(qǐng)求:GET /api/users/123
// lookupRoute() 會(huì):
// 1. 遍歷所有路由
// 2. 使用 AsyncPredicate 異步匹配
// 3. 找到匹配的路由:user-service
// 4. 返回 FilteringWebHandler

關(guān)鍵點(diǎn)

  • lookupRoute() 返回 Mono<Route>,是異步的
  • 路由匹配使用 AsyncPredicate,支持異步條件判斷
  • 匹配成功后,路由信息存儲(chǔ)在 ServerWebExchange 的屬性中

FilteringWebHandler

這是 Gateway 的核心請(qǐng)求處理器,負(fù)責(zé)執(zhí)行過(guò)濾器鏈。它實(shí)現(xiàn)了 Spring WebFlux 的 WebHandler 接口。

工作原理

@Override
public Mono<Void> handle(ServerWebExchange exchange) {
    // 1. 從 Exchange 中獲取路由信息(路由匹配時(shí)設(shè)置的)
    Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);
    // 2. 獲取合并后的過(guò)濾器列表(全局過(guò)濾器 + 路由過(guò)濾器)
    List<GatewayFilter> combined = getCombinedFilters(route);
    // 3. 創(chuàng)建過(guò)濾器鏈并執(zhí)行
    return new DefaultGatewayFilterChain(combined).filter(exchange);
}

實(shí)際例子

// 假設(shè)路由配置了這些過(guò)濾器
route.filters = [
    AddRequestHeaderFilter,
    RateLimitFilter,
    NettyRoutingFilter  // 最后一個(gè),負(fù)責(zé)實(shí)際轉(zhuǎn)發(fā)請(qǐng)求
]
// FilteringWebHandler 會(huì):
// 1. 合并全局過(guò)濾器和路由過(guò)濾器
// 2. 按 Order 排序
// 3. 創(chuàng)建過(guò)濾器鏈
// 4. 依次執(zhí)行過(guò)濾器

過(guò)濾器鏈執(zhí)行

// 過(guò)濾器鏈的實(shí)現(xiàn)(責(zé)任鏈模式)
private static class DefaultGatewayFilterChain implements GatewayFilterChain {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange) {
        return Mono.defer(() -> {
            if (this.index < filters.size()) {
                GatewayFilter filter = filters.get(this.index);
                // 創(chuàng)建下一個(gè)鏈節(jié)點(diǎn)
                DefaultGatewayFilterChain chain = new DefaultGatewayFilterChain(this, this.index + 1);
                // 執(zhí)行當(dāng)前過(guò)濾器,傳入下一個(gè)鏈節(jié)點(diǎn)
                return filter.filter(exchange, chain);
            }
            return Mono.empty();  // 所有過(guò)濾器執(zhí)行完畢
        });
    }
}

RouteLocator

路由定位器,負(fù)責(zé)提供路由列表。Gateway 支持多個(gè) RouteLocator,可以組合使用。

工作原理

@Bean
@Primary
public RouteLocator cachedCompositeRouteLocator(List<RouteLocator> routeLocators) {
    // 1. 組合多個(gè) RouteLocator
    CompositeRouteLocator composite = new CompositeRouteLocator(
        Flux.fromIterable(routeLocators)
    );
    // 2. 添加緩存(提高性能)
    return new CachingRouteLocator(composite);
}

實(shí)際例子

// 可以有多個(gè) RouteLocator
RouteLocator[] locators = [
    PropertiesRouteDefinitionLocator,      // 從配置文件讀取路由
    DiscoveryClientRouteDefinitionLocator, // 從服務(wù)發(fā)現(xiàn)讀取路由
    InMemoryRouteDefinitionRepository      // 從內(nèi)存(API)讀取路由
]
// CompositeRouteLocator 會(huì)合并所有路由
// 返回 Flux<Route>,包含所有路由

路由來(lái)源

配置文件PropertiesRouteDefinitionLocator

spring:
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: http://localhost:8081

服務(wù)發(fā)現(xiàn)DiscoveryClientRouteDefinitionLocator

// 自動(dòng)從 Eureka/Consul 等服務(wù)注冊(cè)中心發(fā)現(xiàn)服務(wù)
// 為每個(gè)服務(wù)自動(dòng)創(chuàng)建路由

API 動(dòng)態(tài)配置InMemoryRouteDefinitionRepository

// 通過(guò) API 動(dòng)態(tài)添加/刪除路由
routeDefinitionRepository.save(routeDefinition);

2. 關(guān)鍵流程描述

2.1 請(qǐng)求處理流程時(shí)序圖

2.2 路由匹配流程

路由匹配是 Gateway 的核心功能。讓我們用一個(gè)實(shí)際例子來(lái)說(shuō)明整個(gè)流程:

場(chǎng)景:客戶端請(qǐng)求 GET /api/users/123

詳細(xì)流程

DispatcherHandler 接收 HTTP 請(qǐng)求

客戶端 → DispatcherHandler → Gateway

DispatcherHandler 是 WebFlux 的請(qǐng)求分發(fā)器,類(lèi)似于 WebMVC 的 DispatcherServlet

它會(huì)把請(qǐng)求交給合適的 HandlerMapping 處理

Gateway 的 RoutePredicateHandlerMapping 優(yōu)先級(jí)很高,會(huì)優(yōu)先處理

RoutePredicateHandlerMapping 從 RouteLocator 獲取所有路由

// 獲取所有路由(返回 Flux<Route>,是響應(yīng)式的)
Flux<Route> routes = routeLocator.getRoutes();
// 實(shí)際的路由列表可能是:
// [
//   { id: "user-service", path: "/api/users/**", uri: "http://user-service" },
//   { id: "order-service", path: "/api/orders/**", uri: "http://order-service" }
// ]

RouteLocator 可能從多個(gè)來(lái)源獲取路由(配置文件、服務(wù)發(fā)現(xiàn)、API)

返回的是 Flux<Route>,是響應(yīng)式的流

使用 AsyncPredicate 異步匹配路由

// 異步匹配路由
return routes
    .filterWhen(route -> {
        // 使用 AsyncPredicate 異步匹配
        return route.getPredicate().test(exchange);
    })
    .next();  // 返回第一個(gè)匹配的路由

匹配過(guò)程

// 路由1:user-service
AsyncPredicate predicate1 = exchange -> {
    String path = exchange.getRequest().getPath().value();
    return Mono.just(path.startsWith("/api/users/"));  // 異步返回 true/false
};
// 路徑 "/api/users/123" 匹配 "/api/users/**" ?
// 路由2:order-service
AsyncPredicate predicate2 = exchange -> {
    String path = exchange.getRequest().getPath().value();
    return Mono.just(path.startsWith("/api/orders/"));  // 異步返回 false
};
// 路徑 "/api/users/123" 不匹配 "/api/orders/**" ?
  • 使用 AsyncPredicate 異步匹配,支持異步條件判斷
  • 可以在這里做異步操作(比如查詢 Redis、數(shù)據(jù)庫(kù)等)
  • 返回 Mono<Boolean>,不會(huì)阻塞線程

找到匹配的路由后,將路由信息存儲(chǔ)到 ServerWebExchange 的屬性中

// 匹配成功后
Route matchedRoute = ...;  // user-service 路由
// 存儲(chǔ)路由信息到 Exchange 的屬性中
exchange.getAttributes().put(GATEWAY_ROUTE_ATTR, matchedRoute);
exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, matchedRoute.getUri());
  • 路由信息存儲(chǔ)在 ServerWebExchange 的屬性中
  • 后續(xù)的過(guò)濾器可以從這里獲取路由信息
  • 比如 NettyRoutingFilter 會(huì)從這里獲取目標(biāo) URI

返回 FilteringWebHandler 作為處理器

// 返回 FilteringWebHandler
return Mono.just(webHandler);
  • FilteringWebHandler 會(huì)負(fù)責(zé)執(zhí)行過(guò)濾器鏈
  • 最終會(huì)調(diào)用 NettyRoutingFilter 轉(zhuǎn)發(fā)請(qǐng)求到下游服務(wù)

完整示例

# 配置文件
spring:
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: http://user-service:8081
          predicates:
            - Path=/api/users/**
            - Method=GET

匹配過(guò)程

  • 請(qǐng)求 GET /api/users/123 到達(dá)
  • 路徑 /api/users/123 匹配 /api/users/** ?
  • 方法 GET 匹配 GET ?
  • 找到匹配的路由 user-service
  • 返回 FilteringWebHandler,目標(biāo) URI 是 http://user-service:8081

2.3 過(guò)濾器鏈執(zhí)行流程

過(guò)濾器鏈?zhǔn)?Gateway 的核心機(jī)制。讓我們用一個(gè)實(shí)際例子來(lái)說(shuō)明:

場(chǎng)景:請(qǐng)求已經(jīng)匹配到路由,現(xiàn)在需要執(zhí)行過(guò)濾器鏈

詳細(xì)流程

FilteringWebHandler 從路由中獲取過(guò)濾器列表

Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);
List<GatewayFilter> routeFilters = route.getFilters();
// 假設(shè)路由配置了這些過(guò)濾器:
// [AddRequestHeaderFilter, RateLimitFilter]
  • 從路由中獲取路由級(jí)別的過(guò)濾器
  • 這些過(guò)濾器只應(yīng)用于當(dāng)前路由

合并全局過(guò)濾器和路由過(guò)濾器,按 Order 排序

// 全局過(guò)濾器(應(yīng)用于所有路由)
List<GlobalFilter> globalFilters = [
    LoadBalancerClientFilter,      // Order: 10100
    NettyRoutingFilter,            // Order: Ordered.LOWEST_PRECEDENCE
    NettyWriteResponseFilter       // Order: Ordered.LOWEST_PRECEDENCE - 1
];
// 路由過(guò)濾器
List<GatewayFilter> routeFilters = [
    AddRequestHeaderFilter,         // Order: 1000
    RateLimitFilter                 // Order: -100
];
// 合并并排序
List<GatewayFilter> combined = [
    RateLimitFilter,                // -100 (最高優(yōu)先級(jí))
    AddRequestHeaderFilter,         // 1000
    LoadBalancerClientFilter,       // 10100
    NettyRoutingFilter,             // LOWEST_PRECEDENCE
    NettyWriteResponseFilter        // LOWEST_PRECEDENCE - 1
];
  • 全局過(guò)濾器 + 路由過(guò)濾器 = 合并后的過(guò)濾器列表
  • 按 Order 排序,數(shù)字越小優(yōu)先級(jí)越高
  • Ordered.LOWEST_PRECEDENCE 是最大整數(shù),優(yōu)先級(jí)最低

創(chuàng)建 DefaultGatewayFilterChain,實(shí)現(xiàn)責(zé)任鏈模式

// 創(chuàng)建過(guò)濾器鏈
DefaultGatewayFilterChain chain = new DefaultGatewayFilterChain(combined);
// 過(guò)濾器鏈的內(nèi)部實(shí)現(xiàn)
private static class DefaultGatewayFilterChain implements GatewayFilterChain {
    private final int index;  // 當(dāng)前執(zhí)行的過(guò)濾器索引
    private final List<GatewayFilter> filters;
    @Override
    public Mono<Void> filter(ServerWebExchange exchange) {
        return Mono.defer(() -> {
            if (this.index < filters.size()) {
                GatewayFilter filter = filters.get(this.index);
                // 創(chuàng)建下一個(gè)鏈節(jié)點(diǎn)
                DefaultGatewayFilterChain nextChain = 
                    new DefaultGatewayFilterChain(this, this.index + 1);
                // 執(zhí)行當(dāng)前過(guò)濾器,傳入下一個(gè)鏈節(jié)點(diǎn)
                return filter.filter(exchange, nextChain);
            }
            return Mono.empty();  // 所有過(guò)濾器執(zhí)行完畢
        });
    }
}
  • 使用責(zé)任鏈模式,每個(gè)過(guò)濾器都可以決定是否繼續(xù)執(zhí)行下一個(gè)過(guò)濾器
  • 通過(guò)遞歸創(chuàng)建鏈節(jié)點(diǎn)來(lái)實(shí)現(xiàn)

遞歸執(zhí)行過(guò)濾器

// 執(zhí)行流程(簡(jiǎn)化版)
RateLimitFilter.filter(exchange, chain1)
  -> 檢查限流
  -> chain1.filter(exchange)  // 調(diào)用下一個(gè)過(guò)濾器
    -> AddRequestHeaderFilter.filter(exchange, chain2)
      -> 添加請(qǐng)求頭
      -> chain2.filter(exchange)  // 調(diào)用下一個(gè)過(guò)濾器
        -> LoadBalancerClientFilter.filter(exchange, chain3)
          -> 負(fù)載均衡選擇實(shí)例
          -> chain3.filter(exchange)
            -> NettyRoutingFilter.filter(exchange, chain4)
              -> 轉(zhuǎn)發(fā)請(qǐng)求到下游服務(wù)
              -> chain4.filter(exchange)
                -> NettyWriteResponseFilter.filter(exchange, chain5)
                  -> 寫(xiě)入響應(yīng)
                  -> chain5.filter(exchange)
                    -> Mono.empty()  // 所有過(guò)濾器執(zhí)行完畢
  • 每個(gè)過(guò)濾器調(diào)用 chain.filter(exchange) 來(lái)執(zhí)行下一個(gè)過(guò)濾器
  • 如果某個(gè)過(guò)濾器不想繼續(xù)執(zhí)行,可以不調(diào)用 chain.filter()
  • 比如限流過(guò)濾器,如果限流了,就直接返回錯(cuò)誤,不繼續(xù)執(zhí)行

NettyRoutingFilter 作為最后一個(gè)過(guò)濾器,執(zhí)行實(shí)際的 HTTP 請(qǐng)求

// NettyRoutingFilter 的實(shí)現(xiàn)(簡(jiǎn)化版)
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    URI requestUrl = exchange.getRequiredAttribute(GATEWAY_REQUEST_URL_ATTR);
    // 使用 Reactor Netty HttpClient 發(fā)送請(qǐng)求(非阻塞)
    return httpClient.get()
        .uri(requestUrl)
        .send((req, nettyOutbound) -> nettyOutbound.send(request.getBody()))
        .responseConnection((res, connection) -> {
            // 設(shè)置響應(yīng)到 Exchange
            exchange.getAttributes().put(CLIENT_RESPONSE_ATTR, res);
            return Mono.just(res);
        })
        .then(chain.filter(exchange));  // 繼續(xù)執(zhí)行下一個(gè)過(guò)濾器
}
  • NettyRoutingFilter 使用 Reactor Netty 的 HttpClient 發(fā)送請(qǐng)求
  • 這是非阻塞的,線程不會(huì)在這里等待
  • 響應(yīng)到達(dá)后,會(huì)繼續(xù)執(zhí)行下一個(gè)過(guò)濾器(NettyWriteResponseFilter

響應(yīng)通過(guò) Mono 鏈?zhǔn)椒祷?/strong>

// 響應(yīng)返回流程
NettyWriteResponseFilter.filter(exchange, chain)
  -> 寫(xiě)入響應(yīng)到客戶端
  -> Mono.empty()  // 完成
  -> 返回給 NettyRoutingFilter
    -> 返回給 LoadBalancerClientFilter
      -> 返回給 AddRequestHeaderFilter
        -> 返回給 RateLimitFilter
          -> 返回給 FilteringWebHandler
            -> 返回給 RoutePredicateHandlerMapping
              -> 返回給 DispatcherHandler
                -> 返回給客戶端
  • 響應(yīng)通過(guò) Mono 鏈?zhǔn)椒祷?/li>
  • 每個(gè)過(guò)濾器都可以修改響應(yīng)
  • 最終返回給客戶端

關(guān)鍵點(diǎn)

  • 過(guò)濾器鏈?zhǔn)琼憫?yīng)式的,不會(huì)阻塞線程
  • 每個(gè)過(guò)濾器都可以修改請(qǐng)求或響應(yīng)
  • 過(guò)濾器可以決定是否繼續(xù)執(zhí)行下一個(gè)過(guò)濾器
  • NettyRoutingFilter 是最后一個(gè)過(guò)濾器,負(fù)責(zé)實(shí)際轉(zhuǎn)發(fā)請(qǐng)求

2.4 響應(yīng)式 HTTP 請(qǐng)求

Flux<HttpClientResponse> responseFlux = httpClient
    .headers(headers -> headers.add(httpHeaders))
    .request(method)
    .uri(url)
    .send((req, nettyOutbound) -> nettyOutbound.send(request.getBody()))
    .responseConnection((res, connection) -> {
        // 處理響應(yīng)
        return Mono.just(res);
    });

關(guān)鍵點(diǎn)

  • 使用 Reactor Netty 的非阻塞 HTTP 客戶端
  • 基于 Reactive Streams 的響應(yīng)式編程模型
  • 支持背壓(Backpressure)控制

3. 實(shí)現(xiàn)關(guān)鍵點(diǎn)說(shuō)明

3.1 響應(yīng)式編程模型

WebFlux 模式完全基于響應(yīng)式編程,使用 Project Reactor 的 Mono 和 Flux。這是 WebFlux 和 WebMVC 最根本的區(qū)別。

基本概念

public interface GlobalFilter {
    Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}

Mono 和 Flux 是什么?

Mono:表示 0 或 1 個(gè)元素的異步序列

Mono<String> name = Mono.just("Spring");  // 一個(gè)值
Mono<String> empty = Mono.empty();        // 0 個(gè)值
Mono<String> async = Mono.fromCallable(() -> {
    // 異步操作
    return fetchNameFromDatabase();
});

Flux:表示 0 到 N 個(gè)元素的異步序列

Flux<String> names = Flux.just("Spring", "Cloud", "Gateway");  // 多個(gè)值
Flux<String> stream = Flux.interval(Duration.ofSeconds(1))
    .map(i -> "Event " + i);  // 無(wú)限流

實(shí)際例子

// WebMVC 方式(阻塞)
public ServerResponse handle(ServerRequest request) {
    User user = userService.getUser(userId);  // 阻塞等待
    return ServerResponse.ok().body(user);
}
// WebFlux 方式(非阻塞)
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    return userService.getUser(userId)  // 返回 Mono<User>,不阻塞
        .flatMap(user -> {
            // 用戶數(shù)據(jù)到達(dá)后才執(zhí)行這里
            exchange.getAttributes().put("user", user);
            return chain.filter(exchange);
        });
}

優(yōu)勢(shì)說(shuō)明

非阻塞 I/O,提高并發(fā)性能

// 非阻塞調(diào)用下游服務(wù)
return httpClient.get()
    .uri("http://backend-service/api/data")
    .retrieve()
    .bodyToMono(String.class)  // 返回 Mono,不阻塞線程
    .flatMap(data -> {
        // 數(shù)據(jù)到達(dá)后才執(zhí)行這里
        return processData(data);
    });
// 在等待響應(yīng)的這段時(shí)間,線程可以處理其他請(qǐng)求
  • 線程不會(huì)阻塞,可以處理其他請(qǐng)求
  • 一個(gè)線程可以處理多個(gè)請(qǐng)求
  • 并發(fā)性能大幅提升

支持背壓,防止內(nèi)存溢出

// 背壓示例
Flux<String> dataStream = getDataStream();  // 數(shù)據(jù)流
dataStream
    .limitRate(100)  // 限制速率,防止內(nèi)存溢出
    .subscribe(data -> {
        // 處理數(shù)據(jù)
        processData(data);
    });
  • 如果生產(chǎn)者生產(chǎn)數(shù)據(jù)太快,消費(fèi)者可以告訴生產(chǎn)者慢一點(diǎn)
  • 防止內(nèi)存溢出
  • 這是 Reactive Streams 規(guī)范的核心特性

資源利用率高,少量線程處理大量請(qǐng)求

場(chǎng)景:處理 10000 并發(fā)請(qǐng)求
WebMVC: 需要 500 線程,內(nèi)存 ~500MB
WebFlux: 只需要 16 線程,內(nèi)存 ~100MB
資源利用率提升 5 倍!

3.2 過(guò)濾器鏈模式

Gateway 使用責(zé)任鏈模式實(shí)現(xiàn)過(guò)濾器鏈。這是 Gateway 的核心設(shè)計(jì)模式之一。

責(zé)任鏈模式

private static class DefaultGatewayFilterChain implements GatewayFilterChain {
    private final int index;  // 當(dāng)前過(guò)濾器索引
    private final List<GatewayFilter> filters;
    @Override
    public Mono<Void> filter(ServerWebExchange exchange) {
        return Mono.defer(() -> {
            if (this.index < filters.size()) {
                GatewayFilter filter = filters.get(this.index);
                // 創(chuàng)建下一個(gè)鏈節(jié)點(diǎn)
                DefaultGatewayFilterChain chain = 
                    new DefaultGatewayFilterChain(this, this.index + 1);
                // 執(zhí)行當(dāng)前過(guò)濾器,傳入下一個(gè)鏈節(jié)點(diǎn)
                return filter.filter(exchange, chain);
            }
            return Mono.empty();  // 所有過(guò)濾器執(zhí)行完畢
        });
    }
}

實(shí)際例子

// 假設(shè)有這些過(guò)濾器
List<GatewayFilter> filters = [
    RateLimitFilter,        // index 0
    AddRequestHeaderFilter,  // index 1
    NettyRoutingFilter      // index 2
];
// 執(zhí)行流程
chain0.filter(exchange)  // index = 0
  -> RateLimitFilter.filter(exchange, chain1)  // index = 1
    -> 檢查限流
    -> chain1.filter(exchange)
      -> AddRequestHeaderFilter.filter(exchange, chain2)  // index = 2
        -> 添加請(qǐng)求頭
        -> chain2.filter(exchange)
          -> NettyRoutingFilter.filter(exchange, chain3)  // index = 3
            -> 轉(zhuǎn)發(fā)請(qǐng)求
            -> chain3.filter(exchange)
              -> index (3) >= filters.size(),返回 Mono.empty()

過(guò)濾器類(lèi)型

GlobalFilter - 全局過(guò)濾器

@Component
public class CustomGlobalFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 這個(gè)過(guò)濾器會(huì)應(yīng)用于所有路由
        return chain.filter(exchange);
    }
    @Override
    public int getOrder() {
        return -1;  // 高優(yōu)先級(jí)
    }
}
  • 應(yīng)用于所有路由
  • 比如認(rèn)證、日志、監(jiān)控等

GatewayFilter - 路由過(guò)濾器

// 通過(guò)配置定義的路由過(guò)濾器
spring:
  cloud:
    gateway:
      routes:
        - id: user-service
          filters:
            - AddRequestHeader=X-User-Id, 123  # 路由過(guò)濾器
  • 只應(yīng)用于特定路由
  • 通過(guò)配置文件或 API 定義

Ordered - 控制執(zhí)行順序

// 通過(guò) Order 接口控制執(zhí)行順序
public class RateLimitFilter implements GlobalFilter, Ordered {
    @Override
    public int getOrder() {
        return -100;  // 數(shù)字越小,優(yōu)先級(jí)越高
    }
}
public class LoggingFilter implements GlobalFilter, Ordered {
    @Override
    public int getOrder() {
        return 1000;  // 優(yōu)先級(jí)較低
    }
}
// 執(zhí)行順序:RateLimitFilter (-100) -> LoggingFilter (1000)

過(guò)濾器可以做什么?

修改請(qǐng)求

@Override
public Mono&lt;Void&gt; filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    ServerHttpRequest request = exchange.getRequest();
    ServerHttpRequest modifiedRequest = request.mutate()
        .header("X-Request-Id", UUID.randomUUID().toString())
        .build();
    return chain.filter(exchange.mutate().request(modifiedRequest).build());
}

修改響應(yīng)

@Override
public Mono&lt;Void&gt; filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    return chain.filter(exchange).then(Mono.fromRunnable(() -&gt; {
        ServerHttpResponse response = exchange.getResponse();
        response.getHeaders().add("X-Response-Time", 
            String.valueOf(System.currentTimeMillis()));
    }));
}

中斷執(zhí)行

@Override
public Mono&lt;Void&gt; filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    if (isRateLimited(exchange)) {
        // 限流了,直接返回錯(cuò)誤,不繼續(xù)執(zhí)行
        exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
        return exchange.getResponse().setComplete();
    }
    return chain.filter(exchange);  // 繼續(xù)執(zhí)行
}

3.3 異步謂詞(AsyncPredicate)

路由匹配使用異步謂詞,支持異步條件判斷:

public interface AsyncPredicate&lt;T&gt; {
    Mono&lt;Boolean&gt; test(T t);
}

支持的謂詞

  • Path Route Predicate
  • Method Route Predicate
  • Header Route Predicate
  • Host Route Predicate
  • Query Route Predicate
  • RemoteAddr Route Predicate
  • Weight Route Predicate

3.4 Netty 集成

使用 Reactor Netty 作為底層 HTTP 客戶端,提供高性能的非阻塞 I/O:

public class NettyRoutingFilter implements GlobalFilter {
    private final HttpClient httpClient;
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 使用 Reactor Netty HttpClient 發(fā)送請(qǐng)求
        Flux<HttpClientResponse> responseFlux = httpClient
            .request(method)
            .uri(url)
            .send(...)
            .responseConnection(...);
    }
}

特性

  • 基于 Netty 的事件驅(qū)動(dòng)模型
  • 支持 HTTP/1.1 和 HTTP/2
  • 支持 WebSocket
  • 連接池管理

3.5 路由緩存

支持路由過(guò)濾器緩存,提高性能:

private final ConcurrentHashMap<Route, List<GatewayFilter>> routeFilterMap = new ConcurrentHashMap();
protected List<GatewayFilter> getCombinedFilters(Route route) {
    if (this.routeFilterCacheEnabled) {
        return routeFilterMap.computeIfAbsent(route, this::getAllFilters);
    }
    return getAllFilters(route);
}

4. 總結(jié)說(shuō)明

4.1 架構(gòu)特點(diǎn)

  • 響應(yīng)式編程: 完全基于 Project Reactor 的響應(yīng)式編程模型
  • 非阻塞 I/O: 使用 Reactor Netty 實(shí)現(xiàn)非阻塞 HTTP 通信
  • 高并發(fā)性能: 少量線程處理大量并發(fā)請(qǐng)求
  • 背壓支持: 支持 Reactive Streams 的背壓機(jī)制

4.2 適用場(chǎng)景

  • 高并發(fā)、高吞吐量的 API 網(wǎng)關(guān)場(chǎng)景
  • 需要處理大量長(zhǎng)連接(如 WebSocket)
  • 微服務(wù)架構(gòu)中的統(tǒng)一入口
  • 需要流式處理(Streaming)的場(chǎng)景

4.3 關(guān)鍵優(yōu)勢(shì)

  • 高性能: 非阻塞 I/O 提供更高的吞吐量
  • 資源高效: 少量線程處理大量請(qǐng)求,資源利用率高
  • 可擴(kuò)展性: 響應(yīng)式模型支持更好的水平擴(kuò)展
  • 功能豐富: 支持 HTTP/2、WebSocket、gRPC 等協(xié)議

4.4 局限性

  • 學(xué)習(xí)曲線: 需要理解響應(yīng)式編程模型
  • 調(diào)試?yán)щy: 異步調(diào)用棧較難調(diào)試
  • 阻塞風(fēng)險(xiǎn): 如果在響應(yīng)式鏈中執(zhí)行阻塞操作,會(huì)降低性能
  • 內(nèi)存管理: 需要理解背壓機(jī)制,避免內(nèi)存問(wèn)題

4.5 最佳實(shí)踐

  • 避免阻塞操作: 不要在響應(yīng)式鏈中執(zhí)行阻塞 I/O
  • 合理使用背壓: 理解背壓機(jī)制,合理配置緩沖區(qū)
  • 監(jiān)控和指標(biāo): 使用 Spring Boot Actuator 監(jiān)控 Gateway 性能
  • 過(guò)濾器順序: 合理設(shè)置過(guò)濾器順序,避免不必要的處理

到此這篇關(guān)于Spring Cloud Gateway WebFlux 模式架構(gòu)分析的文章就介紹到這了,更多相關(guān)Spring Cloud Gateway WebFlux 模式架構(gòu)分析內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Ribbon單獨(dú)使用,配置自動(dòng)重試,實(shí)現(xiàn)負(fù)載均衡和高可用方式

    Ribbon單獨(dú)使用,配置自動(dòng)重試,實(shí)現(xiàn)負(fù)載均衡和高可用方式

    這篇文章主要介紹了Ribbon單獨(dú)使用,配置自動(dòng)重試,實(shí)現(xiàn)負(fù)載均衡和高可用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • Java實(shí)現(xiàn)將PDF轉(zhuǎn)換為Word的示例詳解

    Java實(shí)現(xiàn)將PDF轉(zhuǎn)換為Word的示例詳解

    在日常的數(shù)據(jù)處理、文檔編輯和系統(tǒng)集成工作中,將不可編輯的PDF文檔轉(zhuǎn)換為可編輯的Word文檔是一項(xiàng)常見(jiàn)且重要的需求,下面我們就來(lái)看看如何使用java實(shí)現(xiàn)這一操作吧
    2025-08-08
  • Java中的clone方法詳解_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Java中的clone方法詳解_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    clone顧名思義就是復(fù)制, 在Java語(yǔ)言中, clone方法被對(duì)象調(diào)用,所以會(huì)復(fù)制對(duì)象。下面通過(guò)本文給大家介紹java中的clone方法,感興趣的朋友一起看看吧
    2017-06-06
  • Java?map和bean互轉(zhuǎn)常用的方法總結(jié)

    Java?map和bean互轉(zhuǎn)常用的方法總結(jié)

    這篇文章主要給大家介紹了關(guān)于Java中map和bean互轉(zhuǎn)常用方法的相關(guān)資料,平時(shí)日常Java開(kāi)發(fā),經(jīng)常會(huì)涉及到Java?Bean和Map之間的類(lèi)型轉(zhuǎn)換,需要的朋友可以參考下
    2023-09-09
  • Java?如何用二維數(shù)組創(chuàng)建空心菱形

    Java?如何用二維數(shù)組創(chuàng)建空心菱形

    這篇文章主要介紹了Java?如何用二維數(shù)組創(chuàng)建空心菱形,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • 實(shí)例詳解SpringBoot默認(rèn)的JSON解析方案

    實(shí)例詳解SpringBoot默認(rèn)的JSON解析方案

    JSON數(shù)據(jù)現(xiàn)在是我們開(kāi)發(fā)中用的最多的,百分之九十的數(shù)據(jù)都是通過(guò)JSON方式進(jìn)行傳輸,下面這篇文章主要給大家介紹了關(guān)于SpringBoot默認(rèn)的JSON解析方案的相關(guān)資料,需要的朋友可以參考下
    2021-08-08
  • 使用Mybatis-plus更新null字段的問(wèn)題分析及解決過(guò)程

    使用Mybatis-plus更新null字段的問(wèn)題分析及解決過(guò)程

    文章主要講述了在使用MybatisPlus對(duì)Oracle數(shù)據(jù)庫(kù)的某個(gè)字段進(jìn)行set為Null操作時(shí)遇到的問(wèn)題及解決方案,嘗試了全局配置和在字段上加注解等方法均未解決問(wèn)題,最終通過(guò)在el表達(dá)式中指定javaType解決了問(wèn)題
    2026-05-05
  • Spring詳細(xì)講解7種事務(wù)傳播方式

    Spring詳細(xì)講解7種事務(wù)傳播方式

    Spring事務(wù)傳播機(jī)制是指,包含多個(gè)事務(wù)的方法在相互調(diào)用時(shí),事務(wù)是如何在這些方法間傳播的。本文通過(guò)示例詳細(xì)介紹了Spring的事務(wù)傳播機(jī)制,需要的可以參考一下
    2023-01-01
  • java獲取昨天日期字符串的方法

    java獲取昨天日期字符串的方法

    這篇文章主要介紹了java獲取昨天日期字符串的方法,涉及java針對(duì)日期與時(shí)間的運(yùn)算與轉(zhuǎn)換等相關(guān)操作技巧,需要的朋友可以參考下
    2016-08-08
  • 深入學(xué)習(xí)JavaWeb中監(jiān)聽(tīng)器(Listener)的使用方法

    深入學(xué)習(xí)JavaWeb中監(jiān)聽(tīng)器(Listener)的使用方法

    這篇文章主要為大家詳細(xì)介紹了深入學(xué)習(xí)JavaWeb中監(jiān)聽(tīng)器(Listener)的使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-09-09

最新評(píng)論

鲁甸县| 湟中县| 响水县| 朝阳县| 华容县| 五华县| 浦东新区| 中宁县| 三江| 平度市| 泸定县| 湘潭县| 林周县| 夹江县| 延长县| 连州市| 天水市| 中阳县| 汪清县| 金湖县| 武威市| 临湘市| 交城县| 若尔盖县| 库车县| 长沙县| 湘阴县| 晋州市| 高邑县| 奉节县| 郑州市| 连山| 兖州市| 名山县| 门头沟区| 化隆| 德钦县| 松桃| 宝兴县| 鹤岗市| 定结县|