springcloud gateway 知识库

文章目录

      • 1 gateway 知识图谱
      • 2 什么是spring cloud gateway
      • 3 什么是服务网关
      • 4 为什么要使用网关
      • 5 网关解决了什么问题
      • 6 常用网关解决方案
        • 6.1 nginx+lua
        • 6.2 kong
        • 6.3 Traefik
        • 6.4 spring cloud netflix zuul
        • 6.5 spring cloud Gateway
      • 7 nginx实现网关
        • 7.1 路由工作原理
      • 8 路由规则
        • 8.1 after
        • 8.2 Before
        • 8.3 Between
        • 8.4 [Cookie 路由谓词工厂](https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-cookie-route-predicate-factory)
        • 8.5 header
        • 8.6 HOST
        • 8.7 Method
        • 8.8 Path(常用)
        • 8.9 Query
        • 8.10 RemoteAddr
        • 8.11 Weight
        • 8.12 java正则表达式
      • 9 动态路由(服务于发现路由规则)
      • 10 过滤器
        • 10.1 过滤器
        • 10.2 全局过滤器
        • 10.3 自定义过滤器
          • 10.3.1 自定义网关过滤器
          • 10.3.2 自定义全局过滤器
          • 10.3.3 统一鉴权
      • 11 cors配置
      • 12 配置访问日志
      • 13 开发指南
        • 13.1 [编写自定义路由谓词工厂](https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#writing-custom-route-predicate-factories)
        • 13.2 [编写自定义网关过滤器工厂](https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#writing-custom-gatewayfilter-factories)
        • 13.3 自定义网关过滤器的命名规范
        • 13.4 编写自定义全局过滤器

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)。
\nmln 是八进制数 (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();
}

热门文章

暂无图片
编程学习 ·

Java输出数组的内容

Java输出数组的内容_一万个小时-CSDN博客_java打印数组内容1. 输出内容最常见的方式// List<String>类型的列表List<String> list new ArrayList<String>();list.add("First");list.add("Second");list.add("Third");list.ad…
暂无图片
编程学习 ·

母螳螂的“魅惑之术”

在它们对大蝗虫发起进攻的时候&#xff0c;我认认真真地观察了一次&#xff0c;因为它们突然像触电一样浑身痉挛起来&#xff0c;警觉地面对限前这个大家伙&#xff0c;然后放下自己优雅的身段和祈祷的双手&#xff0c;摆出了一个可怕的姿势。我被眼前的一幕吓到了&#xff0c;…
暂无图片
编程学习 ·

疯狂填词 mad_libs 第9章9.9.2

#win7 python3.7.0 import os,reos.chdir(d:\documents\program_language) file1open(.\疯狂填词_d9z9d2_r.txt) file2open(.\疯狂填词_d9z9d2_w.txt,w) words[ADJECTIVE,NOUN,VERB,NOUN] str1file1.read()#方法1 for word in words :word_replaceinput(fEnter a {word} :)str1…
暂无图片
编程学习 ·

HBASE 高可用

为了保证HBASE是高可用的,所依赖的HDFS和zookeeper也要是高可用的. 通过参数hbase.rootdir指定了连接到Hadoop的地址,mycluster表示为Hadoop的集群. HBASE本身的高可用很简单,只要在一个健康的集群其他节点通过命令 hbase-daemon.sh start master启动一个Hmaster进程,这个Hmast…
暂无图片
编程学习 ·

js事件操作语法

一、事件的绑定语法 语法形式1 事件监听 标签对象.addEventListener(click,function(){}); 语法形式2 on语法绑定 标签对象.onclick function(){} on语法是通过 等于赋值绑定的事件处理函数 , 等于赋值本质上执行的是覆盖赋值,后赋值的数据会覆盖之前存储的数据,也就是on…
暂无图片
编程学习 ·

Photoshop插件--晕影动态--选区--脚本开发--PS插件

文章目录1.插件界面2.关键代码2.1 选区2.2 动态晕影3.作者寄语PS是一款栅格图像编辑软件&#xff0c;具有许多强大的功能&#xff0c;本文演示如何通过脚本实现晕影动态和选区相关功能&#xff0c;展示从互联网收集而来的一个小插件&#xff0c;供大家学习交流&#xff0c;请勿…
暂无图片
编程学习 ·

vs LNK1104 无法打开文件“xxx.obj”

写在前面&#xff1a; 向大家推荐两本新书&#xff0c;《深度学习计算机视觉实战》和《学习OpenCV4&#xff1a;基于Python的算法实战》。 《深度学习计算机视觉实战》讲了计算机视觉理论基础&#xff0c;讲了案例项目&#xff0c;讲了模型部署&#xff0c;这些项目学会之后可以…
暂无图片
编程学习 ·

工业元宇宙的定义与实施路线图

工业元宇宙的定义与实施路线图 李正海 1 工业元宇宙 给大家做一个关于工业元宇宙的定义。对于工业&#xff0c;从设计的角度来讲&#xff0c;现在的设计人员已经做到了普遍的三维设计&#xff0c;但是进入元宇宙时代&#xff0c;就不仅仅只是三维设计了&#xff0c;我们的目…
暂无图片
编程学习 ·

【leectode 2022.1.15】完成一半题目

有 N 位扣友参加了微软与力扣举办了「以扣会友」线下活动。主办方提供了 2*N 道题目&#xff0c;整型数组 questions 中每个数字对应了每道题目所涉及的知识点类型。 若每位扣友选择不同的一题&#xff0c;请返回被选的 N 道题目至少包含多少种知识点类型。 示例 1&#xff1a…
暂无图片
编程学习 ·

js 面试题总结

一、js原型与原型链 1. prototype 每个函数都有一个prototype属性&#xff0c;被称为显示原型 2._ _proto_ _ 每个实例对象都会有_ _proto_ _属性,其被称为隐式原型 每一个实例对象的隐式原型_ _proto_ _属性指向自身构造函数的显式原型prototype 3. constructor 每个prot…
暂无图片
编程学习 ·

java练习代码

打印自定义行数的空心菱形练习代码如下 import java.util.Scanner; public class daYinLengXing{public static void main(String[] args) {System.out.println("请输入行数");Scanner myScanner new Scanner(System.in);int g myScanner.nextInt();int num g%2;//…
暂无图片
编程学习 ·

RocketMQ-什么是死信队列?怎么解决

目录 什么是死信队列 死信队列的特征 死信消息的处理 什么是死信队列 当一条消息初次消费失败&#xff0c;消息队列会自动进行消费重试&#xff1b;达到最大重试次数后&#xff0c;若消费依然失败&#xff0c;则表明消费者在正常情况下无法正确地消费该消息&#xff0c;此时…
暂无图片
编程学习 ·

项目 cg day04

第4章 lua、Canal实现广告缓存 学习目标 Lua介绍 Lua语法 输出、变量定义、数据类型、流程控制(if..)、循环操作、函数、表(数组)、模块OpenResty介绍(理解配置) 封装了Nginx&#xff0c;并且提供了Lua扩展&#xff0c;大大提升了Nginx对并发处理的能&#xff0c;10K-1000K Lu…
暂无图片
编程学习 ·

输出三角形

#include <stdio.h> int main() { int i,j; for(i0;i<5;i) { for(j0;j<i;j) { printf("*"); } printf("\n"); } }
暂无图片
编程学习 ·

stm32的BOOTLOADER学习1

序言 最近计划学习stm32的BOOTLOADER学习,把学习过程记录下来 因为现在网上STM32C8T6还是比较贵的,根据我的需求flash空间小一些也可以,所以我决定使用stm32c6t6.这个芯片的空间是32kb的。 #熟悉芯片内部的空间地址 1、flash ROM&#xff1a; 大小32KB&#xff0c;范围&#xf…
暂无图片
编程学习 ·

通过awk和shell来限制IP多次访问之学不会你打死我

学不会你打死我 今天我们用shell脚本&#xff0c;awk工具来分析日志来判断是否存在扫描器来进行破解网站密码——限制访问次数过多的IP地址&#xff0c;通过Iptables来进行限制。代码在末尾 首先我们要先查看日志的格式&#xff0c;分析出我们需要筛选的内容&#xff0c;日志…
暂无图片
编程学习 ·

Python - 如何像程序员一样思考

在为计算机编写程序之前&#xff0c;您必须学会如何像程序员一样思考。学习像程序员一样思考对任何学生都很有价值。以下步骤可帮助任何人学习编码并了解计算机科学的价值——即使他们不打算成为计算机科学家。 顾名思义&#xff0c;Python经常被想要学习编程的人用作第一语言…
暂无图片
编程学习 ·

蓝桥杯python-数字三角形

问题描述 虽然我前后用了三种做法&#xff0c;但是我发现只有“优化思路_1”可以通过蓝桥杯官网中的测评&#xff0c;但是如果用c/c的话&#xff0c;每个都通得过&#xff0c;足以可见python的效率之低&#xff08;但耐不住人家好用啊&#xff08;哭笑&#xff09;&#xff09…