Spring Cloud Gateway 网关

一. 什么是网关(Gateway)

网关就是一个网络连接到另一个网络的关口。

在同一个项目或某一层级中,存在相似或重复的东西,我们就可以将这些相似重复的内容统一提取出来,向前或向后抽象成单独的一层。这个抽象的过程就是网关。

和AOP切面类似,但有区别。AOP切面是独立于单个项目的,也就是每个项目都需要自己实现AOP逻辑,并引入相应的AOP切面包。而网关是一种更加通用的方案,可以统一处理所有情况。

根据上图所示,最传统的统计接口调用次数的方案是每个接口被调用时都自己去统计一次,计数器加1。

在引入AOP切面后,将统计次数作为一个切面,每个接口被调用后,接口再去调用统计次数的方法。

网关则是作为最前面的一层,用户直接去调用网关,由网关根据用户请求的地址,找到对应的接口,然后调用它,同时调用后次数加1。

对于用户来说,无需关心接口到底是哪个项目的或者是谁开发的,只要知道自己需要什么功能,然后调用对应的网关即可。对开发者来说,也无需统计调用的次数,只要把自己的接口接入到网关中,让网关能找到并调用即可,网关会自己统计调用次数。

综上,网关可以理解成火车站的检票口,通过网关检票后,再去找到对应的车厢。

二. 网关的作用

统一进行一些操作或处理一些问题。

1.路由

起到转发的作用,比如有接口A和B,网关会去记录这些信息,根据用户访问的地址和参数,转发请求到对应的接口。可以理解为转发的条件。

/a => 接口A     /b => 接口B

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

这里就是说如果时间在2017年1月20后之后,都会去访问https://example.org 这个网址。

同理,还有Before、Between等。

参考文档:Spring Cloud Gatewayicon-default.png?t=N7T8https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-after-route-predicate-factory

2.负载均衡

在路由的基础上,根据条件随机转发到其中某个机器上。

/c => 服务A/集群A。

3.统一处理跨域

网关统一处理跨越,不用在每个项目里单独处理。

参考文档:Spring Cloud Gatewayicon-default.png?t=N7T8https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#global-cors-configuration

4.发布控制

灰度发布,比如上线了新接口,先给新接口分配20%的流量,旧接口80%,之后再逐渐调整比重。

参考文档:Spring Cloud Gatewayicon-default.png?t=N7T8https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-weight-route-predicate-factory

5.流量染色

给请求(流量)添加一些标识,一般是设置请求头,或者添加新的请求头。

什么是流量染色?假设现在有个用户想要访问某个接口,但我希望用户不能绕过网关去访问,那么应该如何防止绕过网关呢?

可以给通过网关访问的用户请求增加一个标识,比如添加一个请求头source=gateway,所有经过网关的请求都会有这个请求头,接口就可以根据这个请求头去判断,如果没有的话,直接拒绝掉,说明不是通过网关的请求。这就是流量染色的一种应用。

另一个常见的应用是用于排查用户调用接口时出现的问题。为每个用户的每次调用都打上一个唯一的traceid,当出现问题时,通过这个id,下游服务可以快速追踪到具体的请求,从而逐层排查问题。

参考文档:Spring Cloud Gatewayicon-default.png?t=N7T8https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-addrequestheader-gatewayfilter-factory

 6.统一接口保护

  • 限制请求
  • 信息脱敏
  • 降级(熔断)
  • 限流
  • 超时时间
  • 重试(业务保护)

7.统一业务处理

把每个项目中都要做的通用逻辑放到上一层(网关),进行统一处理,比如接口调用次数统计。

8.统一鉴权

判断用户是否有权限进行操作,无论访问什么接口,都统一去判断权限,不用重复写。

9.访问控制

黑白名单,比如DDos IP。

10.统一日志

统一的请求、响应信息记录。

11.统一文档

将下游项目的文档进行聚合,在一个页面统一查看。类似于语雀的目录。

三. 网关分类

  • 全局网关(接入层网关):实现负载均衡、请求日志等,不和业务逻辑绑定。
  • 业务网关(微服务网关):有一些业务逻辑,作用是将请求转发到不同的业务/项目/接口/服务等。

全局网关通常层级较高,可能覆盖多个项目或微服务,主要用于请求的负载均衡,如Nginx、kong等。Nginx可以部署前端或后端,还能提供文件访问服务等多种功能,比较灵活,但操作不如Spring Cloud Gateway方便。

业务网关,特别是基于Spring Boot技术栈的项目,比较推荐使用Spring Cloud Gateway,性能较高,并允许使用Java编写逻辑,容易上手。Nginx或kong需要学习额外的语言和编程。

四.核心概念和逻辑

1.核心概念:

  • 路由(Route):根据什么条件,转发请求到哪里。
  • 断言(Predicate):一组规则、条件,用来确定如何转发路由。
  • 过滤器(Filter):对请求进行一系列的处理,比如添加请求头、添加请求参数等。

2.实现逻辑:

  1. 客户端发起请求。
  2. Handler Mapping:根据断言,去将请求转发到对应的路由。
  3. Web Handler:处理请求(一层层经过过滤器)。
  4. 实际调用服务

Spring Cloud Gateway的两种配置方式:

  • 配置式:更方便、规范,比较推荐。有简化版、全称版。就是在application.yml中写配置,也就是在创建项目时,将它作为一个依赖导入。

  • 编程式:更灵活,但相对麻烦。

如上述这段官方提供的代码,就是创建了一个路由器,它的作用是当用户访问某个网址时,将其重定向到指定的网址。

spring:cloud:gateway:routes:- id: after_routeuri: https://example.orgpredicates:- Cookie = mycookie, mycookievalue

上述是一个简化版的配置方式。

spring.cloud.gateway.routes:这是配置路由的属性。

- id:after_route:这是路由的唯一标识符,用于区分不同的路由。

uri:https://example.org:这是路由将请求转发到目标URI,即请求经过此路由后会被转发到https://example.org这个地址。

predicates:这个就是断言的配置属性,用于定义请求是否满足路由条件。

- Cookie = mycookie, mycookievalue:这是一个断言条件,指定了请求必须具有名为mycookie的Cookie,且其值必须为mycookievalue,才能匹配这个路由。

通过这个配置,当满足请求带有mycookie的Cookie且值为mycookievalue时,请求会被转发到https://example.org。

spring:cloud:gateway:routes:- id: after_routeuri: https://example.orgpredicates:- name: Cookieargs:name: mycookieregexp: mycookievalue

上述是一个复杂版的配置方式,前面都没变,在predicates处设置的更加详细了。

- name: Cookie :断言条件,指定使用Cookie作为断言类型来检查请求。

args: 断言条件的参数配置。

name: mycookie:匹配名为mycookie的Cookie。

regexp: mycookievalue:使用正则表达式匹配mycookie的值是否为mycookievalue。

注意,predicates使用了复数形式,说明可以加多个规则(“-”代表列表)。

通过阅读官方文档后,断言(Predicates)的作用大概有:

  1. After 在xx时间之后
  2. Before 在xx时间之前
  3. Between 在xx时间之间
  4. 请求类别
  5. 请求头(包含Cookie)
  6. 查询参数
  7. 客户端地址
  8. 权重(可用来实现灰度测试) 

过滤器(Filter)的作用大概有:

对请求头、响应头、请求参数的增删改查,可以这样理解。

  1. 添加请求头
  2. 添加请求参数
  3. 添加响应头
  4. 降级
  5. 限流
  6. 重试

五. API项目中的网关

1.用到的网关特性

  • 路由:转发请求到模拟接口项目
  • 统一鉴权:使用accessKey和secretKey
  • 统一业务处理:每次请求调用后,接口调用次数加1
  • 访问控制:黑白名单
  • 流量染色:记录请求是否来自网关
  • 统一日志:记录每次的请求和响应日志

2.业务逻辑

  1. 用户发送请求到API网关
  2. 生成请求日志
  3. 黑白名单限制
  4. 用户鉴权(判断ak、sk是否合规)
  5. 判断请求的模拟接口是否存在
  6. 请求转发,调用模拟接口(先实现,相对核心,先能调通接口,在说后续的业务)
  7. 生成响应日志
  8. 调用成功,接口调用次数加1
  9. 调用失败,返回一个错误码
  • 请求的转发使用到了前缀匹配断言。

假设提供的接口地址都是以:http://localhost:8123/api/开头,并且都有一个共同的路径前缀/api。那么可以配置一个前缀匹配断言,使得所有路径前缀为/api/**的请求都被匹配到,并转发到对应的路径:http://localhost:8123/api/**。如果有个请求网关的地址为:http://locaohost:8090/api/name/get?name = khr,可以使用前缀匹配断言,将这个请求转发到http://locaohost:8123/api/name/get?name = khr。这样就可以统一处理所有以/api开头的请求,并转发到后端服务的相应路径上。

  • 针对所有路由都执行相同的逻辑,需要使用全局过滤器(GlobalFilter)。

Ordered用来实现过滤器的执行顺序。因为将请求转发到真实接口前会经过多个过滤器,所以这里可以编排这些过滤器,确定哪个过滤器先拦截,哪个后拦截。实现自定义的处理顺序。

其中两个参数exchange(路由交换机)和chain(责任链模式)。

  1. exchange:所有的请求的信息、响应的信息、响应体、请求体都能从这里拿到。
  2. chain:过滤器的执行是从上到下顺序执行,形成一个链条。所以用一个chain,如果当前过滤器对请求进行了过滤后发现可以放行,就要调用责任链中的next方法,相当于直接找到了下一个过滤器,这里称为了chain.filter,原理相同,就是找到下一个过滤器。

有了全局过滤器,就可以将之前的业务逻辑全都定义在这里面。

  •  业务逻辑的实现

打印请求日志用到了exchange.getRequest()方法,看能拿到什么参数,然后打印出来即可。

黑白名单。通常用白名单来指定可以访问的IP,相对会更安全。不包含指定的地址,就会拒绝。拒绝的实现,是先通过exchange获取到响应对象,从而控制该响应,然后设置状态码为403(禁止访问),拦截掉即可。

用户鉴权的实现和之前在模拟接口中进行的鉴权相同,直接复制之前的判断逻辑。

测试整个流程时,发现到了第5步调用模拟接口时,程序并没有调用,反而是跳到了下面的步骤,打印响应日志,然后return filter,之后才去调用模拟接口。

问题:

预期是等模拟接口调用完成后,才记录相应日志、统计调用次数。但现在的情况是chain.filter方法立刻返回了,没有真正触发,而是继续往下执行,直到filter过滤器return后才调用模拟接口。

原因是chain.filter是个异步操作,也就是说它不需要等待其它调用结束就能立即返回。

从这个模型中也能观察到,Spring Cloud Gateway的处理逻辑是等待所有的过滤器都执行完毕后,才会继续向下走,直到最终调用被代理的服务,也就是模拟接口。

但现在我们希望在调用完远程接口后,再输出响应日志,由于异步操作的原因,导致顺序冲突。

解决方案:

用一个自定义响应处理的装饰器。利用response装饰者,增强原有response的处理能力。

装饰者设计模式:也就是给原本的方法外面再包一层,添加额外的功能。在这个装饰层中加入自己的逻辑,让这个方法按照预期的方式执行。

所以即使这里chain.filter是异步操作,但执行到这个方法时,装饰器也能做额外的事情。也就是利用装饰器增强了原有方法的处理能力。

网上找到Spring Cloud Gateway打印请求响应日志,对应的方法代码直接复制进去即可。 

在这个项目中,装饰器最终的目的是先去执行调用模拟接口方法,然后得到返回值。data中就是真实的响应结果,data是从content中拿到的返回值。即返回值的获取是通过content(原本模拟接口返回的数据)。

然后将调用模拟接口之后的步骤全都放到这个方法中去执行即可。

目前实现了部分的业务逻辑,还有一些需要操作数据库的包,或者调用之前写过的代码。比如在用户鉴权时要从数据库中去查aK是否已经分配给用户、从数据库中查调用接口是否存在以及调用从成功后接口次数加一的方法。

但网关项目比较纯净,没有涉及操作数据库的包,并且需要调用之前写过的方法代码,如果通过复制粘贴的方式,开始会相对容易,但随着次数的增多以及未来的维护修改,会变得很繁琐。因此,理想情况下是能够操作数据库并直接请求到后端项目中的方法代码(invokeCount)。所以可以使用远程过程调用(RPC)

3.RPC

设想一个场景:在项目A中编写了一个非常有用高效的函数,想在项目B中也使用。但两个项目独立运行,不共享内存,也不在同一个进程。

如何调用其它项目的方法?

  • 复制代码、依赖和环境。
  • HTTP请求,即提供一个接口供其它项目调用。
  • RPC。
  • 公共代码打个jar包,其它项目去引用。(客户端SDK)

HTTP请求如何调用?

  • 提供方开发一个接口(地址、请求方法、参数、返回值)。
  • 调用方使用HTTP Client之类的代码包去发送HTTP请求。

RPC如何调用?

  • 像调用本地方法一样调用远程方法。

HTTP请求与RPC调用的区别:

  • RPC相比HTTP请求对开发者更加透明,减少了很多沟通的成本。例如之前开发的Client-SDK项目,客户端对象使用到了HTTPUtil Hutool工具类的包发送请求,调用方需要编写特定的代码来发送请求,然后处理返回值,可能还需要封装参数的映射关系等;而RPC可以直接像调用本地方法那样,传参数给方法即可使用,一行代码即可实现方法调用。

  • RPC向远程服务器发送请求时,未必使用到了HTTP协议,可能是其它协议,比如TCP/IP,性能更高。

RPC调用模型:

4.RPC的实现——Dubbo框架

Dubbo是国内主流的RPC实现框架,有两种使用方式:

  • Spring Boot代码(注解+编程):写Java接口,提供者和调用方都去引用这个接口。
  • IDL(接口调用语言):创建一个公共的接口定义文件,提供者和调用方都去读取这个文件。跨语言,所有框架都认识。

Dubbo底层采用Triple协议。Triple协议 | Apache Dubbo

Dubbo框架中内嵌了Zookeeper注册中心,也支持其它存储,比如Nacos。

Dubbo框架在API项目中的整合应用;

  • backend作为服务提供者,提供3个方法:
  1. 从数据库中查aK是否被分配给了用户。
  2. 从数据库在查模拟接口是否存在,以及请求方法是否匹配。
  3. 调用成功,接口次数+1,invokeCount方法。
  • gateway项目作为调用者,调用这3个方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/334861.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AURIX TC3xx单片机介绍-启动过程介绍3

如下的内容是英文为主,对于TC3xx芯片启动原理不清楚的,可以给我留言,我来解答你们的问题! 3.2.1 Reset类型识别 Reset类型的识别是用来判断上次的复位是Application Reset还是System Reset还是CPU0 Reset。基于复位的原因,启动软件会运行不同的分支逻辑。复位原因可以通…

常用目标检测预训练模型大小及准确度比较

目标检测是计算机视觉领域中的一项重要任务,旨在检测和定位图像或者视频中的目标对象。当人类观看图像或视频时,我们可以在瞬间识别和定位感兴趣的对象。目标检测的目标是使用计算机复制这种智能。 近年来,目标检测网络的发展日益成熟&#…

Java GC问题排查的一些个人总结和问题复盘

个人博客 Java GC问题排查的一些个人总结和问题复盘 | iwts’s blog 是否存在GC问题判断指标 有的比较明显,比如发布上线后内存直接就起飞了,这种也是比较好排查的,也是最多的。如果单纯从优化角度,看当前应用是否需要优化&…

【PB案例学习笔记】-11动画显示窗口

写在前面 这是PB案例学习笔记系列文章的第11篇,该系列文章适合具有一定PB基础的读者。 通过一个个由浅入深的编程实战案例学习,提高编程技巧,以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码,小凡都上传到了gite…

IDEA2024创建maven项目

1、new->project 2、创建后展示 3、生成resources文件夹 4、测试--编写一个hello文件

5.28学习总结

java复习总结 hashcode()和equals() hashcode():在Object里这个方法是通过返回地址的整数值来生成哈希值。 equals():在Object里这个方法是通过比较他们的内存地址来确定两个对象是否相同。 运行效率:hashcode的时间复杂度为O(1)(因为只要计算一次哈…

养老院管理系统基于springboot的养老院管理系统java项目

文章目录 养老院管理系统一、项目演示二、项目介绍三、系统部分功能截图四、部分代码展示五、底部获取项目源码(9.9¥带走) 养老院管理系统 一、项目演示 养老院管理系统 二、项目介绍 基于springboot的养老院管理系统 角色:超级…

Python-3.12.0文档解读-内置函数ord()详细说明+记忆策略+常用场景+巧妙用法+综合技巧

一个认为一切根源都是“自己不够强”的INTJ 个人主页:用哲学编程-CSDN博客专栏:每日一题——举一反三Python编程学习Python内置函数 Python-3.12.0文档解读 目录 详细说明 概述 语法 参数 返回值 示例 注意事项 应用场景 记忆策略 常用场景…

网易面试:手撕定时器

概述: 本文使用STL容器-set以及Linux提供的timerfd来实现定时器组件 所谓定时器就是管理大量定时任务,使其能按照超时时间有序地被执行 需求分析: 1.数据结构的选择:存储定时任务 2.驱动方式:如何选择一个任务并执…

微火问答:全域外卖和本地生活服务是同个项目吗?

当前,本地生活赛道火爆程度不断升级,作为其主要板块之一的团购外卖也持续迸发出新的活力。而全域运营的出现无疑是给团购外卖这把正在熊熊燃烧的烈火,又添了一把新柴! 所谓全域运营,简单来说,就是指所有领…

xjar加密springboot的jar包,并编译为执行程序

场景:当前项目需要进行jar包部署在windows环境和linux环境,并要求使用xjar加密。 1. xjar加密 源码程序自行搜索,这里只介绍加密及运行,运行加密程序,指定jar包,输入密码 2. 加密后的目录 3. go程序编译 …

HCIP-Datacom-ARST自选题库__BGP/MPLS IP VPN简答【3道题】

1.在BGP/MPLSIPVPN场景中,如果PE设备收到到达同一目的网络的多条路由时,将按照定的顺序选择最优路由。请将以下内容按照比较顺序进行排序。 2.在如图所示的BGP/MPLSIP VPN网络中,管理员准备通过Hub-Spoke组网实现H站点对VPM流量的集中管控&am…

HNU-人工智能-作业3

人工智能-作业3 计科210X 甘晴void 202108010XXX 1.贝叶斯网络 根据图所给出的贝叶斯网络,其中:P(A)0.5,P(B|A)1, P(B|A)0.5, P(C|A)1, P(C|A)0.5,P(D|BC)1,P(D|B, C)0.5&#xff…

如何将天猫内容保存为PDF格式?详细步骤与实战解析

新书上架~👇全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我👆,收藏下次不迷路┗|`O′|┛ 嗷~~ 目录 一、引言:保存天猫内容的重要性 二、环境准备与工具安装 1. 安装必要的Python包…

宝塔部署Java+Vue前后端分离项目

1. 服务器 服务器选择Linux的CentOS7的版本 2. 宝塔Linux面板 2.1 百度搜索宝塔 2.2 进去之后点击立即免费安装 2.3 选择Linux在线安装,输入服务器信息进行安装(也可以选择其他方式) 安装完成之后会弹一个宝塔的应用面板,并附带有登录名称和密码&…

Linux快速定位日志 排查bug技巧和常用命令

1. 快速根据关键字定位错误信息 grep 在 Linux 系统中,可以使用 grep 命令来查找日志文件中包含特定关键字的行。假设你的日志文件路径为 /var/log/myapp.log,你想要查找包含关键字 "abc" 的日志内容,可以按照以下步骤操作&#…

【机器学习聚类算法实战-5】机器学习聚类算法之DBSCAN聚类、K均值聚类算法、分层聚类和不同度量的聚集聚类实例分析

🎩 欢迎来到技术探索的奇幻世界👨‍💻 📜 个人主页:一伦明悦-CSDN博客 ✍🏻 作者简介: C软件开发、Python机器学习爱好者 🗣️ 互动与支持:💬评论 &…

【微服务】安装docker以及可视化界面

1.配置yum下载源为aliyun源 yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo2.下载docker不加版本号默认为最新版本 yum install -y docker-ce3.启动以及开机自启 #启动docker命令 systemctl start docker #设置开机自启命令…

软件功能测试的类型和流程分享

在现代社会,软件已经成为人们生活中不可或缺的一部分,而在软件的开发过程中,功能测试是不可或缺的环节。软件功能测试指的是对软件系统的功能进行检查和验证,以确保软件在各种情况下能够正常运行,并且能够按照用户需求…

【CTF Web】CTFShow web5 Writeup(SQL注入+PHP+位运算)

web5 1 阿呆被老板狂骂一通&#xff0c;决定改掉自己大意的毛病&#xff0c;痛下杀手&#xff0c;修补漏洞。 解法 注意到&#xff1a; <!-- flag in id 1000 -->拦截很多种字符&#xff0c;连 select 也不给用了。 if(preg_match("/\|\"|or|\||\-|\\\|\/|\…