Spring Cloud Gateway使用说明(6)-- 其它配置

本文深入探讨SpringCloud Gateway的高级配置,包括路由定义、HTTP超时、服务发现路由及跨域配置等关键主题,旨在帮助开发者掌握其核心功能。

10 配置

Spring Cloud Gateway的配置由RouteDefinitionLocator的集合驱动。

Example 65. RouteDefinitionLocator.java

public interface RouteDefinitionLocator {
    Flux<RouteDefinition> getRouteDefinitions();
}

默认情况下,PropertiesRouteDefinitionLocator使用Spring Boot的@ConfigurationProperties机制加载属性。

以下两个示例是等效的:

spring:
  cloud:
    gateway:
      routes:
      - id: setstatus_route
        uri: https://example.org
        filters:
        - name: SetStatus
          args:
            status: 401
      - id: setstatusshortcut_route
        uri: https://example.org
        filters:
        - SetStatus=401

对于网关的大部分用法,配置文件方式是够用的,但一些生产用例更建议从外部源(如数据库)加载配置。未来的里程碑版本将有基于Spring Data Repositories (如Redis、MongoDB和Cassandra)的RouteDefinitionLocator实现。

11. 路由metadata

通过metadata你可以为每个路由配置附加的数据:

Example 67. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: route_with_metadata
        uri: https://example.org
        metadata:
          optionName: "OptionValue"
          compositeObject:
            name: "value"
          iAmNumber: 1

可以从exchange中获取到所有的metadata属性:

Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
// get all metadata properties
route.getMetadata();
// get a single metadata property
route.getMetadata(someKey);

12. http超时配置

可以配置全局的http超时(连接和响应)时间,也可为每个路由单独覆盖配置。

12.1. 全局超时

配置全局http超时时间:
connect-timeout: 连接超时(毫秒)
response-timeout:响应超时,为java.time.Duration

global http timeouts example

spring:
  cloud:
    gateway:
      httpclient:
        connect-timeout: 1000
        response-timeout: 5s

12.2. 路由单独超时

为每个路由单独配置超时:
connect-timeout:单位为毫秒
response-timeout:单位为毫秒

通过配置文件配置

      - id: per_route_timeouts
        uri: https://example.org
        predicates:
          - name: Path
            args:
              pattern: /delay/{timeout}
        metadata:
          response-timeout: 200
          connect-timeout: 200

通过java配置

import static org.springframework.cloud.gateway.support.RouteMetadataUtils.CONNECT_TIMEOUT_ATTR;
import static org.springframework.cloud.gateway.support.RouteMetadataUtils.RESPONSE_TIMEOUT_ATTR;

      @Bean
      public RouteLocator customRouteLocator(RouteLocatorBuilder routeBuilder){
         return routeBuilder.routes()
               .route("test1", r -> {
                  return r.host("*.somehost.org").and().path("/somepath")
                        .filters(f -> f.addRequestHeader("header1", "header-value-1"))
                        .uri("http://someuri")
                        .metadata(RESPONSE_TIMEOUT_ATTR, 200)
                        .metadata(CONNECT_TIMEOUT_ATTR, 200);
               })
               .build();
      }

12.3. java路由配置API

为了可以更简单在Java中配置,在RouteLocatorBuilder bean中定义了一个fluent API。

Example 68. GatewaySampleApplication.java

// static imports from GatewayFilters and RoutePredicates
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder, ThrottleGatewayFilterFactory throttle) {
    return builder.routes()
            .route(r -> r.host("**.abc.org").and().path("/image/png")
                .filters(f ->
                        f.addResponseHeader("X-TestHeader", "foobar"))
                .uri("http://httpbin.org:80")
            )
            .route(r -> r.path("/image/webp")
                .filters(f ->
                        f.addResponseHeader("X-AnotherHeader", "baz"))
                .uri("http://httpbin.org:80")
                .metadata("key", "value")
            )
            .route(r -> r.order(-1)
                .host("**.throttle.org").and().path("/get")
                .filters(f -> f.filter(throttle.apply(1,
                        1,
                        10,
                        TimeUnit.SECONDS)))
                .uri("http://httpbin.org:80")
                .metadata("key", "value")
            )
            .build();
}

12.4. 服务发现路由定义

可以将网关配置为基于使用DiscoveryClient注册中心注册的服务发现路由。

要启用此功能,请设置spring.cloud.gateway.discovery.locator.enabled=true,并确保DiscoveryClient实现位于classpath上并已启用(如netflix eureka、consul或zookeeper)。

12.4.1. 为注册中心路由配置断言和过滤器

默认情况下,网关为通过DiscoveryClient创建的路由定义单个断言和过滤器。
默认断言是使用/serviceId/**定义的path断言,其中serviceId是DiscoveryClient中服务的ID。
默认过滤器是使用正则表达式 /serviceId/(?.*)和替换的/${remaining}进行重写。这只是在请求被发送到下游之前从路径中截取掉 service id 。

可以通过设置spring.cloud.gateway.discovery.locator.predicates[x] and spring.cloud.gateway.discovery.locator.filters[y]来实现自定义DiscoveryClient路由使用的断言和过滤器。当你这样做时,如果你想要保留默认功能,你需要确保包括上面的默认断言和过滤器。下面是这样一个例子。

Example 69. application.properties

spring.cloud.gateway.discovery.locator.predicates[0].name: Path
spring.cloud.gateway.discovery.locator.predicates[0].args[pattern]: "'/'+serviceId+'/**'"
spring.cloud.gateway.discovery.locator.predicates[1].name: Host
spring.cloud.gateway.discovery.locator.predicates[1].args[pattern]: "'**.foo.com'"
spring.cloud.gateway.discovery.locator.filters[0].name: Hystrix
spring.cloud.gateway.discovery.locator.filters[0].args[name]: serviceId
spring.cloud.gateway.discovery.locator.filters[1].name: RewritePath
spring.cloud.gateway.discovery.locator.filters[1].args[regexp]: "'/' + serviceId + '/(?<remaining>.*)'"
spring.cloud.gateway.discovery.locator.filters[1].args[replacement]: "'/${remaining}'"

13. netty访问日志

设置 -Dreactor.netty.http.server.accessLogEnabled=true 来开启Reactor Netty access logs

注意
必须是Java System Property而不是Spring Boot property。

logging 模块也可以通过配置单独输出一个access log文件,下面是logback的配置例子:
Example 70. logback.xml

    <appender name="accessLog" class="ch.qos.logback.core.FileAppender">
        <file>access_log.log</file>
        <encoder>
            <pattern>%msg%n</pattern>
        </encoder>
    </appender>
    <appender name="async" class="ch.qos.logback.classic.AsyncAppender">
        <appender-ref ref="accessLog" />
    </appender>

    <logger name="reactor.netty.http.server.AccessLog" level="INFO" additivity="false">
        <appender-ref ref="async"/>
    </logger>

14 跨域配置

我们可以通过配置网关来控制CORS行为,全局CORS配置是 Spring Framework CorsConfiguration模式的URL MAP。

Example 71. application.yml

spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            allowedOrigins: "https://docs.spring.io"
            allowedHeaders: "*"
            allowedMethods:
            - GET

Spring Cloud Gateway 2.2.3 官方使用说明(1)–路由
Spring Cloud Gateway 2.2.3 官方使用说明(2)-- 路由filter(上)
Spring Cloud Gateway 2.2.3 官方使用说明(2)-- 路由filter(下)
Spring Cloud Gateway 2.2.3 官方使用说明(3)-- Global filter
Spring Cloud Gateway 2.2.3 官方使用说明(4)-- HttpHeader Filters
Spring Cloud Gateway 2.2.3 使用说明(5)-- TLS 和 SSL

Spring Cloud Gateway 2.2.3 使用说明(6)-- 其它配置

Spring Cloud Gateway 2.2.3 使用说明(7)-- actuator
Spring Cloud Gateway 2.2.3 使用说明(8)-- 开发指导

Spring Cloud Gateway 中集成 `spring-boot-starter-cache` 实现缓存功能,可以通过与 Spring Cache 的整合来实现。Spring Cache 提供了统一的缓存抽象层,支持多种缓存实现,如 Caffeine、EhCache、Redis 等。在网关使用缓存可以减少对后端服务的重复请求,提升响应速度,特别是在处理频繁查询且数据变化不频繁的场景中效果显著。 ### 集成步骤 #### 1. 添加依赖 首先,在 `pom.xml` 文件中添加 Spring Boot Cache Starter 和具体的缓存实现依赖,例如 Redis: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` 如果使用 Redis 作为缓存实现,还需要添加对应的客户端依赖,如 Lettuce 或 Jedis。 #### 2. 配置缓存管理器 在 `application.yml` 或 Java 配置类中配置缓存管理器。例如,使用 Redis 缓存时,可以通过以下方式配置: ```yaml spring: cache: type: redis redis: time-to-live: 3600000 # 设置缓存过期时间,单位为毫秒 ``` 或者使用 Java 配置类: ```java @Configuration @EnableCaching public class CacheConfig { @Bean public CacheManager cacheManager(RedisConnectionFactory factory) { RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofHours(1)); // 设置缓存过期时间为1小时 return RedisCacheManager.builder(factory) .cacheDefaults(config) .build(); } } ``` #### 3. 在网关使用缓存 Spring Cloud Gateway 是基于 WebFlux 构建的,因此在使用缓存时需要注意响应式编程模型。可以通过自定义 `GatewayFilter` 来实现对请求结果的缓存。 以下是一个简单的示例,展示如何在过滤器中缓存响应结果: ```java @Component public class CacheGatewayFilterFactory extends AbstractGatewayFilterFactory<CacheGatewayFilterFactory.Config> { private final CacheManager cacheManager; public CacheGatewayFilterFactory(CacheManager cacheManager) { super(Config.class); this.cacheManager = cacheManager; } @Override public GatewayFilter apply(Config config) { return (exchange, chain) -> { String cacheKey = exchange.getRequest().getPath().value(); Cache cache = cacheManager.getCache("gateway_cache"); if (cache != null && cache.get(cacheKey) != null) { // 如果缓存中存在,直接返回缓存内容 Object cachedResponse = cache.get(cacheKey).get(); if (cachedResponse instanceof String) { exchange.getResponse().getHeaders().setContentType(MediaType.APPLICATION_JSON); DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(((String) cachedResponse).getBytes()); return exchange.getResponse().writeWith(Mono.just(buffer)); } } // 如果缓存中没有,继续执行链路并缓存结果 return chain.filter(exchange).then(Mono.fromRunnable(() -> { if (exchange.getResponse().getStatusCode().is2xxSuccessful()) { exchange.getResponse().readWithLengthLimit(1024 * 1024).asInputStream() .map(is -> { try { String responseBody = new String(is.readAllBytes(), StandardCharsets.UTF_8); cache.put(cacheKey, responseBody); return responseBody; } catch (IOException e) { return null; } }).subscribe(); } })); }; } public static class Config { // 配置参数 } } ``` #### 4. 在路由中使用缓存过滤器 在路由配置中引用自定义的缓存过滤器: ```java @Bean public RouteLocator routes(RouteLocatorBuilder builder) { return builder.routes() .route("cached_service", r -> r.path("/api/**") .filters(f -> f.filter(new CacheGatewayFilterFactory(cacheManager))) .uri("http://backend-service")) .build(); } ``` ### 注意事项 - **缓存键设计**:应根据业务需求设计合适的缓存键,例如可以使用请求路径、查询参数等组合生成唯一的缓存键。 - **缓存过期策略**:合理设置缓存过期时间,避免缓存数据过期不及时导致的数据不一致问题。 - **响应内容类型**:确保缓存的响应内容类型正确,避免因类型不匹配导致解析失败。 - **性能影响**:缓存操作本身也会带来一定的性能开销,需评估其对整体性能的影响[^3]。 通过上述步骤,Spring Cloud Gateway 可以有效地集成 `spring-boot-starter-cache`,并在网关层面对请求结果进行缓存,提升系统性能和用户体验。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiegwei

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值