spring cloud alibaba-Geteway详解

spring cloud alibaba-Gateway详解

Gateway介绍

在 Spring Cloud Alibaba 生态系统中,Gateway 是一个非常重要的组件,用于构建微服务架构中的网关服务。它基于 Spring Cloud Gateway 进行扩展和优化,提供了更强大的功能和更好的性能。

Gateway功能

  1. 统一入口
    • 微服务架构中,多个服务通常部署在不同的地址和端口上。网关作为统一的入口,将所有服务的请求集中管理,客户端只需要与网关交互,而不需要直接与各个微服务通信。
    • 这样可以简化客户端的逻辑,同时提高系统的安全性。
  2. 请求路由
    • 根据请求的特征(如路径、方法、参数等)将请求转发到对应的后端服务。
    • 路由规则可以动态配置,方便调整服务的访问路径。
  3. 负载均衡
    • 当后端服务有多个实例时,网关可以根据一定的策略(如轮询、随机、权重等)将请求分发到不同的实例,提高系统的可用性和性能。
  4. 流量控制
    • 限制请求的流量,防止后端服务被过多的请求压垮。
    • 常见的流量控制算法包括令牌桶算法、滑动窗口算法等。
  5. 身份认证
    • 对请求进行身份验证,确保只有合法的用户才能访问后端服务。
    • 常见的身份验证方式包括基于令牌(如 JWT)、基于用户名和密码等。
  6. 协议转换
    • 将一种协议的请求转换为另一种协议的请求,例如将 HTTP 请求转换为 gRPC 请求。
    • 这样可以实现不同协议之间的通信,提高系统的灵活性。
  7. 系统监控
    • 监控网关的运行状态,包括请求量、响应时间、错误率等指标。
    • 通过监控可以及时发现系统的问题,提高系统的可靠性。
  8. 安全防护
    • 防止恶意攻击,如 SQL 注入、XSS 攻击、CSRF 攻击等。
    • 通过安全策略(如防火墙规则、WAF 等)保护系统免受攻击。

创建网关

创建一个新项目

  1. 导入依赖
        <dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>${spring-cloud-alibaba.version}</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency></dependencies>
  1. 编写启动类
package com.nie.gateway;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;@EnableDiscoveryClient
@SpringBootApplication
public class GatewayApplicationMain {public static void main(String[] args) {SpringApplication.run(GatewayApplicationMain.class,args);}
}
  1. 配置application.yml文件
spring:application:name: gatewaycloud:nacos:server-addr: 127.0.0.1:8848profiles:include: route
server:port: 80
  1. 配置路由规则 application-route.yml
spring:cloud:gateway:routes:- id: order-routeuri: lb://service-orderpredicates:- Path=/api/order/**- id: product-routeuri: lb://service-productpredicates:- Path=/api/product/**
@RequestMapping("/api/order/")
@RestController
public class OrderController {@GetMapping("/readDb")public String readDb(){return "readDb";}}

测试:说明是能访问到的
在这里插入图片描述

  1. 进入Nacos
    在这里插入图片描述

断言

断言工厂
名称参数(个数/类型)作用
After1/datetime在指定时间之后
Before1/datetime在指定时间之前
Between2/datetime在指定时间区间内
Cookie2/string, regexp包含cookie名且必须匹配指定值
Header2/string, regexp包含请求头且必须匹配指定值
HostN/string请求host必须是指定枚举值
MethodN/string请求方式必须是指定枚举值
Path2/List, bool请求路径满足规则,是否匹配最后的/
Query2/string, regexp包含指定请求参数
RemoteAddr1/List请求来源于指定网络域(CIDR写法)
Weight2/string, int按指定权重负载均衡
XForwarded1/List从X-Forwarded-For请求头中解析请求来源,并判断是否来源于指定网络域

例如:
predicates的意思就是断言
Cookie:路由断言工厂(名)
mycookie,mycookievalue:参数

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

假如我们要转发到百度 我们在加上一些断言规则

spring:cloud:gateway:routes:- id: bing-routeuri: https://cn.bing.com/predicates:- name: Pathargs:pattern: /search- name: Queryargs:param: qregexp: haha

这时候我们访问时必须为/serrch 必须带上参数 参数名为q 值必须为haha我们才能成功转发
在这里插入图片描述

如果值不等于haha 或者参数名不为q 那么会出现404找不到页面错误
在这里插入图片描述

自定义断言工厂
package com.nie.gateway.predicate;import jakarta.validation.constraints.NotEmpty;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.GatewayPredicate;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;/*** 自定义的VIP路由断言工厂类,用于根据请求参数判断是否匹配VIP路由。* 继承自AbstractRoutePredicateFactory,实现了自定义路由断言逻辑。*/
@Component
public class VipRoutePredicateFactory extends AbstractRoutePredicateFactory<VipRoutePredicateFactory.Config> {/*** 构造函数,指定配置类为Config。*/public VipRoutePredicateFactory() {super(Config.class);}/*** 实现apply方法,根据Config中的配置生成路由断言逻辑。** @param config 配置对象,包含请求参数名和期望值* @return 返回一个Predicate<ServerWebExchange>,用于判断请求是否匹配VIP路由*/@Overridepublic Predicate<ServerWebExchange> apply(Config config) {return new GatewayPredicate() {/*** 判断请求是否匹配VIP路由的逻辑。** @param serverWebExchange 当前的请求上下文* @return 如果请求参数中存在指定参数且值匹配,则返回true,否则返回false*/@Overridepublic boolean test(ServerWebExchange serverWebExchange) {ServerHttpRequest request = serverWebExchange.getRequest();// 获取请求参数中指定参数的第一个值String first = request.getQueryParams().getFirst(config.param);// 判断参数值是否存在且是否等于配置的期望值if (StringUtils.hasText(first) && first.equals(config.value)) {return true;}return false;}};}/*** 定义配置类的字段顺序,用于在配置文件中指定参数时的顺序。** @return 返回字段顺序列表*/@Overridepublic List<String> shortcutFieldOrder() {return Arrays.asList("param", "value");}/*** 配置类,用于存储路由断言的配置信息。*/@Validatedpublic static class Config {/*** 请求参数名,用于从请求中获取参数值。*/@NotEmptyprivate String param;/*** 请求参数期望值,用于判断请求参数值是否匹配。*/@NotEmptyprivate String value;/*** 获取请求参数名。** @return 返回请求参数名*/public String getParam() {return param;}/*** 设置请求参数名。** @param param 请求参数名*/public void setParam(String param) {this.param = param;}/*** 获取请求参数期望值。** @return 返回请求参数期望值*/public String getValue() {return value;}/*** 设置请求参数期望值。** @param value 请求参数期望值*/public void setValue(String value) {this.value = value;}}
}
spring:cloud:gateway:routes:- id: bing-routeuri: https://cn.bing.com/predicates:- name: Pathargs:pattern: /search- name: Queryargs:param: qregexp: haha- name: Vipargs:param: uservalue: xiaonie

在这里插入图片描述

我出现的错误

我在这里犯了一个大错误

java.lang.IllegalArgumentException: Unable to find RoutePredicateFactory with name VipRoutePredicateFactory

我检查了好几遍代码都没问题 最后我发现我在这里把这个包放在了外面去了 所以他没有扫描到这个包 希望打架也注意一下

过滤器

路径重写

如果加上了路径重写那么微服务前面就不需要加上/api/模块名

spring:cloud:gateway:routes:- id: bing-routeuri: https://cn.bing.com/predicates:- name: Pathargs:pattern: /search- name: Queryargs:param: qregexp: haha- name: Vipargs:param: uservalue: xiaonie- id: order-routeuri: lb://service-orderpredicates:- Path=/api/order/**filters:- RewritePath=/api/order/(?<segment>.*), /$\{segment}order: 1- id: product-routeuri: lb://service-productpredicates:- Path=/api/product/**filters:- RewritePath=/api/product/(?<segment>.*), /$\{segment}order: 2
package com.nie.order.controller;import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.nie.order.bean.Order;
import com.nie.order.properties.OrderProperties;
import com.nie.order.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;@RestController
public class OrderController {@Autowiredprivate OrderService orderService;@Autowiredprivate OrderProperties orderProperties;@GetMapping("/readDb")public String readDb(){return "readDb";}@GetMapping("/seckill")@SentinelResource(value = "seckill-order", fallback = "seckillFallback")public Order seckill(@RequestParam("userId") Long userId,@RequestParam("productId") Long productId){Order order = orderService.createOrder(productId, userId);order.setId(Long.MAX_VALUE);return order;}public Order seckillFallback(Long userId, Long productId, Throwable exception){System.out.println("已经开始限制了");Order order = new Order();order.setId(productId);order.setUserId(userId);order.setAddress("异常信息:" + exception.getClass());return order;}@GetMapping("/config")public String config(){return "order.timeout = " + orderProperties.getTimeout()+ ", order.auto-confirm = " + orderProperties.getAutoConfirm()+"order.db="+orderProperties.getDb();}@GetMapping("/create")public Order createOrder(@RequestParam("userId") Long userId,@RequestParam("productId") Long productId){Order order = orderService.createOrder(productId,userId);return order;}
}

这样也就能访问 避免后期因为规划不周到 需要大量改前缀
在这里插入图片描述

          filters:- RewritePath=/api/product/(?<segment>.*), /$\{segment}- AddResponseHeader=X-Response-Abcd, 123

如果我们加上AddResponseHeader=X-Response-Abcd, 123
那么在我们每次请求中他都会带上响应头 值为123
在这里插入图片描述

默认过滤器
      default-filters:- AddResponseHeader=X-Response-Abcd, 123

用上面的例子的话我们就在每次请求中都带入了请求头 值为123
就不用在每个微服务上面都加了

在这里插入图片描述

全局Filters
package com.nie.gateway.filter;import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;@Slf4j
@Component
public class RtGlobalFilter implements GlobalFilter, Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest request = exchange.getRequest();ServerHttpResponse response = exchange.getResponse();String uri = request.getURI().toString();long start = System.currentTimeMillis();log.info("请求【{}】开始: 时间: {}", uri, start);//=============以上是前置逻辑================Mono<Void> filter = chain.filter(exchange).doFinally((result)->{//=============以下是后置逻辑================long end = System.currentTimeMillis();log.info("请求【{}】结束: 时间: {}, 耗时: {}ms",uri,end,end-start);}); //放行  10sreturn filter;}@Overridepublic int getOrder() {return 0;}
}

在这里插入图片描述

自定义过滤器
          filters:- RewritePath=/api/order/(?<segment>.*), /$\{segment}- OnceTooken=X-Response-Token, uuid
package com.nie.gateway.filter;import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractNameValueGatewayFilterFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import java.util.UUID;@Component
public class OnceTokenGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {@Overridepublic GatewayFilter apply(NameValueConfig config) {return new GatewayFilter() {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {//每次响应之前,添加一个一次性令牌,支持 uuid, jwt等各种格式return chain.filter(exchange).then(Mono.fromRunnable(() -> {ServerHttpResponse response = exchange.getResponse();HttpHeaders headers = response.getHeaders();String value = config.getValue();if ("uuid".equalsIgnoreCase(value)) {value = UUID.randomUUID().toString();}if ("jwt".equalsIgnoreCase(value)) {value = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiIjoiMjQ4OTY3Nzg5IiwibmFtZSI6IkpvaG4gRG9lIiLCJleHAiOjE2NTM5MDk3OTksImlhdCI6MTY1MzkwOTc5OCwiZXhwIjoxNjUzOTA5NzkwLCJpc3MiOiJhdXRoIjoiLCJuYW1lIjoiYXV0aG9ycyIsImV4cCI6MTY1MzkwOTc5OCwianRpIjoiMjAyMyIsInR5cCI6IkpXVCJ9LCJpYXQiOjE2NTM5MDk3OTksImV4cCI6MTY1MzkwOTc5OCwiaXNzIjoiaHR0cHM6Ly9hdXRoLmF1dGhvcnMubmV0L3VzZXIiIsImF1dGhvcml0eSI6eyJpZGVudGl0eSI6eyJjbGllbnRzIjp7InVzZXJAZXhhbXBsZS5jb20iOnsiYWV0Ijp7InVzZXJAZXhhbXBsZS5jb20iOnsiZXhhbXBsZSI6eyJ1c2VyQGV4YW1wbGUiOnsiZXhhbXBsZSI6eyJ1c2VyQGV4YW1wbGUiOnsiZXhhbXBsZSI6eyJ1c2VyQGV4YW1wbGUiOnsiZXhhbXBsZSI6eyJ1c2VyQGV4YW1wbGUiOnsiZXhhbXBsZSI6eyJ1c2VyQGV4YW1wbGUiOnsiZXhhbXBsZSI6eyJ1c2VyGVyIjp7fSwicmV4cCI6eyJyIjoiLCJLCJsYW1vdW50aWVub3JhbCIsImZSI6eyJ1c2VyIjp7fX19LCJ30=\n";}headers.add(config.getName(), value);}));}};}}

在这里插入图片描述

全局跨域

这样配置application.yml之后
允许所有请求跨域 allowed-origin-patterns: ‘
允许全部请求来源 允许所有的头 allowed-headers: '

允许所有的请求方式 allowed-methods: ‘*’

spring:cloud:gateway:globalcors:cors-configurations:'[/**]':allowed-origin-patterns: '*'allowed-headers: '*'allowed-methods: '*'

在这里插入图片描述

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

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

相关文章

iOS 直播技术及优化

iOS直播技术的实现和优化涉及多个技术环节&#xff0c;需结合协议选择、编解码方案、播放器技术及性能调优等多方面。 一、核心技术实现 协议选择与传输优化 HLS&#xff08;HTTP Live Streaming&#xff09;&#xff1a;苹果官方推荐&#xff0c;基于HTTP分片传输&#xff0c…

目标检测135个前沿算法模型汇总(附源码)!

目标检测是计算机视觉核心方向之一&#xff0c;也是发论文的热门领域&#xff01; 近来不仅YOLO算法迎来了新突破&#xff0c;迭代出YOLOv12&#xff01;Mamba、大模型等新技术的发展&#xff0c;也给该领域注入了全新的力量&#xff0c;取得了诸多显著成果。比如性能飙升82.3…

期刊采编系统安装升级错误

我们以ojs系统为例&#xff1a; PHP Fatal error: Uncaught Error: Call to a member function getId() on null in /esci/data/html/classes/install/Upgrade.inc.php:1019 Stacktrace: #0 /esci/data/html/lib/pkp/classes/install/Installer.inc.php(415): Upgrade->con…

浅谈无服务器WebSocket的优势

实际上&#xff0c;一个实用的解决方案是将构建业务关键型实时平台的复杂性卸载到专门的云服务中。 完全托管的无服务器 WebSocket 解决方案为事件驱动的消息传递提供了基础结构;它使底层基础设施成为一种商品。客户端使用提供程序服务发送/接收低延迟消息&#xff0c;并专注于…

Python数据可视化高级实战之二——热力图绘制探究

目录 一、热力图的作用 二、热力图反映的信息类型 三、热力图的典型应用场景 1. 地球信息系统 (GIS) 2. 城市交通分析 3. 市场分析 4. 用户行为分析 5. 网络流量分析 6. 传染病传播分析 7. 社交媒体舆情分析 四、Python 绘制热力图的关键技术要点 1. 数据预处理 2. 颜色选择与渐…

配电网运行状态综合评估方法研究

1评估指标体系的构建 [1]冷华,童莹,李欣然,等.配电网运行状态综合评估方法研究[J].电力系统保护与控制,2017,45(01):53-59. 1.1评估范围 图1为配电系统组成示意图&#xff0c;其中A、B、C分别表示高、中、低压配电系统。高压配变(也称主变)将35kV或110kV的电压降到10kV&#…

Docker安装MinIO对象存储中间件

MinIO 是一个高性能、分布式的对象存储系统&#xff0c;兼容 Amazon S3 云存储服务协议&#xff0c;广泛应用于企业存储、大数据、机器学习和容器化应用等领域。以下是详细介绍&#xff1a; 核心特点 兼容 S3 API &#xff1a;全面兼容 Amazon S3 API&#xff0c;这意味着使用…

HTML回顾

html全称:HyperText Markup Language(超文本标记语言) 注重标签语义,而不是默认效果 规则 块级元素包括: marquee、div等 行内元素包括: span、input等 规则1:块级元素中能写:行内元素、块级元素(几乎什么都能写) 规则2:行级元素中能写:行内元素,但不能写:块…

JAVA Spring MVC+Mybatis Spring MVC的工作流程*,多表连查

目录 注解总结 将传送到客户端的数据转成json数据 **描述一下Spring MVC的工作流程** 1。属性赋值 BeanUtils.copyProperties(addUserDTO,user); 添加依赖&#xff1a; spring web、mybatis framework、mysql driver Controller和ResponseBody优化 直接改成RestControl…

H2数据库中一条insert语句到生成java对象到数据写入磁盘的完整步骤

H2 数据库将 SQL 语句转换为磁盘存储的全过程可以分为以下 8 个关键步骤&#xff0c;我们以 INSERT INTO users (id, name) VALUES (1, Alice) 为例详细说明&#xff1a; 1. SQL 解析与语法树生成 词法分析&#xff1a;拆分语句为 INSERT、INTO、users 等 Token语法分析&#…

重磅升级!Google Play商店改版上线

5 月 21 日消息&#xff0c;Android Headline 今天&#xff08;5 月 21 日&#xff09;发布博文&#xff0c;报道称在 2025 年 I/O 开发者大会上&#xff0c;谷歌宣布更新 Google Play 应用商店&#xff0c;在优化用户体验的同时&#xff0c;提升开发者收益。 本次更新中&…

Docker面试题(1)

什么是Docker 一个容器化平台 形式是容器 将你的应用程序及所有依赖项打包在一起 确保应用程序在任何环境中无缝运行 什么是Docker镜像 Docker镜像是Docker容器的源代码 用于创建容器 使用build命令创建镜像 什么是 Docker容器 包括应用程序及所有的依赖项 作为操作系统的独立进…

Ulisses Braga-Neto《模式识别和机器学习基础》

模式识别和机器学习基础 [专著] Fundamentals of pattern recognition and machine learning / (美)乌利塞斯布拉加&#xff0d;内托(Ulisses Braga-Neto)著 ; 潘巍[等]译 推荐这本书&#xff0c;作者有自己的见解&#xff0c;而且提供代码。问题是难度高&#xff0c;对于初学…

RabbitMQ的简介

三个概念 生产者&#xff1a;生产消息的服务消息代理&#xff1a;消息中间件&#xff0c;如RabbitMQ消费者&#xff1a;获取使用消息的服务 消息队列到达消费者的两种形式 队列&#xff08;queue&#xff09;:点对点消息通信&#xff08;point-to-point&#xff09; 消息进入队…

自动切换剪贴板路径中反斜杠为正斜杠

有时候需要将我们常见的win全路径中反斜杠为正斜杠&#xff0c;每次用记事本&#xff0c;编辑替换非常麻烦&#xff0c;于是写了这个工具&#xff0c;能自动修改剪贴板中的数据&#xff0c;只需要运行一下即可。 实现效果&#xff0c;将类似于下面的路径&#xff1a; C:\User…

【时时三省】Python 语言----文件

目录 1,文件打开 2, 文件关闭 3, 文件写入 4, 文件读出 5, 文件定位 6, 文件重命名 7, 复制文件 山不在高,有仙则名。水不在深,有龙则灵。 ----CSDN 时时三省 1,文件打开 file = open(file, mode, buffering, encoding, errors, newline, closefd, opener) 2, 文…

React 个人笔记 Hooks编程

作用 配合函数式编程&#xff0c;保证在不产生类的时候完成一个整体的组件 常用组件 useStateuseContextuseReduceruseEffectuseMemouseCallback 前三个值为自变量 后三者为因变量 前三者相当于其他编程函数的变量声明&#xff0c;而后三者相当于对变量进行了(if now ! pr…

logits是啥、傅里叶变换

什么是logtis&#xff1f; 在深度学习的上下文中&#xff0c;logits 就是一个向量&#xff0c;下一步通常被投给 softmax/sigmoid 的向量。。 softmax的输出是分类任务的概率&#xff0c;其输入是logits层。 logits层通常产生-infinity到 infinity的值&#xff0c;而softmax层…

Adobe Illustrator学习备忘

1.移动画板&#xff1a;需按住空格键加鼠标一块才能拖动 2.放大缩小画板&#xff1a;按住Alt键加鼠标滚轮 3.撤回&#xff1a;CtrlZ 4.钢笔练习网站&#xff1a;The Bzier Game

【初识】内网渗透——基础概念,基本工具使用

目录 一、域&#xff0c;工作组&#xff0c;域控制器&#xff0c;活动目录相关概念&#xff1a; 域环境&#xff1a; 工作组&#xff1a; 域控制器DC&#xff1a; 活动目录AD&#xff1a; 二、内网的基本场景&#xff1a; 三、内网渗透基本测试方案&#xff1a; #案例1一基本信…