SpringCloud微服务-统一网关Gateway

news2024/9/21 14:54:40

统一网关Gateway

文章目录

  • 统一网关Gateway
    • 1、为什么需要网关?
    • 2、gateway快速入门
    • 3、路由断言工厂Route Predicate Factory
    • 4、过滤器工厂-路由过滤器GatewayFilter
    • 5、全局过滤器**GlobalFilter**
    • 6、各种过滤器的执行顺序
    • 7、跨域问题的解决

1、为什么需要网关?

网关与各个服务之间的关系:

image-20240229110119243

网关功能:

  • 身份认证和权限校验

  • 服务路由、负载均衡

  • 请求限流

在SpringCloud中网关的实现包括两种:

  • gateway

  • zuul

Zuul是基于Servlet的实现,属于阻塞式编程。而SpringCloud Gateway则是基于Spring5中提供的WebFlux,属于响应式编程的实现,具备更好的性能。

2、gateway快速入门

搭建网关gateway服务:

搭建网关服务的步骤:

  1. 创建新的module,引入SpringCloudGateway的依赖和nacos的服务发现依赖:
<!--   网关依赖     -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

<!--   nacos的服务发现依赖     -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
  1. 编写module的启动类

    @SpringBootApplication
    public class GatewayApplication {
        public static void main(String[] args) {
            SpringApplication.run(GatewayApplication.class, args);
        }
    }
    
  2. 编写路由配置及nacos地址

    server:
      port: 10010
    spring:
      application:
        name: gateway #网关名称
      cloud:
        nacos:
          server-addr: localhost:8848 #nacos的地址
        gateway:
          routes: #网关路由设置
            - id: user-service #路由id,自定义,唯一即可
            # uri: http://127.0.0.1:8081 #路由的目标地址,http是固定地址
              uri: lb://userservice #路由的目标地址,lb就是负载均衡,后面是服务的名称
              predicates: #路由断言,也就是判断请求是否符合路由规则的条件
                - Path=/user/**  #这个是按照路由匹配,只要以/user/开头就符合要求
            - id: order-service
              uri: lb://orderservice
              predicates: #路由断言
                - Path=/order/**
    

从网关访问数据:

image-20240229113154532

image-20240229113207857

网关服务流程图:

image-20240229113341770

3、路由断言工厂Route Predicate Factory

网关路由可以配置的内容包括:

  • 路由id:路由唯一标示

  • uri:路由目的地,支持lb和http两种

  • predicates:路由断言,判断请求是否符合要求,符合则转发到路由目的地

  • filters:路由过滤器,处理请求或响应

我们在配置文件中写的断言规则只是字符串,这些字符串会被Predicate Factory读取并处理,转变为路由判断的条件

例如Path=/user/**是按照路径匹配,这个规则是由org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory类来处理的像这样的断言工厂在SpringCloudGateway还有十几个。

Spring提供了11种基本的Predicate工厂:

名称说明示例
After是某个时间点后的请求- After=2037-01-20T17:42:47.789-07:00[America/Denver]
Before是某个时间点之前的请求- Before=2031-04-13T15:14:47.433+08:00[Asia/Shanghai]
Between是某两个时间点之前的请求- Between=2037-01-20T17:42:47.789-07:00[America/Denver], 2037-01-21T17:42:47.789-07:00[America/Denver]
Cookie请求必须包含某些cookie- Cookie=chocolate, ch.p
Header请求必须包含某些header- Header=X-Request-Id, \d+
Host请求必须是访问某个host(域名)- Host=.somehost.org,.anotherhost.org
Method请求方式必须是指定方式- Method=GET,POST
Path请求路径必须符合指定规则- Path=/red/{segment},/blue/**
Query请求参数必须包含指定参数- Query=name, Jack或者- Query=name
RemoteAddr请求者的ip必须是指定范围- RemoteAddr=192.168.1.1/24
Weight权重处理

可以查看官方文档来进一步学习或者使用:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories

image-20240229152115249

4、过滤器工厂-路由过滤器GatewayFilter

GatewayFilter是网关中提供的一种过滤器,可以对进入网关的请求和微服务返回的响应做处理:

image-20240229152738630

Spring提供了31种不同的路由过滤器工厂。例如:

名称说明
AddRequestHeader给当前请求添加一个请求头
RemoveRequestHeader移除请求中的一个请求头
AddResponseHeader给响应结果中添加一个响应头
RemoveResponseHeader从响应结果中移除有一个响应头
RequestRateLimiter限制请求的流量

同样参考官方文档进行学习和参考:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gatewayfilter-factories

image-20240229153304967

示例:假如我们需要对某个服务添加请求头(路由过滤器中的一个工厂),添加配置:(最后一行,参考官方文档即可)

spring:
application:
 name: gateway #网关名称
cloud:
 nacos:
   server-addr: localhost:8848 #nacos的地址
 gateway:
   routes: #网关路由设置
        - id: user-service #路由id,自定义,唯一即可
        # uri: http://127.0.0.1:8081 #路由的目标地址,http是固定地址
          uri: lb://userservice #路由的目标地址,lb就是负载均衡,后面是服务的名称
          predicates: #路由断言,也就是判断请求是否符合路由规则的条件
            - Path=/user/**  #这个是按照路由匹配,只要以/user/开头就符合要求
          filters:  
            - AddRequestHeader=hello,Mannor Redaz id the greatest man!

修改接口代码:

@GetMapping("/{id}")
public User queryById(@PathVariable("id") Long id, @RequestHeader(value = "hello", required = false) String hello) {
 //@RequestHeader(value = "hello", required = false) String hello
 //上述代码含义就是获取名为Hello的参数,并且这个参数不是必须的
 System.out.println("hello:" + hello);
 return userService.queryById(id);
}

测试:从网关的端口进入http://localhost:10010/user/1

image-20240229154921406

但是有一个问题就是,当我们需要向多个服务添加相同的过滤工厂的时候,每一个过滤条件都加在每一个服务配置后面就显得很不优雅,例如:image-20240229155256052

所以有个默认路由的概念:

image-20240229160110141

这样就减少了代码的复写,增强可读性。

5、全局过滤器GlobalFilter

全局过滤器的作用也是处理一切进入网关的请求和微服务响应,与上一节的GatewayFilter的作用一样。

区别在于GatewayFilter通过配置定义,处理逻辑是固定的。而GlobalFilter的逻辑需要自己写代码实现

定义方式是实现GlobalFilter接口

代码实现:登录认证逻辑

package cn.pzhu.gateway;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * 权限认证过滤器(全局过滤器的实现)
 * <p>
 * 需求:定义全局过滤器,拦截请求,判断请求的参数是否满足下面条件:
 * 		1.参数中是否有authorization,
 * 		2.authorization参数值是否为admin
 * 		3.如果同时满足则放行,否则拦截
 */
@Order(-1) //定义优先级,过滤器优先级越高,里面的参数值越低,可以看源码学习(也可以实现Ordered接口实现不再赘述)
@Component //将AuthorizeFilter注入到spring作为一个bean
public class AuthorizeFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //1.获取请求参数
        ServerHttpRequest request = exchange.getRequest();
        MultiValueMap<String, String> params = request.getQueryParams();
        //2.获取参数中的authorization参数
        String auth = params.getFirst("authorization"); //设置需要过滤的参数
        //3.判断参数值是否等于admin
        if ("admin".equals(auth)) {
            //4.是,放行
            return chain.filter(exchange);
        }
        //5. 否,拦截 (为了让用户体验到返回的结果,这里就设置响应码401,即未登录状态图码)
        //5.1 设置状态码
        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); //UNAUTHORIZED是401状态码的枚举类型
        //5.2 拦截请求
        return exchange.getResponse().setComplete(); //设置指示完成或错误
    }
}

测试:

image-20240229162830651

image-20240229163045659

6、各种过滤器的执行顺序

请求进入网关会碰到三类过滤器:当前路由的过滤器DefaultFilterGlobalFilter

请求路由后,会将当前路由过滤器和DefaultFilter、GlobalFilter,合并到一个过滤器链(集合)中,排序后依次执行每个过滤器

示意图:

image-20240229164852614

  • 每一个过滤器都必须指定一个int类型的order值,order值越小,优先级越高,执行顺序越靠前

  • GlobalFilter通过实现Ordered接口,或者添加@Order注解来指定order值,由我们自己指定

  • 路由过滤器defaultFilter的order由Spring指定,默认是按照声明顺序从1递增。

  • 当过滤器的order值一样时,会按照 defaultFilter > 路由过滤器 > GlobalFilter的顺序执行。

以上排序原因可以查看源码来推断:

**org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#getFilters()**方法是先加载defaultFilters,然后再加载某个route的filters,然后合并。

image-20240229170120054

org.springframework.cloud.gateway.handler.FilteringWebHandler#handle()方法会加载全局过滤器,与前面的过滤器合并后根据order排序,组织过滤器链

image-20240229170341066

7、跨域问题的解决

什么是跨域?

跨域:域名不一致就是跨域,主要包括:

  • 域名不同: www.taobao.com 和 www.taobao.org 和 www.jd.com 和 miaosha.jd.com

  • 域名相同,端口不同:localhost:8080和localhost8081

跨域问题:浏览器禁止请求的发起者与服务端发生跨域ajax请求,请求被浏览器拦截的问题

解决方案:CORS

跨源资源共享(CORS,或通俗地译为跨域资源共享)是一种基于 HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其他源(域、协议或端口),使得浏览器允许这些源访问加载自己的资源。跨源资源共享还通过一种机制来检查服务器是否会允许要发送的真实请求,该机制通过浏览器发起一个到服务器托管的跨源资源的“预检”请求。在预检中,浏览器发送的头中标示有 HTTP 方法和真实请求中会用到的头。内容来自:mdn文档解释

前端发起一个跨域请求之后:

image-20240229172545567

网关处理跨域采用的同样是CORS方案,并且只需要简单配置即可实现:

spring:
  cloud:
    gateway:
      globalcors: # 全局的跨域处理
      add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题(浏览器询问服务器是否运行跨域)
      corsConfigurations:
        '[/**]':  #拦截那些请求,/**表示拦截所以请求
          allowedOrigins: # 允许哪些网站的跨域请求
            - "http://localhost:8090"
            - "http://www.leyou.com"
          allowedMethods: # 允许的跨域ajax的请求方式
            - "GET"
            - "POST"
            - "DELETE"
            - "PUT"
            - "OPTIONS"
          allowedHeaders: "*" # 允许在请求中携带的头信息
          allowCredentials: true # 是否允许携带cookie
          maxAge: 360000 # 这次跨域检测的有效期,在这个时间内不用再次检测是否允许跨域

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JAVA 反序列化之 Apache Commons Collections 反序列化漏洞分析

Apache Commons Collections 反序列化漏洞是 2015 年影响重大的漏洞之一&#xff0c;同时也开启了各类 java 反序列漏洞的大门&#xff0c;这几年大量各类 java 反序列化漏洞不断出现。java 反序列化漏洞基本一出必高危&#xff0c;风险程度极大&#xff0c;最近研究了一些反序…

找工作的小伙伴有福利了

简历模块 资料说明 ✅内容&#xff1a;300多套简历模块&#xff0c;包含单页简历150套、双页简历15套、三页简历25套、四页简历50套、表格简历15套、自荐信20 套&#xff0c;封面简历、英文简历150 ✅文件格式&#xff1a;word ✅ 文件大小&#xff1a;449MB 资料文件展示 资…

MySQL(基础篇)——多表查询

一.多表关系 一对多(多对一) 多对多一对一 1.一对多(多对一) a.案例&#xff1a;部门与员工的关系 b.关系&#xff1a;一个部门对应多个员工&#xff0c;一个员工对应一个部门 c.实现&#xff1a;在多的一方建立外键&#xff0c;指向一的一方的主键 2.多对多 a.案…

notch 滤波器设计

notch 滤波器是一种用于去除特定频率成分的滤波器&#xff0c;通常用于消除信号中的特定频率的干扰或噪声。也可以与一个系统级联&#xff0c;用于抑制系统谐振峰的影响。 假设 notch 滤波器的下陷频率为 ω c \omega_c ωc​&#xff0c;下陷程度为 d B d o w n dB_{down} …

k8s二进制部署的搭建

1.1 常见k8s安装部署方式 ●Minikube Minikube是一个工具&#xff0c;可以在本地快速运行一个单节点微型K8S&#xff0c;仅用于学习、预览K8S的一些特性使用。 部署地址&#xff1a;Install Tools | Kubernetes ●Kubeadm Kubeadm也是一个工具&#xff0c;提供kubeadm init…

高侧开关芯片四通道 40V 50mΩ车规级带反向电流保护功能负载检测高边开关

概述 PC8845/G是四通道、高侧功率具有集成NMOS功率FET的开关&#xff0c;以及电荷泵。该设备集成了高级 保护功能&#xff0c;例如负载电流限制&#xff0c;通过功率限制进行过载主动管理可配置闩锁关闭的超温停机。全面诊断和高精度电流感应这些功能实现了对负载的智能控制。…

html基础操练和进阶修炼宝典

文章目录 1.超链接标签2.跳锚点3.图片标签4.表格5.表格的方向属性6.子窗口7.音视频标签8.表单9.文件上传10.input属性 html修炼必经之路—各种类型标签详解加展示&#xff0c;关注点赞加收藏&#xff0c;防止迷路哦 1.超链接标签 <!DOCTYPE html> <html lang"en…

「媒体宣传」如何写好新闻稿?

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 写好新闻稿是媒体宣传的关键环节之一&#xff0c;下面是一些关于如何写好新闻稿的建议&#xff1a; 明确新闻稿的目的和受众&#xff1a;在写新闻稿之前&#xff0c;首先要明确新闻稿的目…

在 Rust 中实现 TCP : 1. 联通内核与用户空间的桥梁

内核-用户空间鸿沟 构建自己的 TCP栈是一项极具挑战的任务。通常&#xff0c;当用户空间应用程序需要互联网连接时&#xff0c;它们会调用操作系统内核提供的高级 API。这些 API 帮助应用程序 连接网络创建、发送和接收数据&#xff0c;从而消除了直接处理原始数据包的复杂性。…

一念生花,Coze 结合VisActor 文生图实战总结

前言 词云魔方 逢年过节发送祝福语是中国人特有的礼节&#xff0c;然而准备拜年祝福语也是让人伤透脑筋&#xff0c;大多数人都是拷贝网络上流行的“段子”&#xff0c;改一下名字就发出来了。更有甚者连名字都不改&#xff0c;略显尴尬。 但是如果可以让 AI 总结你想对特定…

18个惊艳的可视化大屏(第十辑):物流运输快递方向

可视化大屏在物流运输行业中具有很大的应用价值&#xff0c;可以帮助企业实现实时监控、路线规划、数据分析、风险预警、服务质量监控和决策支持等目标&#xff0c;提高物流运输效率和安全性&#xff0c;降低成本&#xff0c;提升企业竞争力&#xff0c;贝格前端工场带来的和这…

跨国企业如何选择合格的国际数据业务传输方案

在全球化的商业环境中&#xff0c;跨国企业面临着数据跨境传输的挑战。随着业务的扩展&#xff0c;企业需要在不同国家和地区之间高效、安全地传输大量数据。选择合适的国际数据业务传输方案对于保障数据安全、提高业务效率、遵守法律法规至关重要。 为什么跨国企业需要一个合适…

CentOS 定时调度

文章目录 一、场景说明二、脚本职责三、参数说明四、操作示例五、注意事项 一、场景说明 本自动化脚本旨在为提高研发、测试、运维快速部署应用环境而编写。 脚本遵循拿来即用的原则快速完成 CentOS 系统各应用环境部署工作。 统一研发、测试、生产环境的部署模式、部署结构、…

蓝桥杯练习系统(算法训练)ALGO-994 最大分解

资源限制 内存限制&#xff1a;256.0MB C/C时间限制&#xff1a;1.0s Java时间限制&#xff1a;3.0s Python时间限制&#xff1a;5.0s 问题描述 给出一个正整数n&#xff0c;求一个和最大的序列a0&#xff0c;a1&#xff0c;a2&#xff0c;……&#xff0c;ap&#xff…

案例研究|DataEase助力众陶联应对产业链数据可视化挑战

佛山众陶联供应链服务有限公司&#xff08;以下简称为“众陶联”&#xff09;成立于2016年&#xff0c;是由34家陶瓷企业共同创办的建陶行业工业互联网平台&#xff0c;股东产值占整个行业的22.5%。众陶联以数据赋能为核心&#xff0c;积极探索新的交易和服务模式&#xff0c;构…

安达发|APS自动排程软件的三种模式

APS自动排程软件是一种用于生产计划和调度的工具&#xff0c;它可以帮助制造企业实现生产过程的优化和效率提升。根据不同的需求和应用场景&#xff0c;APS自动排程软件通常有三种模式&#xff1a;基于模拟仿真模式、基于TOC的模式和扩展以及基于数学建模。下面我将详细介绍这三…

小程序开发:app.vue检测更新时判断是否是朋友圈进入

因为如果从朋友圈点进小程序来的&#xff0c;有些功能就用不了&#xff0c;所以需要判断下是否从朋友圈点进来的。 检查代码如下&#xff1a; checkScene() { // 判断场景值 如果是从分享到朋友圈再打开 就会有一些功能无法使用 // 详见 https://developers.weixin.qq.com/…

Nodejs 第四十三章(redis)

Redis&#xff08;Remote Dictionary Server&#xff09;是一个开源的内存数据结构存储系统&#xff0c;它提供了一个高效的键值存储解决方案&#xff0c;并支持多种数据结构&#xff0c;如字符串&#xff08;Strings&#xff09;、哈希&#xff08;Hashes&#xff09;、列表&a…

【机器学习实战1】泰坦尼克号:灾难中的机器学习(一)数据预处理

&#x1f338;博主主页&#xff1a;釉色清风&#x1f338;文章专栏&#xff1a;机器学习实战&#x1f338;今日语录&#xff1a;不要一直责怪过去的自己&#xff0c;她曾经站在雾里也很迷茫。 &#x1f33c;实战项目简介 本次项目是kaggle上的一个入门比赛 &#xff1a;Titani…

QML中动态表格修改数据

1.qml文件中的实现代码 import QtQuick 2.15 import QtQuick.Window 2.15import QtQuick.Controls 2.0 import Qt.labs.qmlmodels 1.0 import QtQuick.Layouts 1.15Window {width: 640height: 480visible: truetitle: qsTr("Hello World")TableModel{id:table_model…