spring cloud gateway系列教程2——GatewayFilter_下篇

spring cloud gateway系列教程目录

  1. spring cloud gateway系列教程1—Route Predicate
  2. spring cloud gateway系列教程2——GatewayFilter_上篇
  3. spring cloud gateway系列教程2——GatewayFilter_下篇
  4. spring cloud gateway系列教程3—Global Filters
  5. spring cloud gateway系列教程4—其他配置

上篇

8. RequestRateLimiter GatewayFilter Factory

RequestRateLimiter GatewayFilter Factory使用RateLimiter来决定当前请求是否允许通过,如果不允许,则默认返回状态码HTTP 429 - Too Many Requests

RequestRateLimiter GatewayFilter可以使用一个可选参数keyResolver来做速率限制。

keyResolverKeyResolver接口的一个实现bean,在配置里面,通过SpEL表达式#{@myKeyResolver}来管理bean的名字myKeyResolver

KeyResolver.java.

public interface KeyResolver {
    Mono<String> resolve(ServerWebExchange exchange);
}

KeyResolver接口允许你使用不同的策略来得出限制请求的key,未来,官方也会推出一些KeyResolver的不同实现。

KeyResolver默认实现是PrincipalNameKeyResolver,通过ServerWebExchange中获取Principal,并以Principal.getName()作为限流的key。

如果KeyResolver拿不到key,请求默认都会被限制,你也可以自己配置spring.cloud.gateway.filter.request-rate-limiter.deny-empty-key:是否允许空key,spring.cloud.gateway.filter.request-rate-limiter.empty-key-status-code :空key时返回的状态码。

RequestRateLimiter不支持捷径配置,如下面的配置是非法的

application.properties.

# INVALID SHORTCUT CONFIGURATION
spring.cloud.gateway.routes[0].filters[0]=RequestRateLimiter=2, 2, #{@userkeyresolver}
8.1 Redis RateLimiter

基于 Stripe的redis实现方案,依赖spring-boot-starter-data-redis-reactiveSpring Boot starter,使用的是令牌桶算法。

redis-rate-limiter.replenishRate配置的是每秒允许通过的请求数,其实就是令牌桶的填充速率。

redis-rate-limiter.burstCapacity配置的是一秒内最大的请求数,其实就是令牌桶的最大容量,如果设置为0,则会阻塞所有请求。

所以可以通过设置相同的replenishRateburstCapacity来实现匀速的速率控制,通过设置burstCapacity大于replenishRate来允许系统流量瞬间突发,但是对于这种情况,突发周期为burstCapacity / replenishRate秒,如果周期内有两次请求突发的情况,则第二次会有部分请求丢失,返回HTTP 429 - Too Many Requests

application.yml.

spring:
  cloud:
    gateway:
      routes:
      - id: requestratelimiter_route
        uri: http://www.google.com
        filters:
        - name: RequestRateLimiter
          args:
            redis-rate-limiter.replenishRate: 10
            redis-rate-limiter.burstCapacity: 20

Config.java.

@Bean
KeyResolver userKeyResolver() {
    return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
}

上面定义了每个用户每秒10个请求的速率限制,允许20的突发流量,突发完,下一秒只允许10个请求通过了,KeyResolver定义了通过请求获取请求参数user作为key。

你也可以实现RateLimiter接口自定义自己的请求速率限制器,在配置文件中使用SpEL表达式配置对应的bean的名字即可。

application.yml.

spring:
  cloud:
    gateway:
      routes:
      - id: requestratelimiter_route
        uri: http://www.google.com
        filters:
        - name: RequestRateLimiter
          args:
            rate-limiter: "#{@myRateLimiter}"
            key-resolver: "#{@userKeyResolver}"

9. RedirectTo GatewayFilter Factory

RedirectTo GatewayFilter Factory使用statusurl两个参数,其中status必须是300系列的HTTP状态码,url则是跳转的地址,会放在响应的Location的header中(http协议中转跳的header)。

application.yml.

spring:
  cloud:
    gateway:
      routes:
      - id: prefixpath_route
        uri: http://www.google.cn
        filters:
        - RedirectTo=302, http://www.edjdhbb.com

上面路由会执行302重定向到http://www.edjdhbb.com

10. RemoveNonProxyHeaders GatewayFilter Factory

RemoveNonProxyHeaders GatewayFilter Factory转发请求是会根据IETF的定义,默认会移除下列的http头信息:

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

你也可以通过配置spring.cloud.gateway.filter.remove-non-proxy-headers.headers来更改需要移除的header列表。

11. RemoveRequestHeader GatewayFilter Factory

RemoveRequestHeader GatewayFilter Factory配置header的name,即可以移除请求的header。

application.yml.

spring:
  cloud:
    gateway:
      routes:
      - id: removerequestheader_route
        uri: http://www.google.com
        filters:
        - RemoveRequestHeader=X-Request-Foo

上面路由在发送请求给下游时,会将请求中的X-Request-Foo头信息去掉。

12. RemoveResponseHeader GatewayFilter Factory

RemoveResponseHeader GatewayFilter Factory通过配置header的name,会在响应返回时移除header。

application.yml.

spring:
  cloud:
    gateway:
      routes:
      - id: removeresponseheader_route
        uri: http://www.google.com
        filters:
        - RemoveResponseHeader=X-Response-Foo

上面路由会在响应返回给gateway的客户端时,将X-Response-Foo响应头信息去掉。

13. RewritePath GatewayFilter Factory

RewritePath GatewayFilter Factory使用路径regexp和替换路径replacement两个参数做路径重写,两个都可以灵活地使用java的正则表达式。

application.yml.

spring:
  cloud:
    gateway:
      routes:
      - id: rewritepath_route
        uri: http://www.google.com
        predicates:
        - Path=/foo/**
        filters:
        - RewritePath=/foo/(?<segment>.*), /$\{segment}

对于上面的例子,如果请求的路径是/foo/bar,则gateway会将请求路径改为/bar发送给下游。

注:在YAML 的格式中使用$\来代替$

14. RewriteResponseHeader GatewayFilter Factory

RewriteResponseHeader GatewayFilter Factory的作用是修改响应返回的header内容,需要配置响应返回的header的name,匹配规则regexp和替换词replacement,也是支持java的正则表达式。

application.yml.

spring:
  cloud:
    gateway:
      routes:
      - id: rewriteresponseheader_route
        uri: http://www.google.com
        filters:
        - RewriteResponseHeader=X-Response-Foo, , password=[^&]+, password=***

举个例子,对于上面的filter,如果响应的headerX-Response-Foo的内容是/42?user=ford&password=omg!what&flag=true,这个内容会修改为/42?user=ford&password=***&flag=true

15. SaveSession GatewayFilter Factory

SaveSession GatewayFilter Factory会在请求下游时强制执行WebSession::save方法,用在那种像Spring Session延迟数据存储的,并在请求转发前确保session状态保存情况。

application.yml.

spring:
  cloud:
    gateway:
      routes:
      - id: save_session
        uri: http://www.google.com
        predicates:
        - Path=/foo/**
        filters:
        - SaveSession

如果你将Spring SecutirySpring Session集成使用,并想确保安全信息都传到下游机器,你就需要配置这个filter。

16. SecureHeaders GatewayFilter Factory

SecureHeaders GatewayFilter Factory会添加在返回响应中一系列安全作用的header,至于为什么,英文好的可以看一下这篇博客

默认会添加这些头信息和默认内容:

  • 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

如果你想修改这些头信息的默认内容,可以在配置文件中添加下面的配置:

前缀:spring.cloud.gateway.filter.secure-headers

上面的header对应的后缀:

  • xss-protection-header
  • strict-transport-security
  • frame-options
  • content-type-options
  • referrer-policy
  • content-security-policy
  • download-options
  • permitted-cross-domain-policies

前后缀接起来即可,如:spring.cloud.gateway.filter.secure-headers.xss-protection-header

17. SetPath GatewayFilter Factory

SetPath GatewayFilter Factory采用路径template参数,通过请求路径的片段的模板化,来达到操作修改路径的母的,运行多个路径片段模板化。

application.yml.

spring:
  cloud:
    gateway:
      routes:
      - id: setpath_route
        uri: http://www.google.com
        predicates:
        - Path=/foo/{segment}
        filters:
        - SetPath=/{segment}

对于上面的例子,如果路径是/foo/bar,则对于下游的请求路径会修改为/bar

18. SetResponseHeader GatewayFilter Factory

SetResponseHeader GatewayFilter Factory通过设置namevalue来替换响应对于的header。

application.yml.

spring:
  cloud:
    gateway:
      routes:
      - id: setresponseheader_route
        uri: http://www.google.com
        filters:
        - SetResponseHeader=X-Response-Foo, Bar

对于上面的例子,如果下游的返回带有头信息为X-Response-Foo:1234,则会gateway会替换为X-Response-Foo:Bar,在返回给客户端。

19. SetStatus GatewayFilter Factory

SetStatus GatewayFilter Factory通过配置有效的Spring HttpStatus枚举参数,可以是类似于404的这些数字,也可以是枚举的name字符串,来修改响应的返回码。

application.yml.

spring:
  cloud:
    gateway:
      routes:
      - id: setstatusstring_route
        uri: http://www.google.com
        filters:
        - SetStatus=BAD_REQUEST
      - id: setstatusint_route
        uri: http://www.google.com
        filters:
        - SetStatus=401

上面例子中,两种路由都会将响应的状态码设置为401。

20. StripPrefix GatewayFilter Factory

StripPrefix GatewayFilter Factory通过配置parts来表示截断路径前缀的数量。

application.yml.

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

如上面例子中,如果请求的路径为/name/bar/foo,则路径会修改为/foo,即将路径的两个前缀去掉了。

21. Retry GatewayFilter Factory

Retry GatewayFilter Factory可以配置针对不同的响应做请求重试,可以配置如下参数:

  • retries: 重试次数
  • statuses: 需要重试的状态码,需要根据枚举 org.springframework.http.HttpStatus来配置
  • methods: 需要重试的请求方法,需要根据枚举org.springframework.http.HttpMethod来配置
  • series: HTTP状态码系列,详情见枚举org.springframework.http.HttpStatus.Series

application.yml.

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

上面例子,当下游服务返回502状态码时,gateway会重试3次。

22. RequestSize GatewayFilter Factory

RequestSize GatewayFilter Factory会限制客户端请求包的大小,通过参数RequestSize来配置最大上传大小,单位字节。

application.yml.

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

如果请求大小超过5000kb限制,则会返回状态码413 Payload Too Large

如果不设置这个filter,默认限制5M的请求大小。

23. Modify Request Body GatewayFilter Factory

官方说这个filter目前只是beta版本,API以后可能会修改。

Modify Request Body GatewayFilter Factory可以修改请求体内容,这个只能通过java来配置。

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

24. Modify Response Body GatewayFilter Factory

官方说这个filter目前只是beta版本,API以后可能会修改。

Modify Response Body GatewayFilter Factory用于修改响应返回的内容,同样只能通过java配置。

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

这一章接着上一章介绍了Spring Cloud Gateway官方的Gateway Filter使用场景,下一章讲Global Filters的使用

如果想查看其他spring cloud gateway的案例和使用,可以点击查看

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容