SpringCloud Gateway使用及原理分析大全(下篇)

文章目录

  • 五、GlobalFilter-全局过滤器
    • 1、组合全局过滤器和网关过滤器排序
    • 2、转发路由过滤器
    • 3、ReactiveLoadBalancerClientFilter
    • 4、Netty路由过滤器
    • 5、NettyWriteResponseFilter
    • 6、RouteToRequestUrl 过滤器
    • 7、Websocket Routing 过滤器
    • 8、Gateway Metrics Filter
    • 9、将Exchange 标记为 Routed(已路由)
  • 六、HttpHeadersFilters
    • 1、Forwarded Headers Filter
    • 2、RemoveHopByHop Headers Filter
    • 3、XForwarded Headers Filter
  • 七、TLS 和SSL
    • TLS 握手
  • 八、配置-Configuration
    • RouteDefinition Metrics
  • 九、Route Metadata Configuration-路由元数据配置
  • 十、Http超时配置
    • 1、全局超时设置
    • 2、配置每个路由的超时
    • 3、Java路由API
    • 4、DiscoveryClient客户端路径定义定位器
      • 为DiscoveryClient 路由配置断言和过滤器
  • 十一、Reactor Netty访问日志
  • 十二、CORS配置
  • 十三、 Actuator API
    • 1、Verbose Actuator 格式化
    • 2、查找路由过滤器
      • Global Filters
      • Route Filters
    • 3、刷新路由缓存
    • 4、检索网关中定义的路由
    • 5、检索特定路由的信息
    • 6、创建和删除特定的路由
    • 7、总结:所有端点的列表
    • 8、在多个网关实例之间共享路由
  • 十四、故障排查
    • 1、日志级别
    • 2、窃听
  • 十五、开发指南
    • 1、编写自定义路由断言工厂
    • 2、编写自定义网关过滤器工厂
      • 在配置中命名自定义过滤器和引用
    • 3、编写自定义全局过滤器
  • 十六、使用Spring MVC或Webflux构建一个简单的网关
  • 十七、配置属性
  • 参考资料

SpringCloud Gateway使用及原理分析大全——断言及过滤器(上篇)

SpringCloud Gateway使用及原理分析大全(下篇)

五、GlobalFilter-全局过滤器

GlobalFilter接口与GatewayFilter具有相同的签名。这些是有条件地应用于所有路由的特殊过滤器。

在未来的里程碑版本中,该接口及其用法可能会有所变化。

1、组合全局过滤器和网关过滤器排序

当请求与路由匹配时,筛选web处理程序会将GlobalFilter的所有实例和GatewayFilter的所有路由特定实例添加到筛选器链中。这个组合的过滤器链由org.springframework.core.Ordered接口排序,您可以通过实现getOrder()方法来设置该接口。

由于Spring Cloud Gateway区分过滤器逻辑执行的“前”和“后”阶段,优先级最高的过滤器是“前”阶段的第一个,是“后”阶段的最后一个。

// 配置一个过滤器链
@Bean
public GlobalFilter customFilter() {
    return new CustomGlobalFilter();
}

public class CustomGlobalFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("custom global filter");
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return -1;
    }
}

2、转发路由过滤器

ForwardRoutingFilter在exchange属性ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR中查找URI。

如果URL有转发方案(比如forward:///localendpoint),它使用Spring DispatcherHandler来处理请求。

请求URL的路径部分被转发URL中的路径覆盖。

未修改的原始URL被附加到ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR中的列表。

3、ReactiveLoadBalancerClientFilter

ReactiveLoadBalancerClientFilter在名为ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR属性中查找URI。

如果URL有lb方案(比如lb://myservice),它使用Spring Cloud ReactorLoadBalancer将名称(本例中为myservice)解析为实际的主机和端口,并替换相同属性中的URI。

未修改的原始URL被附加到ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR中的列表.

该筛选器还会在ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR中查找属性,看是否等于lb。如果是这样,同样的规则也适用。

spring:
  cloud:
    gateway:
      routes:
      - id: myRoute
        uri: lb://service
        predicates:
        - Path=/service/**

默认情况下,当ReactorLoadBalancer找不到服务实例时,将返回503。通过设置spring.cloud.gateway.loadbalancer.use404=true,可以将网关配置为返回404。

从ReactiveLoadBalancerClientFilter返回的ServiceInstance的isSecure值将覆盖向网关发出的请求中指定的方案。例如,如果请求通过HTTPS进入网关,但ServiceInstance指示它不安全,则下游请求通过HTTP发出。相反的情况也适用。但是,如果在网关配置中为路由指定了GATEWAY_SCHEME_PREFIX_ATTR,则前缀将被删除,并且从路由URL生成的方案将覆盖ServiceInstance配置。

4、Netty路由过滤器

如果位于ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR的 exchange属性中的URL具有http或https方案,则Netty路由过滤器将运行。它使用Netty HttpClient发出下游代理请求。响应放在ServerWebExchangeUtils中。CLIENT_RESPONSE_ATTR交换属性,以便在以后的过滤器中使用。(还有一个实验性的WebClientHttpRoutingFilter,它执行相同的功能,但不需要Netty。)

5、NettyWriteResponseFilter

如果ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR中有Netty HttpClientResponse,则NettyWriteResponseFilter将运行。它在所有其他过滤器完成后运行,并将代理响应写回网关客户端响应。(还有一个实验性的WebClientWriteResponseFilter,它执行相同的功能,但不需要Netty)

6、RouteToRequestUrl 过滤器

如果ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR中有路由对象,则运行RouteToRequestUrlFilter。它基于请求URI创建了一个新的URI,但是用路由对象的URI属性进行了更新。新的URI放在ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR中。

7、Websocket Routing 过滤器

如果位于ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR exchange属性中的URL具有ws或wss方案,websocket路由过滤器将运行。它使用Spring WebSocket基础设施向下游转发WebSocket请求。

可以通过在URI前面加上lb来对websockets进行负载平衡,比如lb:ws://serviceid。

如果使用SockJS作为普通HTTP的后备,那么应该配置一个普通HTTP路由以及websocket路由。

# 配置一个websocket 路由过滤器
spring:
  cloud:
    gateway:
      routes:
      # SockJS route
      - id: websocket_sockjs_route
        uri: http://localhost:3001
        predicates:
        - Path=/websocket/info/**
      # Normal Websocket route
      - id: websocket_route
        uri: ws://localhost:3001
        predicates:
        - Path=/websocket/**

8、Gateway Metrics Filter

要启用网关指标,请添加spring-boot-starter-actuator作为项目依赖项。然后,默认情况下,只要属性spring.cloud.gateway.metrics.enabled未设置为false,网关度量过滤器就会运行。该过滤器添加一个名为spring.cloud.gateway.requests的计时器指标,带有以下标记:

  • routeId:路由ID
  • routeUri:API被路由到的URI。
  • outcome:由HttpStatus.Series分类的结果
  • status:返回给客户端的请求的HTTP状态。
  • httpStatusCode:返回给客户端的请求的HTTP状态。
  • httpMethod:用于请求的HTTP方法。

此外,通过属性spring.cloud.gateway.metrics.tags.path.enabled(默认情况下,设置为false),您可以使用标记激活额外的指标:

  • path:请求的路径。

这些指标可以从/actuator/metrics/spring.cloud.gateway.requests中获取,并可以轻松地与Prometheus集成以创建Grafana仪表板。

要启用prometheus端点,请添加micrometer-registry-prometheus作为项目依赖项。

9、将Exchange 标记为 Routed(已路由)

在网关路由了ServerWebExchange之后,它通过将gatewayAlreadyRouted添加到Exchange属性来将该exchange标记为“routed”。一旦请求被标记为已路由,其他路由过滤器将不会再次路由该请求,实质上跳过了该过滤器。有一些方便的方法可以用来将交换标记为已路由,或者检查交换是否已经被路由。

  • ServerWebExchangeUtils.isAlreadyRouted接受一个ServerWebExchange对象并检查它是否已被“路由”。
  • ServerWebExchangeUtils.setAlreadyRouted接受一个ServerWebExchange对象,并将其标记为“已路由”。

六、HttpHeadersFilters

HttpHeadersFilters在将请求发送到下游之前应用于请求,例如在NettyRoutingFilter中。

1、Forwarded Headers Filter

转发头过滤器创建一个转发头发送到下游服务。它将当前请求的主机请求头、方案和端口添加到任何现有的转发请求头中。

2、RemoveHopByHop Headers Filter

RemoveHopByHop头筛选器从转发的请求中删除头。被删除的默认头列表来自IETF。

默认删除的请求头有:

  • Connection
  • Keep-Alive
  • Proxy-Authenticate
  • Proxy-Authorization
  • TE
  • Trailer
  • Transfer-Encoding
  • Upgrade

要更改这一点,请将spring.cloud.gateway.filter.remove-hop-by-hop.headers属性设置为要删除的请求头名称列表。

3、XForwarded Headers Filter

XForwarded Headers筛选器创建各种X-Forwarded-*标头以发送到下游服务。它使用当前请求的主机头、方案、端口和路径来创建各种头。

单个标题的创建可由以下布尔属性控制(默认为true):

  • spring.cloud.gateway.x-forwarded.for-enabled
  • spring.cloud.gateway.x-forwarded.host-enabled
  • spring.cloud.gateway.x-forwarded.port-enabled
  • spring.cloud.gateway.x-forwarded.proto-enabled
  • spring.cloud.gateway.x-forwarded.prefix-enabled

追加多个标题可以由以下布尔属性控制(默认为true):

  • spring.cloud.gateway.x-forwarded.for-append
  • spring.cloud.gateway.x-forwarded.host-append
  • spring.cloud.gateway.x-forwarded.port-append
  • spring.cloud.gateway.x-forwarded.proto-append
  • spring.cloud.gateway.x-forwarded.prefix-append

七、TLS 和SSL

网关可以通过遵循通常的Spring服务器配置来监听HTTPS上的请求。

server:
  ssl:
    enabled: true
    key-alias: scg
    key-store-password: scg1234
    key-store: classpath:scg-keystore.p12
    key-store-type: PKCS12

可以将网关路由路由到HTTP和HTTPS后端。如果要路由到HTTPS后端,可以使用以下配置将网关配置为信任所有下游证书:

spring:
  cloud:
    gateway:
      httpclient:
        ssl:
          useInsecureTrustManager: true

使用不安全的信任管理器不适合生产。对于生产部署,可以使用一组它可以信任的已知证书来配置网关,配置如下:

spring:
  cloud:
    gateway:
      httpclient:
        ssl:
          trustedX509Certificates:
          - cert1.pem
          - cert2.pem

如果Spring Cloud Gateway没有提供可信证书,则使用默认的信任存储(可以通过设置javax.net.ssl.trustStore系统属性来覆盖它)。

TLS 握手

网关维护一个客户端池,用于路由到后端。当通过HTTPS通信时,客户端发起TLS握手。许多超时与该握手相关联。可以按如下方式配置这些超时值(显示默认值):

spring:
  cloud:
    gateway:
      httpclient:
        ssl:
          handshake-timeout-millis: 10000
          close-notify-flush-timeout-millis: 3000
          close-notify-read-timeout-millis: 0

八、配置-Configuration

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

// RouteDefinitionLocator接口的定义
public interface RouteDefinitionLocator {
    Flux<RouteDefinition> getRouteDefinitions();
}

默认情况下,propertiesroutededefinitionlocator使用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

对于网关的某些用途,属性是足够的,但是某些生产用例从外部源(如数据库)加载配置中受益。未来的milestone版本将会有基于Spring数据仓库的RouteDefinitionLocator实现,比如Redis、MongoDB和Cassandra。

RouteDefinition Metrics

要启用RouteDefinition指标,请添加spring-boot-starter-actuator作为项目依赖项。然后,默认情况下,只要属性spring.cloud.gateway.metrics.enabled设置为true,指标就可用。将添加一个名为spring.cloud.gateway.routes.count的测量指标,其值为RouteDefinitions的数量。该指标可从/actuator/metrics/spring.cloud.gateway.routes.count获得。

九、Route Metadata Configuration-路由元数据配置

# 可以使用元数据为每个路径配置附加参数
spring:
  cloud:
    gateway:
      routes:
      - id: route_with_metadata
        uri: https://example.org
        metadata:
          optionName: "OptionValue"
          compositeObject:
            name: "value"
          iAmNumber: 1
// 可以从exchange中获取所有元数据属性
Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
// get all metadata properties
route.getMetadata();
// get a single metadata property
route.getMetadata(someKey);

十、Http超时配置

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

1、全局超时设置

要配置全局http超时:

  • connect-timeout:必须以毫秒为单位指定。
  • response-timeout:必须指定为java.time.Duration。
# 配置全局超时
spring:
  cloud:
    gateway:
      httpclient:
        connect-timeout: 1000
        response-timeout: 5s

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();
      }
# 注意:当单个路由设置response-timeout为负值时,将会禁用全局的response-timeout。
      - id: per_route_timeouts
        uri: https://example.org
        predicates:
          - name: Path
            args:
              pattern: /delay/{timeout}
        metadata:
          response-timeout: -1

3、Java路由API

为了在Java中实现简单的配置,RouteLocatorBuilder bean包含了一个流畅的API。

// 静态引入 GatewayFilters 和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();
}

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

4、DiscoveryClient客户端路径定义定位器

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

要实现这一点,请设置spring.cloud.gateway.discovery.locator.enabled=true,并确保DiscoveryClient实现(如Netflix Eureka, Consul, or Zookeeper)位于类路径中并已启用。

为DiscoveryClient 路由配置断言和过滤器

默认情况下,网关为使用DiscoveryClient创建的路由定义了一个断言和过滤器。
默认断言是用模式/serviceId/**定义的路径断言,其中serviceId是来自DiscoveryClient的服务的Id。

默认过滤器是一个重写路径过滤器,其正则为 /serviceId/?(?.*)和替换/${remaining}。这将在请求发送到下游之前从路径中去除服务ID。

如果想定制DiscoveryClient路由使用的断言或过滤器, 设置 spring.cloud.gateway.discovery.locator.predicates[x] 和spring.cloud.gateway.discovery.locator.filters[y],这样做的时候,如果想保留这个功能,需要确保包含前面显示的默认断言和过滤器,比如:

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: CircuitBreaker
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 + '/?(?.*)'"
spring.cloud.gateway.discovery.locator.filters[1].args[replacement]: "'/${remaining}'"

十一、Reactor Netty访问日志

设置-Dreactor.netty.http.server.accessLogEnabled=true 打开Reactor Netty访问日志。
(它必须是Java系统属性,而不是Spring Boot属性。)

可以将日志记录系统配置为具有单独的访问日志文件。以下示例创建了一个回退配置:

    <appender name="accessLog" class="ch.qos.logback.core.FileAppender">
        <file>access_log.logfile>
        <encoder>
            <pattern>%msg%npattern>
        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>

十二、CORS配置

可以配置网关来控制CORS行为。“全局”CORS配置是URL模式到Spring Framework CORS configuration的映射。

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

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

为了向不由某些网关路由断言处理的请求提供相同的CORS配置,请将spring.cloud.gateway.globalcors.add-to-simple-url-handler-mapping设置为true。当尝试支持CORS预检请求,并且由于HTTP方法为options,路由断言未设置为true时,这很有用。

十三、 Actuator API

/gateway actuator端点允许监控Spring Cloud Gateway应用程序并与之交互。要进行远程访问,必须在应用程序属性中启用并通过HTTP或JMX公开端点。

# 启用端点
management.endpoint.gateway.enabled=true # default value
management.endpoints.web.exposure.include=gateway

1、Verbose Actuator 格式化

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
  }
]
# 默认情况下,此功能处于启用状态。要禁用它,请设置以下属性:(在未来的版本中,这将默认为true。)
spring.cloud.gateway.actuator.verbose.enabled=false

2、查找路由过滤器

Global Filters

要检索应用于所有路由的全局过滤器,请向/actuator/gateway/global filters发出GET请求。产生的响应类似于以下内容:

{
  "org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter@77856cc5": 10100,
  "org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter@4f6fd101": 10000,
  "org.springframework.cloud.gateway.filter.NettyWriteResponseFilter@32d22650": -1,
  "org.springframework.cloud.gateway.filter.ForwardRoutingFilter@106459d9": 2147483647,
  "org.springframework.cloud.gateway.filter.NettyRoutingFilter@1fbd5e0": 2147483647,
  "org.springframework.cloud.gateway.filter.ForwardPathFilter@33a71d23": 0,
  "org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter@135064ea": 2147483637,
  "org.springframework.cloud.gateway.filter.WebsocketRoutingFilter@23c05889": 2147483646
}

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

Route Filters

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

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

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

3、刷新路由缓存

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

4、检索网关中定义的路由

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

[{
  "route_id": "first_route",
  "route_object": {
    "predicate": "org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory$$Lambda$432/1736826640@1e9d7e7d",
    "filters": [
      "OrderedGatewayFilter{delegate=org.springframework.cloud.gateway.filter.factory.PreserveHostHeaderGatewayFilterFactory$$Lambda$436/674480275@6631ef72, order=0}"
    ]
  },
  "order": 0
},
{
  "route_id": "second_route",
  "route_object": {
    "predicate": "org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory$$Lambda$432/1736826640@cd8d298",
    "filters": []
  },
  "order": 0
}]

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

Path Type Description
route_id String The route ID.
route_object.predicate Object The route predicate.
route_object.filters Array The GatewayFilter factories applied to the route.
order Number The route order.

5、检索特定路由的信息

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

{
  "id": "first_route",
  "predicates": [{
    "name": "Path",
    "args": {"_genkey_0":"/first"}
  }],
  "filters": [],
  "uri": "https://www.uri-destination.org",
  "order": 0
}

下表描述了响应的结构:

Path Type Description
id String The route ID.
predicates Array The collection of route predicates. Each item defines the name and the arguments of a given predicate.
filters Array The collection of filters applied to the route.
uri String The destination URI of the route.
order Number The route order.

6、创建和删除特定的路由

要创建路由,请向/gateway/routes/{id_route_to_create}发出POST请求,并在JSON正文中指定路由的字段(请参见5、检索特定路由的信息)。

要删除路由,请向/gateway/routes/{id_route_to_delete}发出删除请求。

7、总结:所有端点的列表

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

ID HTTP Method Description
globalfilters GET Displays the list of global filters applied to the routes.
routefilters GET Displays the list of GatewayFilter factories applied to a particular route.
refresh POST Clears the routes cache.
routes GET Displays the list of routes defined in the gateway.
routes/{id} GET Displays information about a particular route.
routes/{id} POST Adds a new route to the gateway.
routes/{id} DELETE Removes an existing route from the gateway.

8、在多个网关实例之间共享路由

Spring Cloud Gateway提供了两个RouteDefinitionRepository实现。

第一个是inmemorroutedefinitionrepository,它只存在于一个网关实例的内存中。这种类型的存储库不适合跨多个网关实例填充路由。

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

十四、故障排查

1、日志级别

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

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

2、窃听

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

十五、开发指南

1、编写自定义路由断言工厂

为了编写路由断言,需要将RoutePredicateFactory实现为一个bean。有一个名为AbstractRoutePredicateFactory的抽象类,可以对其进行扩展。

@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
    }

}

2、编写自定义网关过滤器工厂

要编写GatewayFilter,必须将GatewayFilterFactory实现为bean。可以扩展名为AbstractGatewayFilterFactory的抽象类。

@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
    }

}
@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
    }

}

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

自定义筛选器类名应以GatewayFilterFactory结尾。
例如,要在配置文件中引用名为Something的筛选器,该筛选器必须位于名为SomethingGatewayFilterFactory的类中。

可以创建不带GatewayFilterFactory后缀的网关筛选器,如class AnotherThing。这个过滤器可以作为配置文件中的另一个东西被引用。这不是受支持的命名约定,在未来的版本中可能会删除此语法。请更新过滤器名称以符合要求。

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

十六、使用Spring MVC或Webflux构建一个简单的网关

Spring Cloud Gateway提供了一个名为ProxyExchange的实用程序对象。可以在常规的Spring web处理程序中使用它作为方法参数。它通过镜像HTTP动词的方法支持基本的下游HTTP交换。对于MVC,它还支持通过forward()方法转发到本地处理程序。要使用ProxyExchange,请在类路径中包含正确的模块(spring-cloud-gateway-mvc或spring-cloud-gateway-webflux)。

// 以下MVC示例将请求代理到/测试下游的远程服务器:
@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的所有特性都可以用于网关处理程序方法。因此,例如,可以注入请求头和查询参数,并且可以用映射注释中的声明来约束传入的请求。

可以使用ProxyExchange上的header()方法向下游响应添加标头。

还可以通过向get()方法(以及其他方法)添加映射器来操作响应头(以及响应中您喜欢的任何内容)。映射器是一个函数,它获取传入的响应实体并将其转换为传出的响应实体。

为“敏感”头(默认为cookie和authorization)和“代理”(x-forwarded-*)头提供了一流的支持,前者不传递给下游。

十七、配置属性

查看所有Spring Cloud Gateway相关配置属性的列表(可以在application.properties文件内、application.yml文件内或作为命令行开关指定各种属性。下面提供了常见Spring Cloud Gateway属性的列表,以及对使用这些属性的底层类的引用。)(属性贡献可以来自类路径上的其他jar文件,因此这不是一个详尽的列表。此外,还可以定义自己的属性。)

Name Default Description
spring.cloud.gateway.default-filters List of filter definitions that are applied to every route.
spring.cloud.gateway.discovery.locator.enabled FALSE Flag that enables DiscoveryClient gateway integration.
spring.cloud.gateway.discovery.locator.filters
spring.cloud.gateway.discovery.locator.include-expression TRUE SpEL expression that will evaluate whether to include a service in gateway integration or not, defaults to: true.
spring.cloud.gateway.discovery.locator.lower-case-service-id FALSE Option to lower case serviceId in predicates and filters, defaults to false. Useful with eureka when it automatically uppercases serviceId. so MYSERIVCE, would match /myservice/**
spring.cloud.gateway.discovery.locator.predicates
spring.cloud.gateway.discovery.locator.route-id-prefix The prefix for the routeId, defaults to discoveryClient.getClass().getSimpleName() + “_”. Service Id will be appended to create the routeId.
spring.cloud.gateway.discovery.locator.url-expression ‘lb://’+serviceId SpEL expression that create the uri for each route, defaults to: ‘lb://’+serviceId.
spring.cloud.gateway.enabled TRUE Enables gateway functionality.
spring.cloud.gateway.fail-on-route-definition-error TRUE Option to fail on route definition errors, defaults to true. Otherwise, a warning is logged.
spring.cloud.gateway.filter.add-request-header.enabled TRUE Enables the add-request-header filter.
spring.cloud.gateway.filter.add-request-parameter.enabled TRUE Enables the add-request-parameter filter.
spring.cloud.gateway.filter.add-response-header.enabled TRUE Enables the add-response-header filter.
spring.cloud.gateway.filter.circuit-breaker.enabled TRUE Enables the circuit-breaker filter.
spring.cloud.gateway.filter.dedupe-response-header.enabled TRUE Enables the dedupe-response-header filter.
spring.cloud.gateway.filter.fallback-headers.enabled TRUE Enables the fallback-headers filter.
spring.cloud.gateway.filter.hystrix.enabled TRUE Enables the hystrix filter.
spring.cloud.gateway.filter.json-to-grpc.enabled TRUE Enables the JSON to gRPC filter.
spring.cloud.gateway.filter.map-request-header.enabled TRUE Enables the map-request-header filter.
spring.cloud.gateway.filter.modify-request-body.enabled TRUE Enables the modify-request-body filter.
spring.cloud.gateway.filter.modify-response-body.enabled TRUE Enables the modify-response-body filter.
spring.cloud.gateway.filter.prefix-path.enabled TRUE Enables the prefix-path filter.
spring.cloud.gateway.filter.preserve-host-header.enabled TRUE Enables the preserve-host-header filter.
spring.cloud.gateway.filter.redirect-to.enabled TRUE Enables the redirect-to filter.
spring.cloud.gateway.filter.remove-hop-by-hop.headers
spring.cloud.gateway.filter.remove-hop-by-hop.order 0
spring.cloud.gateway.filter.remove-request-header.enabled TRUE Enables the remove-request-header filter.
spring.cloud.gateway.filter.remove-request-parameter.enabled TRUE Enables the remove-request-parameter filter.
spring.cloud.gateway.filter.remove-response-header.enabled TRUE Enables the remove-response-header filter.
spring.cloud.gateway.filter.request-header-size.enabled TRUE Enables the request-header-size filter.
spring.cloud.gateway.filter.request-header-to-request-uri.enabled TRUE Enables the request-header-to-request-uri filter.
spring.cloud.gateway.filter.request-rate-limiter.deny-empty-key TRUE Switch to deny requests if the Key Resolver returns an empty key, defaults to true.
spring.cloud.gateway.filter.request-rate-limiter.empty-key-status-code HttpStatus to return when denyEmptyKey is true, defaults to FORBIDDEN.
spring.cloud.gateway.filter.request-rate-limiter.enabled TRUE Enables the request-rate-limiter filter.
spring.cloud.gateway.filter.request-size.enabled TRUE Enables the request-size filter.
spring.cloud.gateway.filter.retry.enabled TRUE Enables the retry filter.
spring.cloud.gateway.filter.rewrite-location-response-header.enabled TRUE Enables the rewrite-location-response-header filter.
spring.cloud.gateway.filter.rewrite-location.enabled TRUE Enables the rewrite-location filter.
spring.cloud.gateway.filter.rewrite-path.enabled TRUE Enables the rewrite-path filter.
spring.cloud.gateway.filter.rewrite-response-header.enabled TRUE Enables the rewrite-response-header filter.
spring.cloud.gateway.filter.save-session.enabled TRUE Enables the save-session filter.
spring.cloud.gateway.filter.secure-headers.content-security-policy default-src ‘self’ https:; font-src ‘self’ https: data:; img-src ‘self’ https: data:; object-src ‘none’; script-src https:; style-src ‘self’ https: ‘unsafe-inline’
spring.cloud.gateway.filter.secure-headers.content-type-options nosniff
spring.cloud.gateway.filter.secure-headers.disable
spring.cloud.gateway.filter.secure-headers.download-options noopen
spring.cloud.gateway.filter.secure-headers.enabled TRUE Enables the secure-headers filter.
spring.cloud.gateway.filter.secure-headers.frame-options DENY
spring.cloud.gateway.filter.secure-headers.permitted-cross-domain-policies none
spring.cloud.gateway.filter.secure-headers.referrer-policy no-referrer
spring.cloud.gateway.filter.secure-headers.strict-transport-security max-age=631138519
spring.cloud.gateway.filter.secure-headers.xss-protection-header 1 ; mode=block
spring.cloud.gateway.filter.set-path.enabled TRUE Enables the set-path filter.
spring.cloud.gateway.filter.set-request-header.enabled TRUE Enables the set-request-header filter.
spring.cloud.gateway.filter.set-request-host-header.enabled TRUE Enables the set-request-host-header filter.
spring.cloud.gateway.filter.set-response-header.enabled TRUE Enables the set-response-header filter.
spring.cloud.gateway.filter.set-status.enabled TRUE Enables the set-status filter.
spring.cloud.gateway.filter.strip-prefix.enabled TRUE Enables the strip-prefix filter.
spring.cloud.gateway.forwarded.enabled TRUE Enables the ForwardedHeadersFilter.
spring.cloud.gateway.global-filter.adapt-cached-body.enabled TRUE Enables the adapt-cached-body global filter.
spring.cloud.gateway.global-filter.forward-path.enabled TRUE Enables the forward-path global filter.
spring.cloud.gateway.global-filter.forward-routing.enabled TRUE Enables the forward-routing global filter.
spring.cloud.gateway.global-filter.load-balancer-client.enabled TRUE Enables the load-balancer-client global filter.
spring.cloud.gateway.global-filter.netty-routing.enabled TRUE Enables the netty-routing global filter.
spring.cloud.gateway.global-filter.netty-write-response.enabled TRUE Enables the netty-write-response global filter.
spring.cloud.gateway.global-filter.reactive-load-balancer-client.enabled TRUE Enables the reactive-load-balancer-client global filter.
spring.cloud.gateway.global-filter.remove-cached-body.enabled TRUE Enables the remove-cached-body global filter.
spring.cloud.gateway.global-filter.route-to-request-url.enabled TRUE Enables the route-to-request-url global filter.
spring.cloud.gateway.global-filter.websocket-routing.enabled TRUE Enables the websocket-routing global filter.
spring.cloud.gateway.globalcors.add-to-simple-url-handler-mapping FALSE If global CORS config should be added to the URL handler.
spring.cloud.gateway.globalcors.cors-configurations
spring.cloud.gateway.handler-mapping.order 1 The order of RoutePredicateHandlerMapping.
spring.cloud.gateway.httpclient.compression FALSE Enables compression for Netty HttpClient.
spring.cloud.gateway.httpclient.connect-timeout The connect timeout in millis, the default is 45s.
spring.cloud.gateway.httpclient.max-header-size The max response header size.
spring.cloud.gateway.httpclient.max-initial-line-length The max initial line length.
spring.cloud.gateway.httpclient.pool.acquire-timeout Only for type FIXED, the maximum time in millis to wait for acquiring.
spring.cloud.gateway.httpclient.pool.eviction-interval 0 Perform regular eviction checks in the background at a specified interval. Disabled by default ({@link Duration#ZERO})
spring.cloud.gateway.httpclient.pool.max-connections Only for type FIXED, the maximum number of connections before starting pending acquisition on existing ones.
spring.cloud.gateway.httpclient.pool.max-idle-time Time in millis after which the channel will be closed. If NULL, there is no max idle time.
spring.cloud.gateway.httpclient.pool.max-life-time Duration after which the channel will be closed. If NULL, there is no max life time.
spring.cloud.gateway.httpclient.pool.metrics FALSE Enables channel pools metrics to be collected and registered in Micrometer. Disabled by default.
spring.cloud.gateway.httpclient.pool.name proxy The channel pool map name, defaults to proxy.
spring.cloud.gateway.httpclient.pool.type Type of pool for HttpClient to use, defaults to ELASTIC.
spring.cloud.gateway.httpclient.proxy.host Hostname for proxy configuration of Netty HttpClient.
spring.cloud.gateway.httpclient.proxy.non-proxy-hosts-pattern Regular expression (Java) for a configured list of hosts. that should be reached directly, bypassing the proxy
spring.cloud.gateway.httpclient.proxy.password Password for proxy configuration of Netty HttpClient.
spring.cloud.gateway.httpclient.proxy.port Port for proxy configuration of Netty HttpClient.
spring.cloud.gateway.httpclient.proxy.type proxyType for proxy configuration of Netty HttpClient.
spring.cloud.gateway.httpclient.proxy.username Username for proxy configuration of Netty HttpClient.
spring.cloud.gateway.httpclient.response-timeout The response timeout.
spring.cloud.gateway.httpclient.ssl.close-notify-flush-timeout 3000ms SSL close_notify flush timeout. Default to 3000 ms.
spring.cloud.gateway.httpclient.ssl.close-notify-read-timeout 0 SSL close_notify read timeout. Default to 0 ms.
spring.cloud.gateway.httpclient.ssl.default-configuration-type The default ssl configuration type. Defaults to TCP.
spring.cloud.gateway.httpclient.ssl.handshake-timeout 10000ms SSL handshake timeout. Default to 10000 ms
spring.cloud.gateway.httpclient.ssl.key-password Key password, default is same as keyStorePassword.
spring.cloud.gateway.httpclient.ssl.key-store Keystore path for Netty HttpClient.
spring.cloud.gateway.httpclient.ssl.key-store-password Keystore password.
spring.cloud.gateway.httpclient.ssl.key-store-provider Keystore provider for Netty HttpClient, optional field.
spring.cloud.gateway.httpclient.ssl.key-store-type JKS Keystore type for Netty HttpClient, default is JKS.
spring.cloud.gateway.httpclient.ssl.trusted-x509-certificates Trusted certificates for verifying the remote endpoint’s certificate.
spring.cloud.gateway.httpclient.ssl.use-insecure-trust-manager FALSE Installs the netty InsecureTrustManagerFactory. This is insecure and not suitable for production.
spring.cloud.gateway.httpclient.websocket.max-frame-payload-length Max frame payload length.
spring.cloud.gateway.httpclient.websocket.proxy-ping TRUE Proxy ping frames to downstream services, defaults to true.
spring.cloud.gateway.httpclient.wiretap FALSE Enables wiretap debugging for Netty HttpClient.
spring.cloud.gateway.httpserver.wiretap FALSE Enables wiretap debugging for Netty HttpServer.
spring.cloud.gateway.loadbalancer.use404 FALSE
spring.cloud.gateway.metrics.enabled FALSE Enables the collection of metrics data.
spring.cloud.gateway.metrics.prefix spring.cloud.gateway The prefix of all metrics emitted by gateway.
spring.cloud.gateway.metrics.tags Tags map that added to metrics.
spring.cloud.gateway.predicate.after.enabled TRUE Enables the after predicate.
spring.cloud.gateway.predicate.before.enabled TRUE Enables the before predicate.
spring.cloud.gateway.predicate.between.enabled TRUE Enables the between predicate.
spring.cloud.gateway.predicate.cloud-foundry-route-service.enabled TRUE Enables the cloud-foundry-route-service predicate.
spring.cloud.gateway.predicate.cookie.enabled TRUE Enables the cookie predicate.
spring.cloud.gateway.predicate.header.enabled TRUE Enables the header predicate.
spring.cloud.gateway.predicate.host.enabled TRUE Enables the host predicate.
spring.cloud.gateway.predicate.method.enabled TRUE Enables the method predicate.
spring.cloud.gateway.predicate.path.enabled TRUE Enables the path predicate.
spring.cloud.gateway.predicate.query.enabled TRUE Enables the query predicate.
spring.cloud.gateway.predicate.read-body.enabled TRUE Enables the read-body predicate.
spring.cloud.gateway.predicate.remote-addr.enabled TRUE Enables the remote-addr predicate.
spring.cloud.gateway.predicate.weight.enabled TRUE Enables the weight predicate.
spring.cloud.gateway.predicate.xforwarded-remote-addr.enabled TRUE Enables the xforwarded-remote-addr predicate.
spring.cloud.gateway.redis-rate-limiter.burst-capacity-header X-RateLimit-Burst-Capacity The name of the header that returns the burst capacity configuration.
spring.cloud.gateway.redis-rate-limiter.config
spring.cloud.gateway.redis-rate-limiter.include-headers TRUE Whether or not to include headers containing rate limiter information, defaults to true.
spring.cloud.gateway.redis-rate-limiter.remaining-header X-RateLimit-Remaining The name of the header that returns number of remaining requests during the current second.
spring.cloud.gateway.redis-rate-limiter.replenish-rate-header X-RateLimit-Replenish-Rate The name of the header that returns the replenish rate configuration.
spring.cloud.gateway.redis-rate-limiter.requested-tokens-header X-RateLimit-Requested-Tokens The name of the header that returns the requested tokens configuration.
spring.cloud.gateway.restrictive-property-accessor.enabled TRUE Restricts method and property access in SpEL.
spring.cloud.gateway.routes List of Routes.
spring.cloud.gateway.set-status.original-status-header-name The name of the header which contains http code of the proxied request.
spring.cloud.gateway.streaming-media-types
spring.cloud.gateway.x-forwarded.enabled TRUE If the XForwardedHeadersFilter is enabled.
spring.cloud.gateway.x-forwarded.for-append TRUE If appending X-Forwarded-For as a list is enabled.
spring.cloud.gateway.x-forwarded.for-enabled TRUE If X-Forwarded-For is enabled.
spring.cloud.gateway.x-forwarded.host-append TRUE If appending X-Forwarded-Host as a list is enabled.
spring.cloud.gateway.x-forwarded.host-enabled TRUE If X-Forwarded-Host is enabled.
spring.cloud.gateway.x-forwarded.order 0 The order of the XForwardedHeadersFilter.
spring.cloud.gateway.x-forwarded.port-append TRUE If appending X-Forwarded-Port as a list is enabled.
spring.cloud.gateway.x-forwarded.port-enabled TRUE If X-Forwarded-Port is enabled.
spring.cloud.gateway.x-forwarded.prefix-append TRUE If appending X-Forwarded-Prefix as a list is enabled.
spring.cloud.gateway.x-forwarded.prefix-enabled TRUE If X-Forwarded-Prefix is enabled.
spring.cloud.gateway.x-forwarded.proto-append TRUE If appending X-Forwarded-Proto as a list is enabled.
spring.cloud.gateway.x-forwarded.proto-enabled TRUE If X-Forwarded-Proto is enabled.

参考资料

https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-starter

你可能感兴趣的:(spring,boot,cloud,spring,cloud,gateway,java)