欢送拜访我的GitHub
https://github.com/zq2599/blog_demos
内容:所有原创文章分类汇总及配套源码,波及Java、Docker、Kubernetes、DevOPS等;
本篇概览
作为《Spring Cloud Gateway实战》系列的第五篇,是时候理解过滤器(filter)的作用了,本篇咱们一起来理解Spring Cloud Gateway内置好的过滤器,真是品种繁多功能强大
AddRequestHeader
- AddRequestHeader过滤器顾名思义,就是在申请头部增加指定的内容
- 带有predicate的残缺配置:
server: #服务端口 port: 8081spring: application: name: hello-gateway cloud: gateway: routes: - id: path_route uri: http://127.0.0.1:8082 predicates: - Path=/hello/** filters: - AddRequestHeader=x-request-foo, bar-config- 带有predicate的残缺动静配置:
[ { "id": "path_route_addr", "uri": "http://127.0.0.1:8082", "predicates": [ { "name": "Path", "args": { "pattern": "/hello/**" } } ], "filters": [ { "name": "AddRequestHeader", "args": { "name": "x-request-foo", "value": "bar-dynamic" } } ] }]- 实际效果:
AddRequestParameter
- AddRequestParameter过滤器顾名思义,就是增加申请参数
- 配置如下,服务提供方收到的申请中会多一个参数,名为foo,值为bar-config:
server: #服务端口 port: 8081spring: application: name: hello-gateway cloud: gateway: routes: - id: path_route uri: http://127.0.0.1:8082 predicates: - Path=/hello/** filters: - AddRequestParameter=foo, bar-config- 带有predicate的残缺动静配置:
[ { "id": "path_route_addr", "uri": "http://127.0.0.1:8082", "predicates": [ { "name": "Path", "args": { "pattern": "/hello/**" } } ], "filters": [ { "name": "AddRequestParameter", "args": { "name": "foo", "value": "bar-dynamic" } } ] }]- 实际效果:
AddResponseHeader
- AddResponseHeader过滤器就是在响应的header中增加参数
- 配置如下,客户端收到的响应,其header中会多一个参数,名为foo,值为bar-config-response:
server: #服务端口 port: 8081spring: application: name: hello-gateway cloud: gateway: routes: - id: path_route uri: http://127.0.0.1:8082 predicates: - Path=/hello/** filters: - AddResponseHeader=foo, bar-config-response- 带有predicate的残缺动静配置:
[ { "id": "path_route_addr", "uri": "http://127.0.0.1:8082", "predicates": [ { "name": "Path", "args": { "pattern": "/hello/**" } } ], "filters": [ { "name": "AddResponseHeader", "args": { "name": "foo", "value": "bar-dynamic-response" } } ] }]- 实际效果:
DedupeResponseHeader
- 服务提供方返回的response的header中,如果有的key出线了多个value(例如跨域场景下的Access-Control-Allow-Origin),DedupeResponseHeader过滤器能够将反复的value剔除调,剔除策略有三种:RETAIN_FIRST (保留第一个,默认), RETAIN_LAST(保留最初一个), RETAIN_UNIQUE(去重)
- 配置如下,指定了两个header key的去重,策略是保留最初一个:
server: #服务端口 port: 8081spring: application: name: hello-gateway cloud: gateway: routes: - id: path_route uri: http://127.0.0.1:8082 predicates: - Path=/hello/** filters: - DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin, RETAIN_LASTDedupeResponseHeader
- 服务提供方返回的response的header中,如果有的key出线了多个value(例如跨域场景下的Access-Control-Allow-Origin),DedupeResponseHeader过滤器能够将反复的value剔除调,剔除策略有三种:RETAIN_FIRST (保留第一个,默认), RETAIN_LAST(保留最初一个), RETAIN_UNIQUE(去重)
- 配置如下,指定了两个header key的去重,策略是保留最初一个:
server: #服务端口 port: 8081spring: application: name: hello-gateway cloud: gateway: routes: - id: path_route uri: http://127.0.0.1:8082 predicates: - Path=/hello/** filters: - DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin, RETAIN_LASTCircuitBreaker
- CircuitBreaker即断路器,咱们在独自的一篇中深刻体验这个弱小的性能吧
FallbackHeaders
- FallbackHeaders个别和CircuitBreaker配合应用,来看上面的配置,产生断路后,申请会被转发FallbackHeaders去解决,此时FallbackHeaders会在header中指定的key上增加异样信息:
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-HeaderMapRequestHeader
- MapRequestHeader用于header中的键值对复制,如下配置的意思是:如果申请header中有<font color="blue">Blue</font>就新增名为<font color="red">X-Request-Red</font>的key,其值和<font color="blue">Blue</font>的值一样
- 配置如下,指定了两个header key的去重,策略是保留最初一个:
server: #服务端口 port: 8081spring: application: name: hello-gateway cloud: gateway: routes: - id: path_route uri: http://127.0.0.1:8082 predicates: - Path=/hello/** filters: - MapRequestHeader=Blue, X-Request-Red- 如下图,申请header中有Blue:
- 再看服务提供方的日志,显示header中多了X-Request-Red:
- 如果申请的header中曾经存在<font color="blue">X-Request-Red</font>会呈现什么状况呢?如下图,咱们把<font color="blue">X-Request-Red</font>写在申请header中:
- 在服务提供方打断点,能够发现神奇的一幕,header中的所有key,对应的值其实都是汇合,只是大多数状况下汇合外面只有一个元素,而MapRequestHeader新增的元素会被放入这个汇合,不会影响原有内容:
PrefixPath
- PrefixPath很好了解,就是转发到服务提供者的时候,给path加前缀
- 例如我这边服务提供者原始地址是<font color="blue">http://127.0.0.1:8082/hello/str</font>配置如下,如果我给网关配置PrefixPath=hello,那么拜访网关的时候,申请门路中就不须要<font color="blue">hello</font>了,配置如下:
server: #服务端口 port: 8081spring: application: name: hello-gateway cloud: gateway: routes: - id: path_route uri: http://127.0.0.1:8082 predicates: - Path=/str filters: - PrefixPath=/hello- 如下图,申请门路无需<font color="blue">hello</font>:
PreserveHostHeader
- PreserveHostHeader在转发申请到服务提供者的时候,会保留host信息(否则就只能由HTTP client来决定了)
- 先看不应用PreserveHostHeader的成果,如下图,服务提供者收到的申请header中的host就是网关配置的信息:
- 加上PreserveHostHeader试试,如下图红框,是真正的host信息:
RequestRateLimiter
- RequestRateLimiter用于限流,波及内容较多,就放在独自的章节深入研究吧
RedirectTo
- RedirectTo的性能简略直白:跳转到指定地位,上面的配置中,uri字段显著是一个有效的地址,但申请还是会被RedirectTo转发到指定地位去:
server: #服务端口 port: 8081spring: application: name: hello-gateway cloud: gateway: routes: - id: path_route uri: http://127.1.1.1:11111 predicates: - Path=/hello/** filters: - RedirectTo=302, http://127.0.0.1:8082/hello/strRemoveRequestHeader
- RemoveRequestHeader很好了解,删除申请header中的指定值
- 上面的配置会删除申请header中的foo:
server: #服务端口 port: 8081spring: application: name: hello-gateway cloud: gateway: routes: - id: path_route uri: http://127.0.0.1:8082 predicates: - Path=/hello/** filters: - RemoveRequestHeader=fooRemoveResponseHeader
- RemoveResponseHeader删除响应header中的指定值
- 上面的配置会删除响应header中的foo:
server: #服务端口 port: 8081spring: application: name: hello-gateway cloud: gateway: routes: - id: path_route uri: http://127.0.0.1:8082 predicates: - Path=/hello/** filters: - RemoveResponseHeader=fooRemoveRequestParameter
- RemoveRequestParameter 删除申请参数中的指定参数
- 上面的配置会删除申请参数中的foo:
server: #服务端口 port: 8081spring: application: name: hello-gateway cloud: gateway: routes: - id: path_route uri: http://127.0.0.1:8082 predicates: - Path=/hello/** filters: - RemoveRequestParameter=foo1RewritePath
- RewritePath十分实用,将申请参数中的门路做变换
- 上面的配置会将<font color="blue">/test/str</font>转成<font color="blue">/hello/str</font>:
server: #服务端口 port: 8081spring: application: name: hello-gateway cloud: gateway: routes: - id: path_route uri: http://127.0.0.1:8082 predicates: - Path=/test/** filters: - RewritePath=/test/?(?<segment>.*), /hello/$\{segment}- 申请如下,可见path中的test会被网关批改成hello,变成正确的申请门路:
RewriteLocationResponseHeader
- RewriteLocationResponseHeader用于改写response中的location信息
- 配置如下,一共是四个参数:stripVersionMode、locationHeaderName、hostValue、protocolsRegex
- 例如申请是<font color="blue">api.example.com/some/object/name</font>,response的location是<font color="blue">object-service.prod.example.net/v2/some/object/id</font>,最终会被上面的filter改写为<font color="blue">api.example.com/some/object/id</font>
spring: cloud: gateway: routes: - id: rewritelocationresponseheader_route uri: http://example.org filters: - RewriteLocationResponseHeader=AS_IN_REQUEST, Location, ,- stripVersionMode的策略一共三种:
NEVER_STRIP:不执行
AS_IN_REQUEST :原始申请没有vesion,就执行
ALWAYS_STRIP :固定执行
- Location用于替换host:port局部,如果没有就是用Request中的host
- protocolsRegex用于匹配协定,如果匹配不上,name过滤器啥都不做
RewriteResponseHeader
- RewriteResponseHeader很好了解:批改响应header,参数有三个:header的key,匹配value的正则表达式,批改value的后果
- 上面的配置示意批改响应header中<font color="blue">X-Response-Red</font>这个key的value,找到password=xxx的内容,改成password=*
server: #服务端口 port: 8081spring: application: name: hello-gateway cloud: gateway: routes: - id: path_route uri: http://127.0.0.1:8082 predicates: - Path=/test/** filters: - RewriteResponseHeader=X-Response-Red, , password=[^&]+, password=***SecureHeaders
- SecureHeaders会在响应的header中增加很多和平安相干的内容,配置如下:
server: #服务端口 port: 8081spring: application: name: hello-gateway cloud: gateway: routes: - id: path_route uri: http://127.0.0.1:8082 predicates: - Path=/hello/** filters: - SecureHeaders- 响应如下,可见header中增加了很多信息:
- 如果不想返回上图中的某些内容,能够在配置文件中敞开掉,如下图红框,x-frame-options和strict-transport-security两项被设置为不返回了:
- 再试试,失去如下响应,可见x-frame-options和strict-transport-security都没有返回:
SetPath
- SetPath配合predicates应用,上面的配置会将申请<font color="blue">/test/str</font>改成<font color="blue">/hello/str</font>,可见这个segment是在predicates中赋值的,而后再filters中拿来用:
server: #服务端口 port: 8081spring: application: name: hello-gateway cloud: gateway: filter: secure-headers: disable: - x-frame-options - strict-transport-security routes: - id: path_route uri: http://127.0.0.1:8082 predicates: - Path=/test/{segment} filters: - SetPath=/hello/{segment}SetRequestHeader
- SetRequestHeader顾名思义,就是改写申请的header,将指定key改为指定value,如果该key不存在就创立:
server: #服务端口 port: 8081spring: application: name: hello-gateway cloud: gateway: filter: secure-headers: disable: - x-frame-options - strict-transport-security routes: - id: path_route uri: http://127.0.0.1:8082 predicates: - Path=/hello/** filters: - SetRequestHeader=X-Request-Red, Blue- 和SetPath相似,SetRequestHeader也能够和predicates配合,在predicates中定义的变量能够用在SetRequestHeader中,如下所示,当申请是/hello/str的时候,header中X-Request-Red的值就是<font color="blue">Blue-str</font>:
server: #服务端口 port: 8081spring: application: name: hello-gateway cloud: gateway: filter: secure-headers: disable: - x-frame-options - strict-transport-security routes: - id: path_route uri: http://127.0.0.1:8082 predicates: - Path=/hello/{segment} filters: - SetRequestHeader=X-Request-Red, Blue-{segment}SetResponseHeader
- SetResponseHeader顾名思义,就是改写响应的header,将指定key改为指定value,如果该key不存在就创立:
server: #服务端口 port: 8081spring: application: name: hello-gateway cloud: gateway: filter: secure-headers: disable: - x-frame-options - strict-transport-security routes: - id: path_route uri: http://127.0.0.1:8082 predicates: - Path=/hello/** filters: - SetResponseHeader=X-Request-Red, BlueSetStatus
- SetStatus很好了解:管制返回code,上面的设置会返回500:
server: #服务端口 port: 8081spring: application: name: hello-gateway cloud: gateway: routes: - id: path_route uri: http://127.0.0.1:8082 predicates: - Path=/hello/** filters: - SetStatus=500- 测试成果如下图,服务提供者的内容会失常返回,然而返回码曾经被改为500了:
- 如果您想用SetStatus批改返回码,同时又不想丢掉实在的返回码,能够减少如下配置,这样实在的返回码就被放在名为<font color="blue">original-status-header-name</font>的key中了:
server: #服务端口 port: 8081spring: application: name: hello-gateway cloud: gateway: set-status: original-status-header-name: aaabbbccc routes: - id: path_route uri: http://127.0.0.1:8082 predicates: - Path=/hello/** filters: - SetStatus=500StripPrefix
- StripPrefix是个很罕用的filter,例如申请是<font color="blue">/aaa/bbb/hello/str</font>,咱们要想将其转为<font color="blue">/hello/str</font>,用<font color="blue">StripPrefix=2</font>即可,后面两级path都被删掉了:
server: #服务端口 port: 8081spring: application: name: hello-gateway cloud: gateway: set-status: original-status-header-name: aaabbbccc routes: - id: path_route uri: http://127.0.0.1:8082 predicates: - Path=/aaa/** filters: - StripPrefix=2- 如下图,响应失常:
Retry
- 顾名思义,Retry就是重试,须要以下参数配合应用:
- retries:重试次数
- statuses:遇到什么样的返回状态才重试,取值参考:org.springframework.http.HttpStatus
- methods:那些类型的办法会才重试(GET、POST等),取值参考:org.springframework.http.HttpMethod
- series:遇到什么样的series值才重试,取值参考:org.springframework.http.HttpStatus.Series
- exceptions:遇到什么样的异样才重试
- backoff:重试策略,由多个参数形成,例如firstBackoff
- 参考配置如下:
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: falseRequestSize
- RequestSize也很罕用:管制申请大小,能够应用<font color="blue">KB</font>或者<font color="blue">MB</font>等单位,超过这个大小就会返回413谬误(Payload Too Large),
spring: cloud: gateway: routes: - id: request_size_route uri: http://localhost:8080/upload predicates: - Path=/upload filters: - name: RequestSize args: maxSize: 5000000- 留神,如果没有设置RequestSize,Spring Cloud Gateway默认的下限是<font color="red">5MB</font>
SetRequestHostHeader
- SetRequestHostHeader会批改申请header中的host值
- 上面的配置,会将申请header中的host改为<font color="blue">aaabbb</font>
server: #服务端口 port: 8081spring: application: name: hello-gateway cloud: gateway: routes: - id: path_route uri: http://127.0.0.1:8082 predicates: - Path=/hello/** filters: - name: SetRequestHostHeader args: host: aaabbb- 在服务提供者的代码中打断点,如下图,可见host曾经被改为<font color="blue">aaabbb</font>
ModifyRequestBody
ModifyRequestBody用于批改申请的body内容,这里官网举荐用代码来配置,如下所示,申请body中本来是字符串,后果被改成了Hello对象的实例:
@Beanpublic 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; }}
ModifyResponseBody
- ModifyResponseBody与后面的ModifyRequestBody相似,官网倡议用代码实现,上面的代码作用是将响应body的内容改为全副大写:
@Beanpublic 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();}TokenRelay
- 在应用第三方鉴权的时候,如OAuth2,用TokenRelay能够将第三方的token转发到服务提供者那里去:
spring: cloud: gateway: routes: - id: resource uri: http://localhost:9000 predicates: - Path=/resource filters: - TokenRelay=- 记得还要增加jar包依赖<font color="blue">org.springframework.boot:spring-boot-starter-oauth2-client</font>
设置全局filter
- 后面的例子中,所有filter都放在路由策略中,配合predicates一起应用的,如果您想配置全局失效的filter,能够在配置文件中做以下设置,上面的配置示意AddResponseHeader和PrefixPath会解决所有申请,和路由设置无关:
spring: cloud: gateway: default-filters: - AddResponseHeader=X-Response-Default-Red, Default-Blue - PrefixPath=/httpbin- 至此,大部分内置过滤器咱们曾经理解了,有几个稍微简单的留待前面的章节深刻学习
你不孤独,欣宸原创一路相伴
- Java系列
- Spring系列
- Docker系列
- kubernetes系列
- 数据库+中间件系列
- DevOps系列
欢送关注公众号:程序员欣宸
微信搜寻「程序员欣宸」,我是欣宸,期待与您一起畅游Java世界...
https://github.com/zq2599/blog_demos