Spring Cloud Gateway
3.1.0

12. Http超时配置

可以为所有路由配置 Http 超时(响应和连接),并为每个特定路由覆盖。

12.1. 全局超时

要配置全局 http 超时:
spring cloud gateway 接口入住动态路由 spring.cloud.gateway.routes[0]_spring cloud 必须以毫秒为单位指定。
spring cloud gateway 接口入住动态路由 spring.cloud.gateway.routes[0]_java_02必须指定为 java.time.Duration

全局 http 超时示例

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

12.2. 每条路由超时

要配置每条路由超时:
spring cloud gateway 接口入住动态路由 spring.cloud.gateway.routes[0]_spring cloud必须以毫秒为单位指定。
spring cloud gateway 接口入住动态路由 spring.cloud.gateway.routes[0]_java_02必须以毫秒为单位指定。

通过配置进行每条路由 http 超时配置

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

使用 Java DSL 的每条路由超时配置

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();
      }

response-timeout具有负值的 per-route将禁用全局response-timeout值。

- id:per_route_timeouts
        网址:https://example.org
        谓词:
          - 名称:路径
            参数:
              模式:/延迟/{超时}
        元数据:
          响应超时:-1

12.3. 流畅的 Java 路由 API

为了允许在 Java 中进行简单配置,RouteLocatorBuilderbean 包含一个流式 API。下面的清单显示了它是如何工作的:

例 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();
}

这种风格还允许更多的自定义断言。bean定义的断言RouteDefinitionLocator使用逻辑组合and。通过使用 fluent Java API,您可以在类上使用and()、or()和negate()运算符Predicate。

12.4. 路线DiscoveryClient定义定位器

您可以将网关配置为基于在DiscoveryClient兼容服务注册表中注册的服务创建路由。

要启用此功能,请设置spring.cloud.gateway.discovery.locator.enabled=true并确保DiscoveryClient实现(例如 Netflix Eureka、Consul 或 Zookeeper)在类路径上并启用。

12.4.1. DiscoveryClient为路由配置谓词和过滤器

默认情况下,网关为使用DiscoveryClient.

默认谓词是使用模式定义的路径谓词/serviceId/**,其中serviceId是来自DiscoveryClient.

默认过滤器是带有正则表达式/serviceId/?(?.*)和替换的重写路径过滤器/${remaining}。这会在请求被发送到下游之前从路径中去除服务 ID。

如果要自定义DiscoveryClient路由使用的谓词或过滤器,请设置spring.cloud.gateway.discovery.locator.predicates[x]和spring.cloud.gateway.discovery.locator.filters[y]。这样做时,如果要保留该功能,则需要确保包含前面显示的默认谓词和过滤器。以下示例显示了它的外观:

示例 69.application.properties

spring.cloud.gateway.discovery.locator.predicates[0].name:路径
spring.cloud.gateway.discovery.locator.predicates[0].args[pattern]: "'/'+serviceId+'/**'"
spring.cloud.gateway.discovery.locator.predicates[1].name:主机
spring.cloud.gateway.discovery.locator.predicates[1].args[pattern]: "'**.foo.com'"
spring.cloud.gateway.discovery.locator.filters[0].name:断路器
spring.cloud.gateway.discovery.locator.filters[0].args[name]: serviceId
spring.cloud.gateway.discovery.locator.filters[1].name:重写路径
spring.cloud.gateway.discovery.locator.filters[1].args[regexp]: "'/' + serviceId + '/?(?<remaining>.*)'"
spring.cloud.gateway.discovery.locator.filters[1].args[replacement]: "'/${remaining}'"

13. Reactor Netty 访问日志

要启用 Reactor Netty 访问日志,请设置-Dreactor.netty.http.server.accessLogEnabled=true.

它必须是 Java 系统属性,而不是 Spring Boot 属性。
您可以将日志记录系统配置为具有单独的访问日志文件。以下示例创建一个 Logback 配置:

例 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 行为。“全局” CORS 配置是 URL 模式到Spring FrameworkCorsConfiguration的映射。以下示例配置 CORS:

例 71.application.yml

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

在前面的示例中,允许来自docs.spring.io所有 GET 请求路径的请求的 CORS 请求。

要为某些网关路由谓词未处理的请求提供相同的 CORS 配置,请将spring.cloud.gateway.globalcors.add-to-simple-url-handler-mapping属性设置为true. 当您尝试支持 CORS 预检请求并且您的路由谓词未评估为时,这很有用,true因为 HTTP 方法是options.

15.执行器 API

执行/gateway器端点允许您监视 Spring Cloud Gateway 应用程序并与之交互。要远程访问,必须在应用程序属性中启用并通过 HTTP 或 JMX 公开端点。以下清单显示了如何执行此操作:

示例 72.application.properties

management.endpoint.gateway.enabled=true # default value
management.endpoints.web.exposure.include=gateway

15.1. 详细执行器格式

Spring Cloud Gateway 中添加了一种新的、更详细的格式。它为每个路由添加了更多详细信息,让您可以查看与每个路由关联的谓词和过滤器以及任何可用配置。以下示例配置/actuator/gateway/routes:

[
  {
    "predicate": "(Hosts: [**.addrequestheader.org] && Paths: [/headers], match trailing slash: true)",
    "route_id": "add_request_header_test",
    "filters": [
      "[[AddResponseHeader X-Response-Default-Foo = 'Default-Bar'], order = 1]",
      "[[AddRequestHeader X-Request-Foo = 'Bar'], order = 1]",
      "[[PrefixPath prefix = '/httpbin'], order = 2]"
    ],
    "uri": "lb://testservice",
    "order": 0
  }
]

默认情况下启用此功能。要禁用它,请设置以下属性:

示例 73.application.properties

spring.cloud.gateway.actuator.verbose.enabled=false

这将true在未来的版本中默认使用。

15.2. 检索路由过滤器

本节详细介绍如何检索路由过滤器,包括:

  • 全局过滤器
  • [网关路由过滤器]

15.2.1. 全局过滤器

要检索应用于所有路由的全局过滤器GET,请向/actuator/gateway/globalfilters. 生成的响应类似于以下内容:

{
  “org.spring framework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter@77856cc5 ”:10100,
  “o rg.springframework.cloud.gateway.filter.RouteToRequestUrlFilter@4f6fd101 ”:10000,
  “或g.springframework.cloud.gateway.filter.NettyWriteResponseFilter@32d22650 ”:-1,
  " org.springframework.cloud.gateway.filter.ForwardRoutingFilter@10 6459d9": 2147483647,
  “ org.springframework.cloud.gateway.filter.NettyRoutingFilter@1fbd 5e0”:2147483647,
  " org.springframework.cloud.gateway.filter.ForwardPathFilter@33a71 d23": 0,
  “org.s pringframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter@135064ea ”:2147483637,
  “ org.springframework.cloud.gateway.filter.WebsocketRoutingFilter@23c05889 ”:2147483646
}

响应包含已到位的全局过滤器的详细信息。对于每个全局过滤器,都有过滤器对象的字符串表示形式(例如,org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter@77856cc5)和过滤器链中的相应顺序。}

15.2.2. 路由过滤器

要检索应用于路由的GatewayFilter工厂GET,请向/actuator/gateway/routefilters. 生成的响应类似于以下内容:

{
  “[ AddRequestHeaderGatewayFilterFactory@570ed9c configClass = AbstractNameValueGatewayFilterFactory.NameValueConfig]”:空,
  “[ SecureHeadersGatewayFilterFactory@fceab5d configClass = Object]”:空,
  “[ SaveSessionGatewayFilterFactory@4449b273 configClass = Object]”:空
}

响应包含GatewayFilter应用于任何特定路由的工厂的详细信息。对于每个工厂,都有对应对象的字符串表示形式(例如,[SecureHeadersGatewayFilterFactory@fceab5d configClass = Object])。请注意,该null值是由于端点控制器的实现不完整,因为它试图设置对象在过滤器链中的顺序,这不适用于GatewayFilter工厂对象。

15.3. 刷新路由缓存

要清除路由缓存,POST请向/actuator/gateway/refresh. 该请求返回没有响应正文的 200。

15.4. 检索网关中定义的路由

要检索网关中定义的路由,GET请向/actuator/gateway/routes. 生成的响应类似于以下内容:

[{
  "route_id": "first_route",
  “路由对象”:{“谓词
    ”:“org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory$$Lambda$432/1736826640@1e9d7e7d ”,
    “过滤器”:[
      “OrderedGatewayFilter{delegate=org.springframework.cloud.gateway.filter.factory.PreserveHostHeaderGatewayFilterFactory$$Lambda$436/674480275@6631ef72 , order =0}”
    ]
  },
  “订单”:0
},
{
  "route_id": "second_route",
  “路由对象”:{“谓词
    ”:“org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory$$Lambda$432/1736826640@cd8d298 ”,
    “过滤器”:[]
  },
  “订单”:0
}]

响应包含网关中定义的所有路由的详细信息。下表描述了响应的每个元素(每个元素都是一个路由)的结构:

路径

类型

描述

route_id

String

路径Id

route_object.predicate

Object

断言

route_object.filters

Array

路由过滤器

order

Number

序号

15.5。检索有关特定路线的信息
要检索有关单个路由的信息,GET请向/actuator/gateway/routes/{id}(例如,/actuator/gateway/routes/first_route)发出请求。生成的响应类似于以下内容:

{
  "id": "first_route",
  “谓词”:[{
    “名称”:“路径”,
    "args": {"_genkey_0":"/first"}
  }],
  “过滤器”:[],
  "uri": "https://www.uri-destination.org",
  “订单”:0
}

下表描述了响应的结构:

路径

类型

描述

id

String

路径Id

predicates

Array

断言数组

filters

Array

路由过滤器

uri

String

uri

order

Number

序号

15.6.创建和删除特定路线

要创建路由,请使用指定路由字段的 JSON 正文POST发出请求(请参阅检索有关特定路由的信息)。/gateway/routes/{id_route_to_create}

要删除路线,DELETE请向/gateway/routes/{id_route_to_delete}.

15.7. 回顾:所有端点的列表

下表总结了 Spring Cloud Gateway 执行器端点(请注意,每个端点都有/actuator/gateway作为基本路径):

id

方法

描述

globalfilters

GET

显示应用于路由的全局过滤器列表。

routefilters

GET

GatewayFilter列表

refresh

POST

清除路由缓存。

routes

GET

显示网关中定义的路由列表。

routes/{id}

GET

显示有关特定路线的信息。

routes/{id}

GET

向网关添加新路由。

routes/{id}

DELETE

从网关中删除现有路由。

15.8. 在多个网关实例之间共享路由

Spring Cloud Gateway 提供了两种RouteDefinitionRepository实现。第一个是 InMemoryRouteDefinitionRepository只存在于一个网关实例的内存中。这种类型的存储库不适合跨多个网关实例填充路由。

为了在 Spring Cloud Gateway 实例的集群中共享路由,RedisRouteDefinitionRepository可以使用。要启用这种存储库,必须将以下属性设置为 true:spring.cloud.gateway.redis-route-definition-repository.enabled 与 RedisRateLimiter Filter Factory 类似,它需要使用 spring-boot-starter-data-redis-reactive Spring Boot 启动器。

16. 故障排除

本节介绍使用 Spring Cloud Gateway 时可能出现的常见问题。

16.1. 日志级别

以下记录器可能在DEBUG和TRACE级别包含有价值的故障排除信息:

  • org.springframework.cloud.gateway
  • org.springframework.http.server.reactive
  • org.springframework.web.reactive
  • org.springframework.boot.autoconfigure.web
  • reactor.netty
  • redisratelimiter

16.2. 窃听

Reactor NettyHttpClient可以HttpServer启用窃听。与将reactor.netty日志级别设置为DEBUG或结合使用时TRACE,它可以记录信息,例如通过网络发送和接收的标头和正文。要启用窃听,请分别为和设置spring.cloud.gateway.httpserver.wiretap=true或。spring.cloud.gateway.httpclient.wiretap=trueHttpServerHttpClient

17. 开发者指南

这些是编写网关的一些自定义组件的基本指南。

17.1. 编写自定义路由谓词工厂

为了编写路由谓词,您需要将其实现RoutePredicateFactory为 bean。有一个AbstractRoutePredicateFactory可以扩展的抽象类。

MyRoutePredicateFactory.java

@Component
public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<MyRoutePredicateFactory.Config> {

    public MyRoutePredicateFactory() {
        super(Config.class);
    }

    @Override
    public Predicate<ServerWebExchange> apply(Config config) {
        // grab configuration from Config object
        return exchange -> {
            //grab the request
            ServerHttpRequest request = exchange.getRequest();
            //take information from the request to see if it
            //matches configuration.
            return matches(config, request);
        };
    }

    public static class Config {
        //Put the configuration properties for your filter here
    }

}

17.2. 编写自定义 GatewayFilter 工厂

要编写GatewayFilter,您必须将其实现GatewayFilterFactory为 bean。您可以扩展一个名为AbstractGatewayFilterFactory. 以下示例显示了如何执行此操作:

示例 74. PreGatewayFilterFactory.java

@Component
public class PreGatewayFilterFactory extends AbstractGatewayFilterFactory<PreGatewayFilterFactory.Config> {

    public PreGatewayFilterFactory() {
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {
        // grab configuration from Config object
        return (exchange, chain) -> {
            //If you want to build a "pre" filter you need to manipulate the
            //request before calling chain.filter
            ServerHttpRequest.Builder builder = exchange.getRequest().mutate();
            //use builder to manipulate the request
            return chain.filter(exchange.mutate().request(builder.build()).build());
        };
    }

    public static class Config {
        //Put the configuration properties for your filter here
    }

}

PostGatewayFilterFactory.java

@Component
public class PostGatewayFilterFactory extends AbstractGatewayFilterFactory<PostGatewayFilterFactory.Config> {

    public PostGatewayFilterFactory() {
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {
        // grab configuration from Config object
        return (exchange, chain) -> {
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                ServerHttpResponse response = exchange.getResponse();
                //Manipulate the response in some way
            }));
        };
    }

    public static class Config {
        //Put the configuration properties for your filter here
    }

}

17.2.1. 在配置中命名自定义过滤器和引用

自定义过滤器类名应以GatewayFilterFactory.

例如,要引用Something配置文件中命名的过滤器,该过滤器必须位于名为SomethingGatewayFilterFactory.

可以创建一个不带 GatewayFilterFactory后缀的网关过滤器,例如class AnotherThing. 此过滤器可以AnotherThing在配置文件中引用。这不是受支持的命名约定,并且在将来的版本中可能会删除此语法。请更新过滤器名称以使其符合要求。

17.3. 编写自定义全局过滤器

要编写自定义全局过滤器,您必须GlobalFilter将接口实现为 bean。这会将过滤器应用于所有请求。

以下示例分别显示了如何设置全局前置和后置过滤器:

@Bean
public GlobalFilter customGlobalFilter() {
    return (exchange, chain) -> exchange.getPrincipal()
        .map(Principal::getName)
        .defaultIfEmpty("Default User")
        .map(userName -> {
          //adds header to proxied request
          exchange.getRequest().mutate().header("CUSTOM-REQUEST-HEADER", userName).build();
          return exchange;
        })
        .flatMap(chain::filter);
}

@Bean
public GlobalFilter customGlobalPostFilter() {
    return (exchange, chain) -> chain.filter(exchange)
        .then(Mono.just(exchange))
        .map(serverWebExchange -> {
          //adds header to response
          serverWebExchange.getResponse().getHeaders().set("CUSTOM-RESPONSE-HEADER",
              HttpStatus.OK.equals(serverWebExchange.getResponse().getStatusCode()) ? "It worked": "It did not work");
          return serverWebExchange;
        })
        .then();
}

18. 使用 Spring MVC 或 Webflux 构建简单网关

下面描述了另一种风格的网关。先前的文档均不适用于以下内容。
Spring Cloud Gateway 提供了一个名为ProxyExchange. 您可以在常规 Spring Web 处理程序中将其用作方法参数。它通过镜像 HTTP 动词的方法支持基本的下游 HTTP 交换。使用 MVC,它还支持通过forward()方法转发到本地处理程序。要使用ProxyExchange,请在类路径中包含正确的模块(spring-cloud-gateway-mvc或spring-cloud-gateway-webflux)。

以下 MVC 示例将请求代理到/test下游到远程服务器:

@RestController
@SpringBootApplication
public class GatewaySampleApplication {

    @Value("${remote.home}")
    private URI home;

    @GetMapping("/test")
    public ResponseEntity<?> proxy(ProxyExchange<byte[]> proxy) throws Exception {
        return proxy.uri(home.toString() + "/image/png").get();
    }

}

以下示例对 Webflux 执行相同的操作:

@RestController
@SpringBootApplication
public class GatewaySampleApplication {

    @Value("${remote.home}")
    private URI home;

    @GetMapping("/test")
    public Mono<ResponseEntity<?>> proxy(ProxyExchange<byte[]> proxy) throws Exception {
        return proxy.uri(home.toString() + "/image/png").get();
    }

}

上的便捷方法ProxyExchange使处理程序方法能够发现和增强传入请求的 URI 路径。例如,您可能希望提取路径的尾随元素以将它们传递到下游:

@GetMapping("/proxy/path/**")
public ResponseEntity<?> proxyPath(ProxyExchange<byte[]> proxy) throws Exception {
  String path = proxy.path("/proxy/path/");
  return proxy.uri(home.toString() + "/foos/" + path).get();
}

Spring MVC 和 Webflux 的所有特性都可用于网关处理程序方法。因此,您可以注入请求标头和查询参数,例如,您可以使用映射注释中的声明来约束传入请求。有关这些功能的更多详细信息,请参阅@RequestMappingSpring MVC 中的文档。

header()您可以使用on 上的方法将标头添加到下游响应中ProxyExchange。

get()您还可以通过向方法(和其他方法)添加映射器来操作响应标头(以及响应中您喜欢的任何其他内容)。映射器是一个Function接收传入ResponseEntity并将其转换为传出的映射器。

cookie为不向下游传递的“敏感”标头(默认情况下和authorization)和“代理”(x-forwarded-*)标头提供一流的支持。

19.配置属性

要查看所有 Spring Cloud Gateway 相关配置属性的列表,请参阅附录。