• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

springcloud gateway 知识库

武飞扬头像
南京小菜
帮助1

1 gateway 知识图谱

学新通

2 什么是spring cloud gateway

spring cloud gateway 是springcloud 生态系统中的网关,目标是代替zuul,其不仅提供统一的路由方式,并且还基于filter链的方式提供网关基本的功能.目前最新的springcloud中引用的还是zuul 1.x版本,而这个版本是基于过滤器的,是阻塞IO,不支持长连接

学新通

zuul 2.x 版本一直跳票,2019年5月,netflix终于开源支持异步调用模式的zuul2.0版本。可惜的是spring cloud 已经不在集成zuul2.x。这是我们学习 spring cloud gateway的前置原因。

spring cloud gateway 是基于spring生态系统之上构建的API 网关,包括:spring5、springboot2 和project Reactor。spring cloud Gateway 提供一种简单有效的方法来路由到api。并为他们提供跨域的关注点。例如:安全性,监视\指标、限流等。由于spring5.0 支持netty HTTP2 ,而springboot 2.0支持spring5.0,因此spring cloud gateway支持netty和http2顺理成章。

3 什么是服务网关

api gateway,是出现在系统边界上的一个面向api的、串行集中式强管控服务,这里的边界是企业IT系统的边界,可以理解为企业及应用防火墙。主要起到隔离外部方位与内部系统的作用。在微服务概念流行之前,api网关就已经诞生了,例如:银行、证券等灵越常见的前置机系统,可以也是解决访问认证、报文转换,访问统计等问题。

随着微服务架构概念的提出,api 网关成了微服务架构的一个标配组件。

api网关是一个服务器,是系统对外唯一入口。api网关封装了系统内部架构,为每个客户提定制的api。所有与的客户端和消费端都通过统一的网关介入微服务,在网关层处理所有非业务功能。api网关并不是微服务场景必须的组件。

学新通

对于服务数量众多,复杂度比较高,规模比较大的业务来说,引入api网关也有一系统的好处。

  • 聚合接口使得服务队调用者透明,客户端和后端的耦合度降低

  • 聚合后台服务,节省流量,提高性能,提升用户体验

  • 提供安全、流控、过滤、缓存、计费、监控等api管理功能

4 为什么要使用网关

  • 单体应用:浏览器发起请求到单体应用的服务器所在的机器上,应用从数据库查询数据原路返回给浏览器。对于单体应用来说是不需要网关的。
  • 微服务:微服务的应用可能部署在不同的机房、不同地域、不同的域名下。此时客户端想要请求对应服务,都需要知道机器真实的ip或者域名url,当微服务实例众多时,这个非常难以记忆的,对于客户端来说太复杂难以维护。此时就有了网关。客户端相关请求直接发动到网关,由网关更加请求标识解析判断出具体的微服务地址,在吧请求转发到微服务实例。这个记忆功能就全部交给了网关来操作。

学新通

总结:

  • 客户端会多次请求不同的微服务,增加了客户端的复杂性
  • 存在跨域请求,在一定场景下处理相对复杂
  • 身份认证问题,每个微服务需要独立身份认证
  • 难以重构,随着项目迭代可能需要重新话费微服务
  • 某些微服务可能使用了防火墙,浏览器不友好协议,直接访问会有一定的困难

因此,我们需要网关结余客户端和服务器之间的中间层,所有的外部请求睢县进过微服务网关,客户端只要需要与网关交互,只需要知道网关地址即可:这样便于开发且有一下有点:

  • 易于监控,在微服务网关收集监控数据并将其推送到外部系统进行分析
  • 易于认证,在微服务网关进行认证,然后再将请求转发到后端的微服务,从而无需再每个为服务器中进行认证。
  • 减少了客户端与各个微服务之间的交互次数

5 网关解决了什么问题

学新通

网关具有身份认证与安全,审查与监控、动态路由、负载均衡、缓存、请求分片与管理、静态响应处理等功能。当然最主要的职责还是与外界联系

  • 性能:api 高可能,负载均衡,容错机制。

  • 安全:权限身份认证、脱敏、流量清洗,后端签名(保证链路可信调用)。黑名单(非法调用的限制)

  • 日志:日志记录,一旦涉及分布式,全链路更加比不可少

  • 缓存:数据缓存

  • 监控:记录请求响应数据,api耗时分析,性能监控

  • 限流:流量控制,错峰流控,可以定义多种限流规则

  • 灰度:线上灰度部署,可以减小风险

  • 路由:动态路由规则

6 常用网关解决方案

6.1 nginx lua

nginx是一个高性能http和反向代理服务器。nginx一方面可以做反向代理服务器,另一方面可以做静态资源服务器

  • nginx适合做门户网关,是这个全局网关,对外处于最外层的那种;而gateway属于业务网关,主要来应对不同可短端提供服务,用于聚合业务。各个微服务独立部署,职责单一,对外提供无的时候需要有一个东西把业务聚合起来。
  • gateway可以实现熔断、重试等功能。这个是nginx不具备的

6.2 kong

kong是mashape提供的一款api管理软件,他本身是基于nginx lua的,但比nginx提供了更简单的配置方式,数据采用apacheCassandra/postgresql存储,并且提供了一些优秀的插件,如:验证,日志,调用频次限制等。kong非常诱人的地方就是提供了大量的插件来拓展应用,通过设置不同插件可以为服务提供各种增强的功能。

  • 优点:预计nginx所以在性能和稳定性上都没有问题,kong作为一款商业软件,在nginx上做了很多拓展工作,而且还有付费的商业插件。kong本身也有付费的企业版,其中包括技术支持和培训以及api分析插件。
  • 缺点:如果你使用了spring cloud ,kong如何结合目前已有的服务治理体系

6.3 Traefik

Traefik 是一个开源的go语言开发的为了让部署微服务更加便捷而诞生的现代HTTP反向代理,负载均衡工具。他支持多后台(docker、swarm、kubernetes,marathon、mesos。consoul、etcd、zookeeper)。来来自动化,动态奶的应用他的配置文件设置。traefik拥有一个机遇angularjs编写简单网站界面,支持restapi,配置文件热更新,无需重启进程。高可用的集群配置文件

  • 相对于spring cloud 和kubernetes而言,目前比较适合kubernetes

6.4 spring cloud netflix zuul

zuul 是netflix公司开源的一个api 网关组件,spring cloud 对齐进行二次基于springboot的注解方式做到开箱即用,目前来说,结合spring cloud提供服务器治理体系,可以做到请求转发,更加配置或者默认路由规则进行路由和load balance,无缝集成hystrix。

  • 退让可以通过自定义filter实现我们想要的功能,但是由于zuul本身设计是基于单线程的接受请求和转发是阻塞IO,不支持长链接。且springcloud 自己有gateway所以这个种方案,现在已经不怎么被市场接受了

6.5 spring cloud Gateway

7 nginx实现网关

这里不做重点,大家可以去查看我的博客,其原理就是做了一个反向代理。做地址正则配置,转发到不同的微服务上

7.1 路由工作原理

学新通

8 路由规则

https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories官方文档

共计11个规则

8.1 after

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

此路由匹配 2017 年 1 月 20 日 17:42 山地时间(丹佛)之后提出的任何请求。

8.2 Before

所述Before路线谓词工厂有一个参数,一个datetime(其是Java ZonedDateTime)。此谓词匹配发生在指定 之前的请求datetime。以下示例配置了一个 before 路由谓词:

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

此路由匹配 2017 年 1 月 20 日 17:42 山地时间(丹佛)之前提出的任何请求。

8.3 Between

Between路线谓词工厂有两个参数,datetime1并且datetime2 这是JavaZonedDateTime对象。此谓词匹配发生在 之后datetime1和之前的请求datetime2。该datetime2参数必须是后datetime1。以下示例配置了一个 between 路由谓词:

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]

8.4 Cookie 路由谓词工厂

所述Cookie路线谓词工厂采用两个参数,该cookienameregexp(其是Java正则表达式)。此谓词匹配具有给定名称且其值与正则表达式匹配的 cookie。以下示例配置 cookie 路由谓词工厂:

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

此路由匹配 2017 年 1 月 20 日 17:42 山地时间(丹佛)之后和 2017 年 1 月 21 日 17:42 山地时间(丹佛)之前提出的任何请求。这对于维护窗口可能很有用。

8.5 header

所述Header路线谓词工厂采用两个参数,报头name和一个regexp(其是Java正则表达式)。此谓词与具有给定名称的标头匹配,其值与正则表达式匹配。以下示例配置标头路由谓词:

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

如果请求的标头名称X-Request-Id\d 正则表达式匹配(即,它的值为一位或多位数字),则此路由匹配。

8.6 HOST

Host路线谓词工厂需要一个参数:主机名的列表patterns。该模式是一个 Ant 风格的模式,以.作为分隔符。此谓词匹配Host与模式匹配的标头。以下示例配置主机路由谓词:

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

{sub}.myhost.org还支持URI 模板变量(例如)。

如果请求具有这种路由匹配Host用的头值www.somehost.orgbeta.somehost.orgwww.anotherhost.org

此谓词提取 URI 模板变量(例如sub,在前面的示例中定义的)作为名称和值的映射,并将其放置在 中ServerWebExchange.getAttributes(),键定义在 中ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE。然后这些值可供工厂使用GatewayFilter

8.7 Method

所述Method路线谓词厂需要methods的参数,它是一个或多个参数:HTTP方法来匹配。以下示例配置方法路由谓词:

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

8.8 Path(常用)

Path路线谓词厂有两个参数:春天的列表PathMatcher patterns和所谓的可选标志matchTrailingSlash(默认true)。以下示例配置路径路由谓词:

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

8.9 Query

所述Query路线谓词工厂采用两个参数:所要求的param和可选的regexp(其是Java正则表达式)。以下示例配置查询路由谓词:

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

如果请求包含green查询参数,则前面的路由匹配。


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

如果请求包含red其值与正则gree.表达式匹配的查询参数,则前面的路由匹配,因此greengreet将匹配。

8.10 RemoteAddr

所述RemoteAddr路线谓词工厂需要的列表(分钟尺寸1) sources,其是CIDR的表示法(IPv4或IPv6)的字符串,如192.168.0.1/16(其中192.168.0.1是一个IP地址和16一个子网掩码)。以下示例配置 RemoteAddr 路由谓词:

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

例如,如果请求的远程地址是 ,则此路由匹配192.168.1.10

8.11 Weight

Weight路线谓词工厂有两个参数:groupweight(一个int)。权重是按组计算的。以下示例配置权重路由谓词:

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

该路由会将约 80% 的流量转发到weighthigh.org,将约 20% 的流量转发weightlow.org

注意分组的概念。

8.12 java正则表达式

字符 说明
\ 将下一字符标记为特殊字符、文本、反向引用或八进制转义符。例如, n匹配字符 n\n 匹配换行符。序列 \\ 匹配 \\( 匹配 (
^ 匹配输入字符串开始的位置。如果设置了 RegExp 对象的 Multiline 属性,^ 还会与"\n"或"\r"之后的位置匹配。
$ 匹配输入字符串结尾的位置。如果设置了 RegExp 对象的 Multiline 属性,$ 还会与"\n"或"\r"之前的位置匹配。
* 零次或多次匹配前面的字符或子表达式。例如,zo* 匹配"z"和"zoo"。* 等效于 {0,}。
一次或多次匹配前面的字符或子表达式。例如,"zo "与"zo"和"zoo"匹配,但与"z"不匹配。 等效于 {1,}。
? 零次或一次匹配前面的字符或子表达式。例如,"do(es)?“匹配"do"或"does"中的"do”。? 等效于 {0,1}。
{n} n 是非负整数。正好匹配 n 次。例如,"o{2}"与"Bob"中的"o"不匹配,但与"food"中的两个"o"匹配。
{n,} n 是非负整数。至少匹配 n 次。例如,"o{2,}“不匹配"Bob"中的"o”,而匹配"foooood"中的所有 o。"o{1,}“等效于"o ”。"o{0,}“等效于"o*”。
{n,m} mn 是非负整数,其中 n <= m。匹配至少 n 次,至多 m 次。例如,"o{1,3}"匹配"fooooood"中的头三个 o。‘o{0,1}’ 等效于 ‘o?’。注意:您不能将空格插入逗号和数字之间。
? 当此字符紧随任何其他限定符(*、 、?、{n}、{n,}、{n,m})之后时,匹配模式是"非贪心的"。"非贪心的"模式匹配搜索到的、尽可能短的字符串,而默认的"贪心的"模式匹配搜索到的、尽可能长的字符串。例如,在字符串"oooo"中,"o ?“只匹配单个"o”,而"o “匹配所有"o”。
. 匹配除"\r\n"之外的任何单个字符。若要匹配包括"\r\n"在内的任意字符,请使用诸如"[\s\S]"之类的模式。
(pattern) 匹配 pattern 并捕获该匹配的子表达式。可以使用 $0…$9 属性从结果"匹配"集合中检索捕获的匹配。若要匹配括号字符 ( ),请使用"(“或者”)"。
(?:pattern) 匹配 pattern 但不捕获该匹配的子表达式,即它是一个非捕获匹配,不存储供以后使用的匹配。这对于用"or"字符 (|) 组合模式部件的情况很有用。例如,'industr(?:y|ies) 是比 ‘industry|industries’ 更经济的表达式。
(?=pattern) 执行正向预测先行搜索的子表达式,该表达式匹配处于匹配 pattern 的字符串的起始点的字符串。它是一个非捕获匹配,即不能捕获供以后使用的匹配。例如,‘Windows (?=95|98|NT|2000)’ 匹配"Windows 2000"中的"Windows",但不匹配"Windows 3.1"中的"Windows"。预测先行不占用字符,即发生匹配后,下一匹配的搜索紧随上一匹配之后,而不是在组成预测先行的字符后。
(?!pattern) 执行反向预测先行搜索的子表达式,该表达式匹配不处于匹配 pattern 的字符串的起始点的搜索字符串。它是一个非捕获匹配,即不能捕获供以后使用的匹配。例如,‘Windows (?!95|98|NT|2000)’ 匹配"Windows 3.1"中的 “Windows”,但不匹配"Windows 2000"中的"Windows"。预测先行不占用字符,即发生匹配后,下一匹配的搜索紧随上一匹配之后,而不是在组成预测先行的字符后。
x|y 匹配 xy。例如,‘z|food’ 匹配"z"或"food"。’(z|f)ood’ 匹配"zood"或"food"。
[xyz] 字符集。匹配包含的任一字符。例如,"[abc]“匹配"plain"中的"a”。
[^xyz] 反向字符集。匹配未包含的任何字符。例如,"[^abc]“匹配"plain"中"p”,“l”,“i”,“n”。
[a-z] 字符范围。匹配指定范围内的任何字符。例如,"[a-z]"匹配"a"到"z"范围内的任何小写字母。
[^a-z] 反向范围字符。匹配不在指定的范围内的任何字符。例如,"[^a-z]"匹配任何不在"a"到"z"范围内的任何字符。
\b 匹配一个字边界,即字与空格间的位置。例如,“er\b"匹配"never"中的"er”,但不匹配"verb"中的"er"。
\B 非字边界匹配。“er\B"匹配"verb"中的"er”,但不匹配"never"中的"er"。
\cx 匹配 x 指示的控制字符。例如,\cM 匹配 Control-M 或回车符。x 的值必须在 A-Z 或 a-z 之间。如果不是这样,则假定 c 就是"c"字符本身。
\d 数字字符匹配。等效于 [0-9]。
\D 非数字字符匹配。等效于 [^0-9]。
\f 换页符匹配。等效于 \x0c 和 \cL。
\n 换行符匹配。等效于 \x0a 和 \cJ。
\r 匹配一个回车符。等效于 \x0d 和 \cM。
\s 匹配任何空白字符,包括空格、制表符、换页符等。与 [ \f\n\r\t\v] 等效。
\S 匹配任何非空白字符。与 [^ \f\n\r\t\v] 等效。
\t 制表符匹配。与 \x09 和 \cI 等效。
\v 垂直制表符匹配。与 \x0b 和 \cK 等效。
\w 匹配任何字类字符,包括下划线。与"[A-Za-z0-9_]"等效。
\W 与任何非单词字符匹配。与"[^A-Za-z0-9_]"等效。
\xn 匹配 n,此处的 n 是一个十六进制转义码。十六进制转义码必须正好是两位数长。例如,"\x41"匹配"A"。"\x041"与"\x04"&"1"等效。允许在正则表达式中使用 ASCII 代码。
*num* 匹配 num,此处的 num 是一个正整数。到捕获匹配的反向引用。例如,"(.)\1"匹配两个连续的相同字符。
*n* 标识一个八进制转义码或反向引用。如果 *n* 前面至少有 n 个捕获子表达式,那么 n 是反向引用。否则,如果 n 是八进制数 (0-7),那么 n 是八进制转义码。
*nm* 标识一个八进制转义码或反向引用。如果 *nm* 前面至少有 nm 个捕获子表达式,那么 nm 是反向引用。如果 *nm* 前面至少有 n 个捕获,则 n 是反向引用,后面跟有字符 m。如果两种前面的情况都不存在,则 *nm* 匹配八进制值 nm,其中 nm 是八进制数字 (0-7)。
\nml n 是八进制数 (0-3),ml 是八进制数 (0-7) 时,匹配八进制转义码 nml
\un 匹配 n,其中 n 是以四位十六进制数表示的 Unicode 字符。例如,\u00A9 匹配版权符号 (©)。

9 动态路由(服务于发现路由规则)

因为业务系统的复杂性建议,不适用默认规则,而是人工配置的方式,实际业务中,一般不适用动态路由

10 过滤器

路由过滤器允许以某种方式修改传入的 HTTP 请求或传出的 HTTP 响应。路由过滤器的范围是特定的路由。Spring Cloud Gateway 包含许多内置的 GatewayFilter 工厂。

10.1 过滤器

这里就不展开说了,官方文档都有共计31个网关过滤器

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

10.2 全局过滤器

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

全局过滤器一共9个

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

10.3 自定义过滤器

10.3.1 自定义网关过滤器
10.3.2 自定义全局过滤器
@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;
    }
}
学新通
10.3.3 统一鉴权

11 cors配置

配置跨域解决方案

spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            allowedOrigins: "*" #配置允许的跨域域名
            allowedMethods: #配置允许跨域的方法
            - GET

12 配置访问日志

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

*它必须是 Java 系统属性,而不是 Spring Boot 属性

logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- 从高到地低 OFF 、 FATAL 、 ERROR 、 WARN 、 INFO 、 DEBUG 、 TRACE 、 ALL -->
<!-- 日志输出规则  根据当前ROOT 级别,日志输出时,级别高于root默认的级别时  会输出 -->
<!-- 以下每个配置的 filter 是过滤掉输出文件里面,会出现高级别文件,依然出现低级别的日志信息,通过filter 过滤只记录本级别的日志-->

<!-- 属性描述 scan:性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true scanPeriod:设置监测配置文件是否有修改的时间间隔,
如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。   debug:当此属性设置为true时,将打印出logback内部日志信息,
实时查看logback运行状态。默认值为false。 -->
<configuration scan="true" scanPeriod="60 seconds" debug="false">

    <!-- 定义日志文件 输入位置 -->
    <property name="log_dir" value="D:/logs" />
    <!-- 日志最大的历史 30天 -->
    <property name="maxHistory" value="15"/>
    <!-- ConsoleAppender 控制台输出日志 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <!-- 对日志进行格式化 -->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger -%msg%n</pattern>
        </encoder>
    </appender>

    <!-- INFO级别日志 appender -->
    <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 过滤器,只记录INFO级别的日志 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 按天回滚 daily -->
            <fileNamePattern>${log_dir}/%d{yyyy-MM-dd}/info-log.log
            </fileNamePattern>
            <!-- 日志最大的历史 60天 -->
            <maxHistory>${maxHistory}</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
        </encoder>
    </appender>


    <appender name="accessLog" class="ch.qos.logback.core.FileAppender">

        <file>${log_dir}/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>

    <!-- root级别   DEBUG -->
    <root level="INFO">
        <!-- 控制台输出 -->
        <appender-ref ref="accessLog" />
        <!-- 文件输出 -->
        <appender-ref ref="STDOUT" />
        <appender-ref ref="INFO" />

    </root>

</configuration>
学新通

13 开发指南

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

13.1 编写自定义路由谓词工厂

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

MyRoutePredicateFactory.java

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
    }

}
学新通

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

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

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
    }
学新通

13.3 自定义网关过滤器的命名规范

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

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

13.4 编写自定义全局过滤器

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

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

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

学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhggbfea
系列文章
更多 icon
同类精品
更多 icon
继续加载