gateway应用(1)

1 简介

简单理解---业务服务的统一入口,方便实现,服务路由,安全,限流,过滤,黑白名单,证书加密解密,服务降级/熔断,灰度,等等

2 介绍

  1. Predicate(断言):如果请求路径与断言相匹配则进行路由。(路径匹配是常见断言)
  2. Route(路由):路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如果断言为true则匹配该路由。
  3. Filter(过滤):指的是Spring框架中GatewayFilter的实例,使用过滤器,路由成功,则可以执行pre Filter  ,服务响应回数据,可以执行 Post Filter。

3 注意事项

3.1

spring-boot-starter-parent和spring-cloud-starter-gateway版本要一致,否则可能报错

4 基本路由实战

4.1 pom文件

 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.3.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.gateway</groupId><artifactId>gateway</artifactId><version>0.0.1-SNAPSHOT</version><packaging>war</packaging><name>gateway</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version><spring-cloud.version>2.1.3.RELEASE</spring-cloud.version></properties><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId><version>${spring-cloud.version}</version></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId><version>${spring-cloud.version}</version></dependency></dependencies>

 配置文件

server:port: 80
spring:application:name: gatewaycloud:nacos:discovery:server-addr: 127.0.0.1:8848# config:#   server-addr: localhost:8848 # Nacos 服务器地址gateway:routes:- id: goods-server #路由的ID,没有固定规则但要求唯一,建议配合服务名# uri: http://localhost:8001          #匹配后提供服务的路由地址uri: lb://goods-server      #匹配后提供服务的路由地址,lb负载predicates:- Path=/goods/**     # 断言,路径相匹配的进行路由- id: order-serveruri: lb://order-serverpredicates:- Path=/order/**#- Path=/goods/,/goods/** 多个可以逗号隔开enabled: true #开启网关,默认true 如果程序引用了spring-cloud-starter-gateway,但不希望启用网关 设置为false

4.2 测试路由转发

另外一个 goods 服务,直接访问 http://localhost:8080/goods/good/list 即可出现数据

 直接访问gateway服务 http://localhost/goods/good/list 自己就会转发到goods服务上

4.3 StripPrefix

有一种场景,前端会在所有的接口前加一个api。前端请求的路径是 http://localhost/api/goods/good/list  。实际上请求 http://localhost/goods/good/list 怎么办

StripPrefix=1的意思就是去掉路径上第一个,也就是api将会去掉。 当我们访问。http://localhost/api/goods/good/list  它会自动变成  http://localhost/goods/good/list

5 限流

  添加 pom坐标

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis-reactive</artifactId></dependency>

注意点:

配置文件中 redis-rate-limiter.replenishRate ,redis-rate-limiter.burstCapacity等同于配置bean中的 RedisRateLimiter,但是同时存在时,只有配置文件的配置生效。

server:port: 80
spring:application:name: gatewaycloud:nacos:discovery:server-addr: 127.0.0.1:8848# config:#   server-addr: localhost:8848 # Nacos 服务器地址gateway:routes:- id: goods-server #路由的ID,没有固定规则但要求唯一,建议配合服务名# uri: http://localhost:8001          #匹配后提供服务的路由地址uri: lb://goods-server      #匹配后提供服务的路由地址predicates:- Path=/goods/**     # 断言,路径相匹配的进行路由filters:- name: RequestRateLimiterargs:#spel表达式 它会去容器查找名称为hostKeyResolver 的Bean。key-resolver: '#{@hostKeyResolver}'#针对同一个key,允许的每秒请求数,不包括被抛弃的请求。这实际是令牌桶填充率。redis-rate-limiter.replenishRate: 1#针对同一个key,一秒内允许的最大请求数。这实际是令牌桶可容纳的最大令牌数。若设为0,则拒绝所有请求。redis-rate-limiter.burstCapacity: 1
package com.order.config;import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import reactor.core.publisher.Mono;import java.util.Objects;/*** @创建人 赵伟* @创建时间 2024/3/18* @描述*/
@Slf4j
@Configuration
public class RouteConfig {
/*    @Beanpublic KeyResolver userKeyResolver() {return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("userId")//exchange.getRequest().getHeaders().getFirst("X-Forwarded-For") 基于请求ip的限流);}*/
/*    *//*** 根据 路径 进行限流** @return KeyResolver*//*@Beanpublic KeyResolver pathKeyResolver() {return exchange -> Mono.just(Objects.requireNonNull(exchange.getRequest().getPath()).toString());}*//*** 根据 HostAddress 进行限流** @return KeyResolver*/@Beanpublic KeyResolver hostKeyResolver() {return exchange -> Mono.just(Objects.requireNonNull(exchange.getRequest().getRemoteAddress()).getHostString());}/*** Redis 令牌桶 限流*   这个等同于配置文件中的 redis-rate-limiter.replenishRate,redis-rate-limiter.burstCapacity*   同时存在时,加载的是配置文件中的配置* @return RedisRateLimiter*/@Bean RedisRateLimiter redisRateLimiter() {return new RedisRateLimiter(1, 1);}
}

6黑白名单

/*** @描述 禁用ip*/
public class BlackIpFilter implements GlobalFilter, Ordered {@Overridepublic int getOrder() {return 0;}@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest request = exchange.getRequest();String remoteIp = GatewayUtil.getRemoteIp(request);//查询 ip接口-缓存等实现if (true) {//返回禁用提示码exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);return exchange.getResponse().setComplete();}return chain.filter(exchange);}
}

7 权限或token/续时/传递用户信息/串行/

package com.order.filter;import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.order.entity.MyUser;
import com.order.utils.GatewayUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.*;/*** @创建人 赵伟* @创建时间 2024/3/20* @描述 禁用ip*/
@Component //需要将实现设置为Spring的组件
public class BlackIpFilter implements GlobalFilter, Ordered {/*** 顺序执行* @return*/@Overridepublic int getOrder() {return 0;}@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest request = exchange.getRequest();ServerHttpResponse response = exchange.getResponse();//1 ip黑名单String remoteIp = GatewayUtil.getRemoteIp(request);//查询 ip接口-缓存等实现if (false) {//返回禁用提示码return loseToken(exchange,response);//  return exchange.getResponse().setComplete();}//2 OPTIONS 不允许if (request.getMethod().equals(RequestMethod.OPTIONS.name())) {//返回禁用提示码exchange.getResponse().setStatusCode(HttpStatus.METHOD_NOT_ALLOWED);return exchange.getResponse().setComplete();}//4 忽略的urlString pass = "/aaa/getToken|/aaa/updatePwd";String uri = request.getURI().toString();if (isPass(pass, uri)) {return chain.filter(exchange);}//5 校验tokenList<String> tokenList = request.getHeaders().get("token");if (CollectionUtil.isEmpty(tokenList)) {return loseToken(exchange,response);}//6 根据token 获取redis用户信息判断是否失效,//注意多端系统生成token规则String token = tokenList.get(0);//自己写逻辑MyUser user = queryCacheByToken(token);if (ObjectUtil.isNull(user)) {return loseToken(exchange,response);}//7 已经获取到用户了,判断用户状态,是够禁用/用户密码强制多少天修改。 登录接口也要实现,boolean forbidden = false;//禁用if (forbidden) {return loseToken(exchange,response);}MultiValueMap<String, String> queryParams = exchange.getRequest().getQueryParams();//put是覆盖//  queryParams.put("userId", Collections.singletonList("123"));// add则不会覆盖,而是继续添加//   queryParams.add("userId","123");//3 设置请求头加串行idServerHttpRequest.Builder mutate = request.mutate();//不存在新增,存在即修改mutate.header("serialId", UUID.randomUUID().toString());//8 赋值用户信息 可用jwt加密 子服务 通过拦截器 在解析,放到ThreadLocal//请求头中文乱码//  mutate.header("userInfo", String.valueOf(user));String s = Base64.getEncoder().encodeToString(String.valueOf(user).getBytes());mutate.header("userInfo", s );ServerHttpRequest build = mutate.build();exchange.mutate().request(build).build();//9 token续时//刷新token失效时间 是否每次请求都要续时,还是先获取判断小于一定时间在续时//  redisTemplate.setExpire(token, 60 * 60 * 24);return chain.filter(exchange);}/*** 假的获取缓存用户信息* @param token* @return*/private MyUser queryCacheByToken(String token) {MyUser myUser = new MyUser();myUser.setUserId("123");myUser.setUserName("小明");myUser.setUpdatePasswordTime(new Date());return myUser;}/*** 失效token* @param exchange* @param response1* @return*/private Mono<Void> loseToken(ServerWebExchange exchange,ServerHttpResponse response1) {// 设置响应的Content-Type头并指定编码为UTF-8ServerHttpResponse response = exchange.getResponse();response.setStatusCode(HttpStatus.OK);response.getHeaders().add("Content-Type","application/json;charset=UTF-8");JSONObject responseBody = new JSONObject();responseBody.put("result", Boolean.FALSE);responseBody.put("msg", "您当前登录状态已失效,请重新登录");responseBody.put("status", 400);responseBody.put("isSuccess",  Boolean.FALSE);String s = JSON.toJSONString(responseBody);byte[] bytes = new String(s.getBytes(), StandardCharsets.UTF_8).getBytes(StandardCharsets.UTF_8);DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(bytes);return  exchange.getResponse().writeWith(Flux.just(buffer));/*JSONObject jsonObject = new JSONObject();jsonObject.put("code","401");jsonObject.put("message","非法请求");byte[] datas = JSON.toJSONString(jsonObject).getBytes(StandardCharsets.UTF_8);DataBuffer buffer = response.bufferFactory().wrap(datas);response.setStatusCode(HttpStatus.UNAUTHORIZED);response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");return response.writeWith(Mono.just(buffer));*/}/*** 是否放行的url* @param passString* @param requestURI* @return*/public static boolean isPass(String passString, String requestURI) {if (StringUtils.isNotBlank(passString)) {String[] split1 = passString.split("\\|");for (int i = 0; i < split1.length; i++) {String s = split1[i];if (!StringUtils.isBlank(s) && StringUtils.containsIgnoreCase(requestURI, s)) {return true;}}}return false;}}

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

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

相关文章

荣誉 | 人大金仓连续三年入选“金融信创优秀解决方案”

3月28日&#xff0c;由中国人民银行领导&#xff0c;中国金融电子化集团有限公司牵头组建的金融信创生态实验室发布“第三期金融信创优秀解决方案”&#xff0c;人大金仓新一代手机银行系统解决方案成功入选&#xff0c;这也是人大金仓金融行业解决方案连续第三年获得用户认可。…

LabVIEW齿轮箱噪声监测系统

LabVIEW齿轮箱噪声监测系统 齿轮箱作为机械设备的“心脏”&#xff0c;其健康状态对设备的性能有着重要的影响。传统的齿轮箱监测方法依赖于直接的振动信号分析&#xff0c;但这种方法不仅成本高昂&#xff0c;而且在安装和拆卸过程中可能对设备造成损害。针对这些问题&#x…

filetype: python中判断图像格式库imghdr替代库

引言 imghdr库是python中的一个内置库&#xff0c;用来判断图像原本格式的。自己一直有在用&#xff0c;不过近来看到这个库在python 3.13中会被移除。 自己感觉一直被python版本赶着走。这不找了好久&#xff0c;才找到一个替代库–filetype Python各个版本将要移除和可替代…

Kubernetes控制器(四)______StatefulSet

控制器介绍 StatefulSet&#xff1a; 是Kubernetes中用于管理有状态应用的控制器。与Deployment不同&#xff0c;StatefulSet用于部署和管理需要持久标识、有序部署和唯一网络标识的 Pod。典型的用例包括数据库、缓存和队列等有状态应用。&#xff08;有状态服务&#xff1a;单…

分享几个好用的电商API接口(可测试)

以下是一些好用的电商API接口&#xff0c;这些接口都可以用于获取电商平台的商品、订单、物流等相关信息&#xff0c;并提供了测试功能以确保接口的稳定性和可用性&#xff1a; 请求示例&#xff0c;API接口接入Anzexi58 淘宝开放平台API&#xff1a;淘宝开放平台提供了丰富的…

Keil 警告解决 : warning: #870-D: invalid multibyte character sequence

说明&#xff1a;在Keil项目编译时出现了几个 warning: #870-D: 的警告&#xff0c;接下来分析解决这个警告。 注意&#xff1a;在尝试解决问题前一定要将整个工程打包成压缩文件备份&#xff0c;以防更改失败变文件成乱码。 1.警告内容 warning: #870-D: warning: #870-…

Android Monkey自动化测试

monkey一般用于压力测试&#xff0c;用户模拟用户事件 monkey 基本用法 adb shell monkey [参数] [随机事件数]monkey常用命令 -v&#xff1a;用于指定反馈信息级别&#xff0c;总共分三个等级-v -v -vadb shell mokey -v -v -v 100-s&#xff1a;用于指定伪随机数生成器的种…

CentOS7安装flink1.17完全分布式

前提条件 准备三台CenOS7机器&#xff0c;主机名称&#xff0c;例如&#xff1a;node2&#xff0c;node3&#xff0c;node4 三台机器安装好jdk8&#xff0c;通常情况下&#xff0c;flink需要结合hadoop处理大数据问题&#xff0c;建议先安装hadoop&#xff0c;可参考 hadoop安…

impnt只读,燕用,必填,提示词(占位符)属性分别是什么

readonly 属性规定输入字段为只读&#xff08;不能修改&#xff09; <input type"text" placeholder"点我啊" readonly/> disabled 属性规定输入字段是禁用的 <input type"text" placeholder"点我啊" disabled/> re…

XXLJob中GLUE模式实现在线编写java/shell/python/php/nodejs/powerShell---SpringCloud工作笔记202

1.起因: 之前就一直想实现类似的功能,今天总于找到有可以参考的东西了,这个思路可以帮助实现这种功能. 2.获得灵感 就是:我想实现通过在线编写代码,来扩展我们平台的能力,这样随着业务的扩展,不用我们每次都修改了代码,再去部署,这样就比较麻烦,今天偶尔发现,对于xxljob来说.有…

OSCP靶场--ProStore

OSCP靶场–ProStore 考点(node.js代码注入gdb-list源文件c语言命令执行) 1.nmap扫描 ## ┌──(root㉿kali)-[~/Desktop] └─# nmap 192.168.200.250 -sV -sC -Pn --min-rate 2500 -p- Starting Nmap 7.92 ( https://nmap.org ) at 2024-04-01 09:18 EDT Nmap scan report…

Stream2Graph论文翻译

Stream2Graph: Dynamic Knowledge Graph for Online Learning Applied in Large-scale Network Abstract 知识图谱(KG)是用于存储某个领域(医疗保健、金融、电子商务、ITOps等)中的知识的有价值的信息来源。大多数工业KG本质上是动态的&#xff0c;因为它们定期更新流数据(客…

Scala第十八章节(Iterable集合、Seq集合、Set集合、Map集合以及统计字符个数案例)

Scala第十八章节 章节目标 掌握Iterable集合相关内容.掌握Seq集合相关内容.掌握Set集合相关内容.掌握Map集合相关内容.掌握统计字符个数案例. 1. Iterable 1.1 概述 Iterable代表一个可以迭代的集合, 它继承了Traversable特质, 同时也是其他集合的父特质. 最重要的是, 它定…

windows无法使用hadoop报错:系统找不到路径

在windows下安装hadoop-3.1.4,进行环境变量配置后&#xff0c;打开window命令行窗口测试hadoop命令&#xff0c;报错&#xff0c;如图所示&#xff1a; 方案&#xff1a;由于JAVA_HOME路径有空格导致&#xff0c;可修改hadoop下\etc\hadoop\hadoop_env.cmd文档中set JAVA_HOME以…

Kubernetes(k8s):如何进行 Kubernetes 集群健康检查?

Kubernetes&#xff08;k8s&#xff09;&#xff1a;如何进行 Kubernetes 集群健康检查&#xff1f; 一、节点健康检查1、使用 kubectl 查看节点状态2、查看节点详细信息3、检查节点资源使用情况 2、Pod 健康检查2.1、 使用 kubectl 查看 Pod 状态2.2、 查看特定 Pod 的详细信息…

Oracle数据库常见 问题 或 报错 集合

【报错】字段长度不足 一般字段长度不够时报错&#xff1a; Cause: java.sql.SQLException: ORA-12899: value too large for colum “列名” 【报错】修改字段长度&#xff0c;提示资源正忙 以pl/sql为例&#xff1a; ctrl选中表&#xff0c;在列选项卡下修改字段长度&#x…

基于 java + Springboot + vue +mysql 大学生实习管理系统(含源码)

目录 &#x1f4da; 前言 &#x1f4d1;摘要 &#x1f4d1;实习管理系统的特点 &#x1f4d1;使用架构 &#x1f4da; 总体设计 &#x1f4da; 数据库设计 &#x1f4ac; 系统公告实体属性 &#x1f4ac; 单位成绩实体属性 &#x1f4ac; 学生实体属性 &#x1f4da; 系…

[已解决]Vue3+Element-plus使用el-dialog对话框无法显示

文章目录 问题发现原因分析解决方法 问题发现 点击按钮&#xff0c;没有想要的弹框 代码如下 修改 el-dialog到body中&#xff0c;还是不能显示 原因分析 使用devtool中vue工具进行查看组件结构 原因在于&#xff0c;在一个局部组件(Detail->ElTabPane->…)中使用…

Qt实现Kermit协议(三)

3 实现 3.2 KermitSendFile 该模块实现了Kermit发送文件功能。 序列图如下&#xff1a; 3.2.1 KermitSendFile定义 class QSerialPort; class KermitSendFile : public QObject, public Kermit {Q_OBJECT public:explicit KermitSendFile(QSerialPort *serial, QObject *…

计算机网络针对交换机的配置

实验 目的 交换机的基本配置&#xff0c;交换机VLAN配置 实验条件 Windows&#xff0c;Cisco packet tracer 实验 内容 交换机的基本配置&#xff0c;交换机VLAN配置 实验 过程 一、交换机的基本配置 进入特权模式 Switch>enable 进入配置模式 Switch#configure ter…