当前位置: 首页 > news >正文

网关Gateway

什么是网关?

        网关实质上是一个网络通向其他网络的 IP 地址,是当前微服务项目的"统一入口"。

网关能做什么?

        反向代理 、鉴权、 流量控制、 熔断、 日志监控等

图片原文:http://t.csdnimg.cn/SvUJh

核心概念

Router(路由):路由时构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如果断言为true则匹配该路由。

Predicate(断言):断言说简单点,就是请求匹配条件。断言是定义匹配条件,如果请求符合条件,则该请求匹配断言所属的路由。

Filter( 过滤): 指的是 Spring 框架中 GatewayFilter 的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。

Spring Cloud Gateway 网关的搭建:

创建 springboot 项目,引入 jar
        <!--网关jar--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId><version>${spring-cloud-alibaba-version}</version></dependency><!--引入nacos--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId><version>${spring-cloud-alibaba-version}</version></dependency><!--注意我这里没有引入父工程,而是springboot父启动依赖,也不要引入web依赖而是webflux--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency>
Spring Cloud GateWay是基于 webflux 的,如果非要 web 支持的话需要导入spring-boot-starter-webflux而不是spring-boot-start-web
应用启动类添加注解 @EnableDiscoveryClient
编写application.yml
server:port: 8070
spring:application:name: alibaba-gateway
cloud:nacos:discovery:server-addr: 127.0.0.1:3333 #注册服务到nacos,注意nacos的端口号配置gateway:discovery:locator:enabled: true #表明gateway开启服务注册和发现的功能,gateway为每一个服务创建了一个router,这个router将以服务名开头的请求路径转发到对应的服务。lower-case-service-id: true #请求路径的服务g名改为小写
启动项目,输入路径 ip+GateWay 端口号 + 要请求的服务名 + 地址
如: http://127.0.0.1:8070/alibaba-user-consumer-8090/user/findUserById?id=3

自定义路由

修改yml文件信息 :
server:port: 8070
spring:application:name: alibaba-gateway
cloud:nacos:discovery:server-addr: 127.0.0.1:3333 #注册服务到nacos,注意nacos的端口号配置gateway:discovery:locator:enabled: false #表明gateway开启服务注册和发现的功能,gateway为每一个服务创建了一个router,这个router将以服务名开头的请求路径转发到对应的服务。lower-case-service-id: true #请求路径的服务g名改为小写routes:    l- id: user-consumer #唯一 路由iduri: http://127.0.0.1:7780 #使用http:IP+服务端口 或lb://alibaba-user-consumer-8090 也可以,lb为负载均衡predicates: # 断言- Path=/ts/** # 路径需携带tsfilters:- StripPrefix=1 #路由去掉前缀信息 使用内置过滤器
路由的主要四个配置:
  • 路由idid
  • 路由目标(uri
  • 路由断言(predicates):判断路由的规则,
  • 路由过滤器(filters):对请求或响应做处理
再次启动项目 输入路径:ip+GateWay 端口号+ts+ 路径
如: http://127.0.0.1:8070/ts/user/findUserById?id=3

路由过滤器

客户端请求先找到路由,路由匹配时经过过滤器层层筛选,最终访问到微服务。
 

请求头过滤器配置示例(局部过滤器)

在yml中配置相关信息:
给所有进入 user-consumer 的请求添加一个请求头。
请求头的 key token value test。
默认过滤器配置示例(全局过滤器)
default - filters 的配置和 routes 平级。
只要配置在 default - filters 下面的过滤器,会对 routes 配置的所有路由都生效。
自定义全局路由过滤器
        

有时候SpringCloudGateWay提供的过滤器工厂不能满足自己的要求。 ,可能有时候需要在过滤时做一些其它的逻辑操作。 那么这时候可以选择使用Java代码自定义全局过滤器

yml配置如图:

创建 GateWayFilter 实现接口 GlobalFilter Ordered:
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.http.HttpStatus;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;/*** @Author * @Date 2023/12/25 11:11* @Description:*/
//@Component
//@Order(1)
public class GateWayFilter implements GlobalFilter {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {String token=exchange.getRequest().getHeaders().getFirst("token");System.out.println("token1====="+token);if ("123".equals(token)){return chain.filter(exchange);}System.out.println("错误,不放行");exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);return exchange.getResponse().setComplete();}
}

这里请求头携带的token为123时才允许放行。

当有多个过滤器时,Order的值决定了过滤器的执行顺序。

数值越大优先级越低, 负的越多, 优先级越高。

设置 Order 的值有两种方式:
1. 实现 Ordered 接口,并且重写 getOrder 方法
2. 使用@Order注解

如:GateWayFilter1
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;/*** @Author * @Date 2023/12/25 11:31* @Description:*/
//@Component
public class GateWayFilter1  implements GlobalFilter, Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {return null;}@Overridepublic int getOrder() {return 2;}
}

网关的跨域问题
使用 CORS 方式。
CORS是一个 W3C 标准,全称是 " 跨域资源共享 " Cross-origin resource sharing )。
它允许浏览器向跨源服务器,发出XMLHttpRequest 请求,从而克服了 AJAX 只能同源使用的限制。
方式一:配置 application.yml 文件:
spring:cloud:gateway:globalcors: # 全局的跨域配置add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题# options请求 就是一种询问服务器是否浏览器可以跨域的请求# 如果每次跨域都有询问服务器是否浏览器可以跨域对性能也是损耗# 可以配置本次跨域检测的有效期maxAge# 在maxAge设置的时间范围内,不去询问,统统允许跨域corsConfigurations:'[/**]':allowedOrigins: # 允许哪些网站的跨域请求- "http://localhost:8090"allowedMethods: # 允许的跨域ajax的请求方式- "GET"- "POST"- "DELETE"- "PUT"- "OPTIONS"allowedHeaders: "*" # 允许在请求中携带的头信息allowCredentials: true # 允许在请求中携带cookiemaxAge: 360000 # 本次跨域检测的有效期(单位毫秒)# 有效期内,跨域请求不会一直发option请求去增大服务器压力

方式二:使用编码方式定义配置类

@Configuration
public class CorsConfig {private static final String MAX_AGE = "18000L";@Beanpublic WebFilter corsFilter() {return (ServerWebExchange ctx, WebFilterChain chain) -> {ServerHttpRequest request = ctx.getRequest();// 使用SpringMvc自带的跨域检测工具类判断当前请求是否跨域if (!CorsUtils.isCorsRequest(request)) {return chain.filter(ctx);}HttpHeaders requestHeaders = request.getHeaders();// 获取请求头ServerHttpResponse response = ctx.getResponse();// 获取响应对象HttpMethod requestMethod =requestHeaders.getAccessControlRequestMethod(); // 获取请求方式对象HttpHeaders headers = response.getHeaders();// 获取响应头headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN,requestHeaders.getOrigin()); // 把请求头中的请求源(协议+ip+端口)添加到响应头中(相当于yml中的allowedOrigins)headers.addAll(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS,requestHeaders.getAccessControlRequestHeaders());if (requestMethod != null) {headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS,requestMethod.name()); // 允许被响应的方法(GET/POST等,相当于yml中的allowedMethods)}headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");// 允许在请求中携带cookie(相当于yml中的allowCredentials)headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, "*");// 允许在请求中携带的头信息(相当于yml中的allowedHeaders)headers.add(HttpHeaders.ACCESS_CONTROL_MAX_AGE, MAX_AGE);// 本次跨域检测的有效期(单位毫秒,相当于yml中的maxAge)if (request.getMethod() == HttpMethod.OPTIONS) {// 直接给option请求反回结果response.setStatusCode(HttpStatus.OK);return Mono.empty();}return chain.filter(ctx);// 不是option请求则放行};}
}

网关限流

        网关可以做很多的事情,比如,限流,当我们的系统被频繁的请求的时候,就有可能将系统压垮,所以为了解决这个问题,需要在每一个微服务中做限流操作,但是如果有了网关,那么就可以在网关系统做限流,因为所有的请求都需要先通过网关系统才能路由到微服务中。
令牌桶算法是比较常见的限流算法之一,大概描述如下:
  • 所有的请求在处理之前都需要拿到一个可用的令牌才会被处理;
  • 根据限流大小,设置按照一定的速率往桶里添加令牌;
  • 桶设置最大的放置令牌限制,当桶满时、新添加的令牌就被丢弃或者拒绝;
  • 请求达到后首先要获取令牌桶中的令牌,拿着令牌才可以进行其他的业务逻辑,处理完业务逻辑之后,将令牌直接删除;
  • 令牌桶有最低限额,当桶中的令牌达到最低限额的时候,请求处理完之后将不会删除令牌,以此保证足够的限流
网关限流代码实现
需求:每个 ip 地址 1 秒内只能发送 1 次请求,多出来的请求返回 429 错误。
spring cloud gateway 默认使用 redis RateLimter 限流算法来实现。所以我们要使用首先需要引
redis 的依赖
jar包引入:
       <!--redis 限流--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis-reactive</artifactId><version>2.1.3.RELEASE</version></dependency>
定义 KeyResolver
@Configuration
public class KeyResolverConfiguration {@Beanpublic KeyResolver ipKeyResolver(){return new KeyResolver() {@Overridepublic Mono<String> resolve(ServerWebExchange exchange) {return Mono.just(exchange.getRequest().getRemoteAddress().getHostName());}};}
}

修改yml中的配置项,指定限制流量的配置以及redis的配置

      routes:- id: cloud-user-consumeruri: http://127.0.0.1:7780predicates: # 断言- Path=/ts/** # 路径需携带tsfilters:- StripPrefix=1 #路由去掉前缀信息 使用内置过滤器- AddRequestHeader=token,123 #添加请求头- name: RequestRateLimiter #请求数限流 名字不能随便写args:key-resolver: "#{@ipKeyResolver}" #用于限流的键的解析器的 Bean 对象的名字。它使用SpEL 表达式根据#{@beanName}从 Spring 容器中获取 Bean 对象redis-rate-limiter.replenishRate: 1 #令牌桶每秒填充平均速率redis-rate-limiter.burstCapacity: 1 #令牌桶总容量。

  • burstCapacity :令牌桶总容量。
  • replenishRate :令牌桶每秒填充平均速率。
  • key - resolver 用于限流的键的解析器的 Bean 对象的名字。它使用 SpEL 表达式根据 #{@beanName} Spring 容器中获取 Bean 对象。

相关文章:

网关Gateway

什么是网关? 网关实质上是一个网络通向其他网络的 IP 地址&#xff0c;是当前微服务项目的"统一入口"。 网关能做什么&#xff1f; 反向代理 、鉴权、 流量控制、 熔断、 日志监控等 图片原文&#xff1a;http://t.csdnimg.cn/SvUJh 核心概念 Router&#xff08;…...

java 生成一个当前时间的时间搓

开发过程中 用时间搓数值格式存储 会更加精准 那么 我们在一些日常增删查改中就可以用时间搓来记录操作时间 就一行代码 long timestamp System.currentTimeMillis();他就能生成当前时间的时间搓 运行结果如下 然后 我们可以在 http://shijianchuo.wiicha.com/ 上进行转换查…...

金融中IC和IR的定义

当谈到金融领域时&#xff0c;IC&#xff08;Information Coefficient&#xff09;和IR&#xff08;Information Ratio&#xff09;通常是用来评估投资组合管理绩效的指标。它们都涉及到投资者对信息的利用和管理的效果。 信息系数&#xff08;IC - Information Coefficient&a…...

Git(2):Git环境的安装

本教程里的git命令例子都是在Git Bash中演示的&#xff0c;会用到一些基本的linux命令&#xff0c;在此为大家提前列举&#xff1a; ls/ll 查看当前目录cat 查看文件内容touch 创建文件vi vi编辑器&#xff08;使用vi编辑器是为了方便展示效果&#xff0c;学员可以记事本、edi…...

Pytest单元测试系列[v1.0.0][pytest插件常用技巧]

使用pytest-xdist并发执行测试 pytest-xdist&#xff1a;Run Tests in Parallel [https://pypi.python.org/pypi/pytest-xdist] 在自动化测试中有些资源只能同时被一个测试用例访问&#xff0c;如果不需要同时使用同一个资源&#xff0c;那么测试用例便可以并行执行 执行命令…...

嵌入式培训机构四个月实训课程笔记(完整版)-Linux系统编程第五天-Linux消息共享内存练习题(物联技术666)

更多配套资料CSDN地址:点赞+关注,功德无量。更多配套资料,欢迎私信。 物联技术666_嵌入式C语言开发,嵌入式硬件,嵌入式培训笔记-CSDN博客物联技术666擅长嵌入式C语言开发,嵌入式硬件,嵌入式培训笔记,等方面的知识,物联技术666关注机器学习,arm开发,物联网,嵌入式硬件,单片机…...

04set注入专题/简单类型/数组/List/Set/Map/空字符串/null/特殊符号

1.1注入外部Bean 在之前使用的案例就是注入外部Bean的方式。 <!-- class属性声明要管理哪个类中的对象 property标签的name是提示set方法名ref标签指明注入的bean的id--><bean id"userServiceBean" class"com.powernode.spring6.service.UserService…...

Linux引导和服务管理

目录 一.Linux引导&#xff1a; 1、Linux开机启动的完整过程&#xff1a; 2、bios的作用&#xff1a; 3、boot&#xff1a; 4.mbr: 5、grub&#xff1a; 6、加载内核文件&#xff1a; 7、启动进程&#xff1a; 8、centos6与centos7的区别&#xff1a; 9、完整的过程 …...

HarmonyOS 应用开发学习笔记 ets自定义组件及其引用 @Component自定义组件

Component注解的作用是用来构建自定义组件 Component组件官方文档 自定义组件具有以下特点&#xff1a; 可组合&#xff1a;允许开发者组合使用系统组件、及其属性和方法。 可重用&#xff1a;自定义组件可以被其他组件重用&#xff0c;并作为不同的实例在不同的父组件或容器…...

在做题中学习(43):长度最小的子数组

LCR 008. 长度最小的子数组 - 力扣&#xff08;LeetCode&#xff09; 解法&#xff1a;同向双指针-------滑动窗口算法 解释&#xff1a;本是暴力枚举做法&#xff0c;因为全部是正整数&#xff0c;就可以利用单调性和双指针解决问题来节省时间 思路&#xff1a; 如上面图&am…...

如何将 element-ui 中的 el-select 默认展开

<el-form-item label"藕粉桂花糖糕" prop"state" required><el-selectref"mySelect"v-model"form.state"style"width: 280px"placeholder"请选择"><el-option label"藕粉" :value"…...

Typora基本用法

文章目录 一、标题标题快捷键 二、段落1.换行2.分割线 三、文字显示1.字体2.上下标 四、列表1.无序列表2.有序列表3.任务列表 五、区块显示六、代码显示1.行内代码2.代码块 七、链接八、脚注九、图片插入十、表格十一、流程图十二、表情符号十三、数学公式的输入1.公式的插入①…...

读元宇宙改变一切笔记02_元素(上)

1. 很多组织和机构都想在元宇宙的定义上掌握话语权&#xff0c;使得它的定义中存在矛盾之处&#xff0c;也有大量含义混淆之处 1.1. 微软 1.1.1. 在谈论“多个元宇宙” 1.1.2. 微软首席执行官萨提亚纳德拉将元宇宙描述为一种可以将“整个…...

听GPT 讲Rust源代码--compiler(2)

File: rust/compiler/rustc_codegen_cranelift/build_system/prepare.rs 在Rust源代码中&#xff0c;rust/compiler/rustc_codegen_cranelift/build_system/prepare.rs文件的作用是为Cranelift代码生成器构建系统准备依赖项。 具体来说&#xff0c;该文件的主要目标是处理Crane…...

SpringCloud系列篇:核心组件之负载均衡组件

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于SpringCloud的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.负载均衡组件是什么 二.负载均衡…...

多线程模板应用实现(实践学习笔记)

出处&#xff1a;B站码出名企路 个人笔记&#xff1a;因为是跟着b站的教学视频以及文档初步学习&#xff0c;可能存在诸多的理解有误&#xff0c;对大家仅供借鉴&#xff0c;参考&#xff0c;然后是B站up阳哥的视频&#xff0c;我是跟着他学。大家有兴趣的可以到b站搜索。加油…...

Linux系统中MYSQL重置密码(针对root忘记密码)

⼀ .进⼊MySql配置⽂件中 vi /etc/my.cnf 在最后⼀⾏添加免密码登陆: skip-grant-tables :wq 保存退出 ⼆.重启MySql service mysql restart 或 systemctl restart mysqld.service 三. 登陆数据库 mysql -uroot -p 让输⼊密码直接回⻋就可以 四.修改MySql密码 use mysql…...

蓝桥杯基础知识1 字母大小写转换

蓝桥杯基础知识1 字母大小写转换 isalpha()判断一个字符是否为字母。 isalnum()判断一个字符是否为十进制数字字符或者字母&#xff0c;是否属于a~ z或A~ Z或0~9。 isdigit() 判断一个字符是否是十进制数字字符。十进制数字是&#xff1a;0 1 2 3 4 5 6 7 8 9 isalnum()和isdig…...

攀登者1 - 华为OD统一考试

OD统一考试 分值: 100分 题解: Java / Python / C++ 题目描述 攀登者喜欢寻找各种地图,并且尝试攀登到最高的山峰。 地图表示为一维数组,数组的索引代表水平位置,数组的元素代表相对海拔高度。其中数组元素0代表地面。 例如:[0,1,2,4,3,1,0,0,1,2,3,1,2,1,0],代表如下…...

通信原理期末复习——基础小题汇总(二)

个人名片&#xff1a; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的在校大学生 &#x1f42f;个人主页&#xff1a;妄北y &#x1f427;个人QQ&#xff1a;2061314755 &#x1f43b;个人邮箱&#xff1a;2061314755qq.com &#x1f989;个人WeChat&#xff1a;V…...

Pandoc:5步掌握全能文档转换的极简工作流

Pandoc&#xff1a;5步掌握全能文档转换的极简工作流 【免费下载链接】pandoc Universal markup converter 项目地址: https://gitcode.com/gh_mirrors/pa/pandoc 价值定位&#xff1a;为什么每个开发者都需要一款"格式翻译官" 当你需要将Markdown笔记转换为…...

终极指南:如何使用LeetDown轻松降级A6/A7苹果设备系统

终极指南&#xff1a;如何使用LeetDown轻松降级A6/A7苹果设备系统 【免费下载链接】LeetDown a GUI macOS Downgrade Tool for A6 and A7 iDevices 项目地址: https://gitcode.com/gh_mirrors/le/LeetDown LeetDown是一款专为macOS设计的图形化降级工具&#xff0c;能够…...

Android Gradle - Gradle 自定义插件(Build Script 自定义插件、buildSrc 自定义插件、独立项目自定义插件)

一、Build Script 自定义插件 1、基本介绍插件代码直接写在模块级 build.gradle 文件中逻辑非常简单&#xff0c;且仅在该模块使用2、演示 &#xff08;1&#xff09;具体实现 在模块级 build.gradle 文件中定义插件 class SimpleBuildScriptPlugin implements Plugin<Proje…...

JeecgBoot低代码开发平台终极实战指南:从零开始构建企业级应用

JeecgBoot低代码开发平台终极实战指南&#xff1a;从零开始构建企业级应用 【免费下载链接】jeecg-boot jeecgboot/jeecg-boot 是一个基于 Spring Boot 的 Java 框架&#xff0c;用于快速开发企业级应用。适合在 Java 应用开发中使用&#xff0c;提高开发效率和代码质量。特点是…...

Obsidian Full Calendar:5步构建个人知识与时间管理一体化系统

Obsidian Full Calendar&#xff1a;5步构建个人知识与时间管理一体化系统 【免费下载链接】obsidian-full-calendar Keep events and manage your calendar alongside all your other notes in your Obsidian Vault. 项目地址: https://gitcode.com/gh_mirrors/obs/obsidian…...

为什么你的Tinymce总是显示秘钥提示?深入解析富文本编辑器的授权机制

解密Tinymce授权机制&#xff1a;从技术原理到合规实践 每次启动项目时&#xff0c;那个突兀的"未授权"提示框是否让你感到困扰&#xff1f;作为前端开发领域的标配工具&#xff0c;Tinymce的授权机制远比表面看到的复杂。让我们拨开迷雾&#xff0c;从技术实现到商业…...

Nunchaku-flux-1-dev部署避坑指南:解决403 Forbidden错误

Nunchaku-flux-1-dev部署避坑指南&#xff1a;解决403 Forbidden错误 部署Nunchaku-flux-1-dev时遇到403 Forbidden错误&#xff1f;别急&#xff0c;这篇文章手把手带你排查和解决这个常见但棘手的问题。 最近在部署Nunchaku-flux-1-dev时&#xff0c;不少小伙伴反映遇到了403…...

Phi-4-Reasoning-Vision惊艳案例:模糊图像增强后多步逻辑推理还原

Phi-4-Reasoning-Vision惊艳案例&#xff1a;模糊图像增强后多步逻辑推理还原 1. 项目概述 Phi-4-Reasoning-Vision是基于微软Phi-4-reasoning-vision-15B多模态大模型开发的高性能推理工具&#xff0c;专为双卡4090环境优化。这款工具能够处理复杂的图像推理任务&#xff0c…...

3分钟搞定!Windows 11 LTSC 24H2微软商店终极安装指南

3分钟搞定&#xff01;Windows 11 LTSC 24H2微软商店终极安装指南 【免费下载链接】LTSC-Add-MicrosoftStore Add Windows Store to Windows 11 24H2 LTSC 项目地址: https://gitcode.com/gh_mirrors/ltscad/LTSC-Add-MicrosoftStore 你是否正在使用Windows 11 24H2 LTS…...

vLLM-v0.17.1保姆级教程:SSH中查看vLLM实时请求队列与Pending统计

vLLM-v0.17.1保姆级教程&#xff1a;SSH中查看vLLM实时请求队列与Pending统计 1. vLLM框架简介 vLLM是一个专注于大语言模型(LLM)推理和服务的高性能库&#xff0c;它的设计目标是让开发者能够轻松部署和管理大规模语言模型。这个项目最初由加州大学伯克利分校的天空计算实验…...