Spring Cloud:网关 - Spring Cloud Gateway

版本:3.0.2

Spring Cloud Gateway基于Spring生态提供了一套API Gateway,包括:Spring 5,Spring Boot 2和Project Reactor。Spring Cloud Gateway旨在提供一个简单、有效的API路由和一系列基础功能,如:安全,监控/指标和限流。

1、引入Spring Cloud Gateway

如果需要在项目中使用Spring Cloud Gateway,只需要在项目中引入spring-cloud-starter-gateway,详情参考Spring Cloud Project page

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

如果引入了starter,但是不想启动,可以配置spring.cloud.gateway.enabled=false。

Spring Cloud Gateway是基于Spring Boot 2.x,Spring WebFlux和Project Reactor。所以许多我们熟悉的同步库(如Spring Data和Spring Security)都可能无法在Spring Cloud Gateway中使用,如果你不太熟悉这些项目,建议在使用前先行阅读并学习相关项目文档。

Spring Cloud Gateway需要基于Netty运行,无法运行于传统Servlet容器或构建为WAR包。

2、术语

  • Route(路由):网关的基本组成单位,一个路由模块包括一个ID,一个目标URI,一组Predidate(断言)和一组Filter(过滤器)。如果断言为真,则路由匹配,目标URI会被访问。

  • Predicate(断言):Java 8的Predicate(Java 8 Function Predicate),输入类型是一个Spring Framework的 ServerWebExchange 。可以使用它来匹配来自 HTTP 请求的任何内容,例如 headers 或参数。

  • Filter(过滤器):一个特殊工程构建的一组GatewayFilter实例,你可以使用它在发送下游请求之前或之后修改requests和responses。

3、如何实现

客户端向Spring Cloud Gateway发起请求,如果网关的Gateway Handler Mapping判断请求命中路由,则将其发送到Gateway Web Handler。Handler 再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑。过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(“pre”)或之后(“post”)执行业务逻辑。

4、配置Route Predicate Factories和Gateway Filter Factories

我们可以通过两种方式配置predicates和filters:快捷方式和全量方式。

4.1、快捷方式

快捷方式由 名称=参数1,参数2组成。

application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: after_route
        uri: https://example.org
        predicates:
		- Cookie=mycookie,mycookievalue

例子中定义了一个Cookie路由断言,这个断言包含两个参数:cookie名称和命中的值mycookievalue

4.2、全量方式

全量方式采用传统yaml的name/value配置方式。通常由一个name key和一个args key组成,args key是一组用于配置断言或过滤器的键值对。

application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: after_route
        uri: https://example.org
        predicates:
        - name: Cookie
          args:
            name: mycookie
			regexp: mycookievalue

参数意义和上面的例子一致。

5、路由断言规则

Spring Cloud Gateway通过Spring WebFlux的HandlerMapping实现路由判断,Spring Cloud Gateway内建一系列路由断言规则。这些断言规则通过不同的HTTP request属性条件匹配不同路由。

 

5.1、After Predicate

spring:
  cloud:
    gateway:
      routes:
      - id: after_route
        uri: https://example.org
        predicates:
		- After=2017-01-20T17:42:47.789-07:00[America/Denver]

After断言包含一个参数datetime,格式为ZonedDateTime,匹配所有指定时间后的请求,

5.2、Before Predicate

spring:
  cloud:
    gateway:
      routes:
      - id: before_route
        uri: https://example.org
        predicates:
		- Before=2017-01-20T17:42:47.789-07:00[America/Denver]

Before断言包含一个参数datetime,格式为ZonedDateTime,匹配所有指定时间前的请求

5.3、Between Predicate


spring:
  cloud:
    gateway:
      routes:
      - id: between_route
        uri: https://example.org
        predicates:
        - Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]

Between断言包含两个参数:datetime1和datetime2,格式为ZonedDateTime,匹配所有发生在两个时间之间的请求。

5.4、Cookie Predicate


spring:
  cloud:
    gateway:
      routes:
      - id: cookie_route
        uri: https://example.org
        predicates:
		- Cookie=chocolate, ch.p

Cookie包含两个参数,name(cookie名字)和regexp(正则表达式),匹配指定名称满足正则表达式的cookies。

5.5、Header Predicate

spring:
  cloud:
    gateway:
      routes:
      - id: header_route
        uri: https://example.org
        predicates:
		- Header=X-Request-Id, \d+

Header包含两个参数,name(header名称)和regexp(正则表达式),匹配指定名称满足正则表达式的headers。

5.6、Host Predicate

spring:
  cloud:
    gateway:
      routes:
      - id: host_route
        uri: https://example.org
        predicates:
        - Host=**.somehost.org,**.anotherhost.org

Host包含一个参数,一组Host域名,匹配满足域名规则的请求。

5.7、Method Predicate

spring:
  cloud:
    gateway:
      routes:
      - id: method_route
        uri: https://example.org
        predicates:
		- Method=GET,POST

Method匹配HTTP methods请求方式,参数可以包含一个或多个请求方式。

5.8、Path Predicate


spring:
  cloud:
    gateway:
      routes:
      - id: path_route
        uri: https://example.org
        predicates:
		- Path=/red/{segment},/blue/{segment}

Path包含两个参数,一组路由匹配器(PathMatcher)和一个可选的/匹配表示(matchTrailingSlash),默认是true。如果matchTrailingSlash为false,则/red/1/将匹配失败。

5.9、Query Predicate

spring:
  cloud:
    gateway:
      routes:
      - id: query_route
        uri: https://example.org
        predicates:
		- Query=red, gree.

Query包含两个参数,一个请求参数param和一个可选正则表达式regexp,匹配指定名称的满足正则表达式的请求参数。

5.10、RemoteAddr Predicate

spring:
  cloud:
    gateway:
      routes:
      - id: remoteaddr_route
        uri: https://example.org
        predicates:
        - RemoteAddr=192.168.1.1/24

RemoteAddr包含一个IPv4或IPv6的字符串列表,例如192.168.0.1/16,配置包含在列表内的请求。

5.11、Weight Predicate


spring:
  cloud:
    gateway:
      routes:
      - id: weight_high
        uri: https://weighthigh.org
        predicates:
        - Weight=group1, 8
      - id: weight_low
        uri: https://weightlow.org
        predicates:
		- Weight=group1, 2

Weight包含两个参数,group和weight(int类型),将根据分组权重分配路由请求,如例子中80%导流到weighthigh.org,20%导流到weightlow.org

6、过滤器

路由过滤器用于修改HTTP request和HTTP response,Spring Cloud Gateway包含许多内建过滤器。

6.1、AddRequestHeader GatewayFilter


spring:
  cloud:
    gateway:
      routes:
      - id: add_request_header_route
        uri: https://example.org
        filters:
		- AddRequestHeader=X-Request-red, blue

AddRequestHeader包含name和value两个参数,可添加参数(如X-Request-red:blue)到所有匹配的下游请求头。AddRequestHeader还可以匹配URI请求参数,并在value中使用,例如:

spring:
  cloud:
    gateway:
      routes:
      - id: add_request_header_route
        uri: https://example.org
        predicates:
        - Path=/red/{segment}
        filters:
		- AddRequestHeader=X-Request-Red, Blue-{segment}

6.2、AddRequestParameter GatewayFilter


spring:
  cloud:
    gateway:
      routes:
      - id: add_request_parameter_route
        uri: https://example.org
        filters:
		- AddRequestParameter=red, blue

AddRequestParameter包含name和value两个参数,可添加参数(如red-blue)到所有匹配的请求参数。AddRequestParameter还可以匹配URI参数,并用于value中,例如:


spring:
  cloud:
    gateway:
      routes:
      - id: add_request_parameter_route
        uri: https://example.org
        predicates:
        - Host: {segment}.myhost.org
        filters:
		- AddRequestParameter=foo, bar-{segment}

6.3、AddResponseHeader GatewayFilter


spring:
  cloud:
    gateway:
      routes:
      - id: add_response_header_route
        uri: https://example.org
        filters:
		- AddResponseHeader=X-Response-Red, Blue

AddResponseHeader包含name和value两个参数,可添加参数到下游response的headers中,如X-Response-Foo:Bar。AddResponseHeader还可以匹配URI请求参数,并用于value中,例如:


spring:
  cloud:
    gateway:
      routes:
      - id: add_response_header_route
        uri: https://example.org
        predicates:
        - Host: {segment}.myhost.org
        filters:
		- AddResponseHeader=foo, bar-{segment}

6.4、DedupeResponseHeader GatewayFilter


spring:
  cloud:
    gateway:
      routes:
      - id: dedupe_response_header_route
        uri: https://example.org
        filters:
		- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin

DedupeResponseHeader包含一个name(一个通过空格分隔的header名称列表)和一个可选的strategy(默认RETAIN_FIRST-保留优先,RETAIN_LAST和RETAIN_UNIQUE)。例如删除Response Header中Access-Control-Allow-Credentials和Access-Control-Allow-Origin重复的值。

6.5、CircuitBreaker GatewayFilter

CircuitBreaker GatewayFilter基于Spring Cloud的CircuitBreaker实现,支持各种熔断限流实现,例如Resilience4J,如果要使用CircuitBreaker GatewayFilter需引入依赖如spring-cloud-starter-circuitbreaker-reactor-resilience4j。

spring:
  cloud:
    gateway:
      routes:
      - id: circuitbreaker_route
        uri: lb://backing-service:8088
        predicates:
        - Path=/consumingServiceEndpoint
        filters:
        - name: CircuitBreaker
          args:
            name: myCircuitBreaker
            fallbackUri: forward:/inCaseOfFailureUseThis
		- RewritePath=/consumingServiceEndpoint, /backingServiceEndpoint

6.6、FallbackHeader GatewayFilter

spring:
  cloud:
    gateway:
      routes:
      - id: ingredients
        uri: lb://ingredients
        predicates:
        - Path=//ingredients/**
        filters:
        - name: CircuitBreaker
          args:
            name: fetchIngredients
            fallbackUri: forward:/fallback
      - id: ingredients-fallback
        uri: http://localhost:9994
        predicates:
        - Path=/fallback
        filters:
        - name: FallbackHeaders
          args:
            executionExceptionTypeHeaderName: Test-Header

FallbackHeaders可用于添加异常详情并传递到fallbackUri中。例如,当发生熔断异常时,请求将重定向到

localhost:9994,并添加Execution-Exception-Type到请求Header中。

常用参数如下:

  • executionExceptionTypeHeaderName ("Execution-Exception-Type")

  • executionExceptionMessageHeaderName ("Execution-Exception-Message")

  • rootCauseExceptionTypeHeaderName ("Root-Cause-Exception-Type")

  • rootCauseExceptionMessageHeaderName ("Root-Cause-Exception-Message")

详情请参考 Spring Cloud CircuitBreaker Factory section.

6.7、MapRequestHeader GatewayFilter

spring:
  cloud:
    gateway:
      routes:
      - id: map_request_header_route
        uri: https://example.org
        filters:
		- MapRequestHeader=Blue, X-Request-Red

MapRequestHeader包含fromHeader和toHeader两个参数,将自动匹配HTTP请求中是否包含fromHeader(如Blue),如不存在,则不影响,如存在,则替换fromHeader为toHeader(如替换Blue为X-Request-Red)。

6.8、PrefixPath GatewayFilter

spring:
  cloud:
    gateway:
      routes:
      - id: prefixpath_route
        uri: https://example.org
        filters:
		- PrefixPath=/mypath

PrefixPath包含单个prefix参数,将为所有满足条件的请求添加前缀,例如请求/hello将变为/mypath/hello

6.9、PreserveHostHeader GatewayFilter

spring:
  cloud:
    gateway:
      routes:
      - id: preserve_host_route
        uri: https://example.org
        filters:
		- PreserveHostHeader

PreserveHostHeader没有参数,定义了原始Host将一定被传输到下游请求。

6.10、RequestRateLimiter GatewayFilter


spring:
  cloud:
    gateway:
      routes:
      - id: requestratelimiter_route
        uri: https://example.org
        filters:
        - name: RequestRateLimiter
          args:
            rate-limiter: "#{@myRateLimiter}"
			key-resolver: "#{@userKeyResolver}"

RequestRateLimiter使用限流器(RateLimiter)实现请求限流,这个过滤器包含一个可选的的keyResolver,KeyResolver接口采用可插拔策略实现限制请求的密钥获取,默认实现是PrincipalNameKeyResolver。

6.11、RedirectTo GatewayFilter


spring:
  cloud:
    gateway:
      routes:
      - id: prefixpath_route
        uri: https://example.org
        filters:
		- RedirectTo=302, https://acme.org

RedirectTo包含两个参数status(HTTP状态码)和url。当状态为302时,将重定向为Location:https://acme.org。

6.12、RemoveRequestHeader GatewayFilter

spring:
  cloud:
    gateway:
      routes:
      - id: removerequestheader_route
        uri: https://example.org
        filters:
		- RemoveRequestHeader=X-Request-Foo

RemoveRequestHeader包含一个name参数,将删除指定名称的header,如X-Request-Foo Header在发送到下游之前将删除。

6.13、RemoveResponseHeader GatewayFilter

spring:
  cloud:
    gateway:
      routes:
      - id: removeresponseheader_route
        uri: https://example.org
        filters:
		- RemoveResponseHeader=X-Response-Foo

RemoveResponseHeader包含一个name参数,将删除指定名称的header,如X-Request-Foo Header在返回之前将删除。

6.14、RemoveRequestParameter GatewayFilter

spring:
  cloud:
    gateway:
      routes:
      - id: removerequestparameter_route
        uri: https://example.org
        filters:
		- RemoveRequestParameter=red

RemoveRequestParameter包含一个name参数,将删除指定名称的请求参数,如red在发送到下游请求之前将删除。

6.15、RewritePath GatewayFilter

spring:
  cloud:
    gateway:
      routes:
      - id: rewritepath_route
        uri: https://example.org
        predicates:
        - Path=/red/**
        filters:
        - RewritePath=/red/?(?<segment>.*), /$\{segment}

RewritePath包含一个regexp(正则表达式)和一个replacement(替代值)两个参数,用于灵活的重写请求路径。

6.16、RewriteLocationResponseHeader GatewayFilter

spring:
  cloud:
    gateway:
      routes:
      - id: rewritelocationresponseheader_route
        uri: http://example.org
        filters:
		- RewriteLocationResponseHeader=AS_IN_REQUEST, Location, ,

RewriteLoacationResponseHeader用于刘改response的Location Header,包括四个参数: 

stripVersionMode:忽略版本,枚举值:NEVER_STRIP(不过滤),AS_IN_REQUEST(默认值,有时过滤),ALWAYS_STRIP(一直过滤)

locationHeaderName:header 名称

hostValue:如果提供,将替换Location中的host:port

protocolsRegex:协议名称的匹配正则表达式,如果不命中,则不执行,默认值为http|https|ftp|ftps

6.17、RewriteResponseHeader GatewayFilter


spring:
  cloud:
    gateway:
      routes:
      - id: rewriteresponseheader_route
        uri: https://example.org
        filters:
		- RewriteResponseHeader=X-Response-Red, , password=[^&]+, password=***

RewriteResponseHeader包含三个参数:name,regexp和replacement,提供灵活的方式重写Response Header。

6.18、SaveSession GatewayFilter


spring:
  cloud:
    gateway:
      routes:
      - id: save_session
        uri: https://example.org
        predicates:
        - Path=/foo/**
        filters:
        - SaveSession

SaveSession将在转发到下游请求之前执行WebSession::save操作。

6.19、SecureHeaders GatewayFilter

SecureHeaders将添加一系列Header到response,添加的参数如下:

  • X-Xss-Protection:1 (mode=block)

  • Strict-Transport-Security (max-age=631138519)

  • X-Frame-Options (DENY)

  • X-Content-Type-Options (nosniff)

  • Referrer-Policy (no-referrer)

  • 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)'

  • X-Download-Options (noopen)

  • X-Permitted-Cross-Domain-Policies (none)

6.20、SetPath GatewayFilter

spring:
  cloud:
    gateway:
      routes:
      - id: setpath_route
        uri: https://example.org
        predicates:
        - Path=/red/{segment}
        filters:
		- SetPath=/{segment}

SetPath包含一个参数template,通过URI template模板来修改请求路径。例如/red/blue将自动修改为/blue

6.21、SetRequestHeader GatewayFilter

 spring:
  cloud:
    gateway:
      routes:
      - id: setrequestheader_route
        uri: https://example.org
        filters:
		- SetRequestHeader=X-Request-Red, Blue

SetRequestHeader包括name和value两个参数,用于替换指定名称的header,如果存在相同名称的header(如X-Request-Red:1234),则替换为X-Request-Red:Blue。

6.22、SetResponseHeader GatewayFilter

spring:
  cloud:
    gateway:
      routes:
      - id: setresponseheader_route
        uri: https://example.org
        predicates:
        - Host: {segment}.myhost.org
        filters:
		- SetResponseHeader=foo, bar-{segment}

SetResponseHeader包括name和value两个参数,用于替换指定名称的header,如果存在相同名称的header(如foo),则替换为bar-{segment}。

6.23、SetStatus GatewayFilter

spring:
  cloud:
    gateway:
      routes:
      - id: setstatusstring_route
        uri: https://example.org
        filters:
        - SetStatus=BAD_REQUEST
      - id: setstatusint_route
        uri: https://example.org
        filters:
		- SetStatus=401

SetStatus包含单个参数status,格式为HttpStatus,如例子中Http状态被设置为401。

6.24、StripPrefix GatewayFilter

spring:
  cloud:
    gateway:
      routes:
      - id: nameRoot
        uri: https://nameservice
        predicates:
        - Path=/name/**
        filters:
        - StripPrefix=2

StripPrefix包括一个参数parts,表示请求Path的下标。例如请求路径为/name/blue/red,则将替换为https://nameservice/red

6.25、Retry GatewayFilter

Retry包含以下参数:

  • retries: 重试次数

  • statuses: 引起重试的 HTTP status codes ,参考org.springframework.http.HttpStatus.

  • methods: 引起重试的HTTP methods,参考 org.springframework.http.HttpMethod.

  • series: 系列HTTP状态码,参考 org.springframework.http.HttpStatus.Series.

  • exceptions: 引起重试的异常列表

  • backoff: 重试配置的指数补偿.

spring:
  cloud:
    gateway:
      routes:
      - id: retry_test
        uri: http://localhost:8080/flakey
        predicates:
        - Host=*.retry.com
        filters:
        - name: Retry
          args:
            retries: 3
            statuses: BAD_GATEWAY
            methods: GET,POST
            backoff:
              firstBackoff: 10ms
              maxBackoff: 50ms
              factor: 2
			  basedOnPreviousValue: false

6.26、RequestSize GatewayFilter

spring:
  cloud:
    gateway:
      routes:
      - id: request_size_route
        uri: http://localhost:8080/upload
        predicates:
        - Path=/upload
        filters:
        - name: RequestSize
          args:
			maxSize: 5000000

RequestSize包含一个maxSize参数,默认单位为B,可以自定义为KB或MB,用于限制请求大小。

6.27、SetRequestHostHeader GatewayFilter

spring:
  cloud:
    gateway:
      routes:
      - id: set_request_host_header_route
        uri: http://localhost:8080/headers
        predicates:
        - Path=/headers
        filters:
        - name: SetRequestHostHeader
          args:
				host: example.org

SetRequestHostHeader包含一个host参数,用于替换host header为指定的值。 

6.28、ModifyRequestBody GatewayFilter

ModifyRequestBody用于修改请求body


@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
    return builder.routes()
        .route("rewrite_request_obj", r -> r.host("*.rewriterequestobj.org")
            .filters(f -> f.prefixPath("/httpbin")
                .modifyRequestBody(String.class, Hello.class, MediaType.APPLICATION_JSON_VALUE,
                    (exchange, s) -> return Mono.just(new Hello(s.toUpperCase())))).uri(uri))
        .build();
}

static class Hello {
    String message;

    public Hello() { }

    public Hello(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

6.29、ModifyResponseBody GatewayFilter

ModifyResponseBody用于修改response body


@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
    return builder.routes()
        .route("rewrite_response_upper", r -> r.host("*.rewriteresponseupper.org")
            .filters(f -> f.prefixPath("/httpbin")
                .modifyResponseBody(String.class, String.class,
                    (exchange, s) -> Mono.just(s.toUpperCase()))).uri(uri))
        .build();
}

6.30、TokenRelay GatewayFilter

TokenRelay可以通过转发到SSO代理服务实现OAuth2校验,需要引入依赖org.springframework.boot:spring-boot-starter-oauth2-client。

App.java


@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
    return builder.routes()
            .route("resource", r -> r.path("/resource")
                    .filters(f -> f.tokenRelay())
                    .uri("http://localhost:9000"))
            .build();
}

application.yaml

spring:
  cloud:
    gateway:
      routes:
      - id: resource
        uri: http://localhost:9000
        predicates:
        - Path=/resource
        filters:
		- TokenRelay=

6.31、默认Filter

可以通过spring.cloud.gateway.default-filters的方式添加作用于全部路由的过滤器,可以设置一系列filter作为默认过滤器

spring:
  cloud:
    gateway:
      default-filters:
      - AddResponseHeader=X-Response-Default-Red, Default-Blue
	  - PrefixPath=/httpbin

7、Global Filters(全局过滤器)

Global Filter是一种作用于全部路由的特殊过滤器。

7.1、自定义Global Filter和排序

可以通过继承GlobalFilter接口自定义全局过滤器,Spring Cloud Gateway将自动加载所有全局过滤器构建过滤链。

过滤链条的执行顺序通过org.springframework.core.Ordered接口实现,order越大优先级越低:


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

7.2、Forward Routing Filter

ForwardRoutingFilter判断URL是否包含forward标识(如:forward://localendpoint),将使用 DispatcherHandler去处理这请求,请求URL的路径将被转发URL中的路径覆盖。

7.3、LoadBalancerClientFilter

LoadBalancerClientFilter判断URL是否包含lb标识(如:lb://myservice),将使用Spring Cloud LoadBalancerClient去分析myservice的真实地址和端口实现负载均衡。

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

通常情况下,如果loadbalancer没有找到对应的服务将默认返回503,如果需要返回404,请配置spring.cloud.gateway.loadbalancer.use404=true。

7.4、ReactiveLoadBalancerClientFilter

LoadBalancerClientFilter判断URL是否包含lb标识(如:lb://myservice),将使用Spring Cloud ReactorLoadBalancer去分析myservice的真实地址和端口实现负载均衡。和LoadBalancerClientFilter的区别在于是基于响应式实现。

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

7.5、Netty Routing Filter

NettyRoutingFilter判断URL是否包含http或者https标识,将使用Netty HttpClient发起一个下游代理请求。

7.6、Netty Write Response Filter

如果存在Netty HttpClientResponse时,NettyWriteResponseFilter将在所有filter执行完成后执行并返回response给网关客户端。

7.7、RouteToRequestUrl Filter

如果存在Route对象,RouteToRequestUrlFilter将执行并创建一个基于Request请求但是根据Route对象更新的新URI。

7.8、Websocket Routing Filter

如果URI中包含ws或wss标识,Websocket routing filter将执行,实现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/**

7.9、Gateway Metrics Filter

添加spring-boot-starter-actuator引用,则可以通过spring.cloud.gateway.metrics.enabled启动gateway metrics监控,默认true。可以通过/actuator/metrics/gateway.requests查看对应指标参数,通常包括以下标识:

  • routeId: The route ID.

  • routeUri: The URI to which the API is routed.

  • outcome: The outcome, as classified by HttpStatus.Series.

  • status: The HTTP status of the request returned to the client.

  • httpStatusCode: The HTTP Status of the request returned to the client.

  • httpMethod: The HTTP method used for the request.

7.10、路由执行标识

可以通过设置ServerWebExchange的gatewayAlreadyRouted属性标识exchange对象是否被路由处理过,如果标识为routed,则其他路由过滤器将不再执行。

  • ServerWebExchangeUtils.isAlreadyRouted: takes a ServerWebExchange object and checks if it has been “routed”.

  • ServerWebExchangeUtils.setAlreadyRouted takes a ServerWebExchange object and marks it as “routed”.

8、HttpHeadersFilters

HttpHeadersFilters类似于NettyRoutingFilter,作用于所有下游请求发送之前。

8.1、Forwarded Headers Filter

Forwarded Filter创建一个Forwarded 请求头并发送到下游服务。

8.2、RemoveHopByHop Headers Filter

RemoveHopByHop用于移除前置请求的请求头,默认可移除的请求头如下:

  • Connection

  • Keep-Alive

  • Proxy-Authenticate

  • Proxy-Authorization

  • TE

  • Trailer

  • Transfer-Encoding

  • Upgrade

8.3、XForwarded Headers Filter

XForwarded Filter用于创建一系列X-Forwarded-*请求头并发送到下游服务。

通过以下属性创建当个请求头:

  • 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

通过以下属性追加请求头:

  • 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

9、TLS和SSL

网关可以通过配置支持HTTPS请求

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

10、Configuation

Configuation是由一组RouteDefinitionLocator实例实现的。PropertiesRouteDefinitionLocator通过Spring Boot的@ConfigurationProperties机制加载配置,

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

Example application.yml


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

11、路由元数据配置(Metadata)

我们可以通过额外的属性给每个路由配置元数据,例如:

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

12、HTTP超时配置

12.1、全局超时配置

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

12.2、单路由超时配置

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

也可以通过代码配置:

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

13、Netty访问日志

可以通过设置-Dreactor.netty.http.server.accessLogEnabled=true来打开Reactor Netty访问日志。注意是启动参数而不是Spring Boot配置

可以通过logback配置输出日志文件:


    <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配置

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

例子中,允许docs.spring.io进行跨域的get请求操作。

15、Actuator API

网关通过暴露/gateway,创建actuator endpoints来暴露HTTP或者JMX来监控和管理应用。

application.properties

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

提供如下actuator endpoints:

ID

HTTP Method

Description

globalfilters

GET

查看全局路由过滤器信息

routefilters

GET

查看 GatewayFilter 信息

refresh

POST

刷新路由缓存

routes

GET

查看路由信息

routes/{id}

GET

查询指定路由信息

routes/{id}

POST

新增新路由

routes/{id}

DELETE

删除指定路由

16、故障排除

16.1 日志等级

通过调整下列package的日志等级为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 窃听(Wiretap)

可以通过开启HttpClient(spring.cloud.gateway.httpserver.wiretap=true)和HttpServer(spring.cloud.gateway.httpclient.wiretap=true)的窃听模式获取如请求头,body等日志信息。

17、开发手册

17.1、自定义Route Predicate


public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<HeaderRoutePredicateFactory.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

PreGatewayFilterFactory.java


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


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.3、自定义Global Filters


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

 

 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值