sentinel 网关

网关简介

大家都都知道在微服务架构中,一个系统会被拆分为很多个微服务。那么作为客户端要如何去调用这么多的微服务呢?如果没有网关的存在,我们只能在客户端记录每个微服务的地址,然后分别去调用。

这样的架构,会存在着诸多的问题:

l 客户端多次请求不同的微服务,增加客户端代码或配置编写的复杂性

l 认证复杂,每个服务都需要独立认证。

l 存在跨域请求,在一定场景下处理相对复杂。

上面的这些问题可以借助API网关来解决。

所谓的API网关,就是指系统的统一入口,它封装了应用程序的内部结构,为客户端提供统一服 务,一些与业务本身功能无关的公共逻辑可以在这里实现,诸如认证、鉴权、监控、路由转发等等。 添加上API网关之后,系统的架构图变成了如下所示:

在业界比较流行的网关,有下面这些:

l Ngnix+lua

使用nginx的反向代理和负载均衡可实现对api服务器的负载均衡及高可用

lua是一种脚本语言,可以来编写一些简单的逻辑, nginx支持lua脚本

l Kong

基于Nginx+Lua开发,性能高,稳定,有多个可用的插件(限流、鉴权等等)可以开箱即用。

问题:

只支持Http协议;二次开发,自由扩展困难;提供管理API,缺乏更易用的管控、配置方式。

l Zuul

Netflflix开源的网关,功能丰富,使用JAVA开发,易于二次开发

问题:缺乏管控,无法动态配置;依赖组件较多;处理Http请求依赖的是Web容器,性能不如Nginx

l Spring Cloud Gateway

Spring公司为了替换Zuul而开发的网关服务,将在下面具体介绍。

注意:SpringCloud alibaba技术栈中并没有提供自己的网关,我们可以采用Spring Cloud Gateway来做网关

Gateway

1.概念

Spring Cloud Gateway是Spring公司基于Spring 5.0,Spring Boot 2.0 和 Project Reactor 等术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。它的目标是替代 Netflflix Zuul,其不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控和限流。

优点:

l 性能强劲:是第一代网关Zuul的1.6倍

l 功能强大:内置了很多实用的功能,例如转发、监控、限流等

l 设计优雅,容易扩展

缺点:

l 其实现依赖Netty与WebFlux,不是传统的Servlet编程模型,学习成本高

l 不能将其部署在Tomcat、Jetty等Servlet容器里,只能打成jar包执行

l 需要Spring Boot 2.0及以上的版本,才支持

2.使用Gateway

<!--加入gateway的依赖-->
<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>
<!--hutool工具-->
<dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.16</version>
</dependency>
<!--        负载均衡-->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>

1)创建Gateway模块

引入jar包

创建启动类

配置文件

启动查看nacos

服务添加成功

2)设置路由规则

3.内置断言

SpringCloud Gateway包括许多内置的断言工厂,所有这些断言都与HTTP请求的不同属性匹配体如下:

l 基于Datetime类型的断言工厂

此类型的断言根据时间做判断,主要有三个:

AfterRoutePredicateFactory: 接收一个日期参数,判断请求日期是否晚于指定日期

BeforeRoutePredicateFactory: 接收一个日期参数,判断请求日期是否早于指定日期

BetweenRoutePredicateFactory: 接收两个日期参数,判断请求日期是否在指定时间段内

-After=2019-12-31T23:59:59.789+08:00[Asia/Shanghai]

l 基于远程地址的断言工厂 RemoteAddrRoutePredicateFactory:

接收一个IP地址段,判断请求主机地址是否在地址段中

-RemoteAddr=192.168.1.24

l 基于Cookie的断言工厂

CookieRoutePredicateFactory:接收两个参数,cookie 名字和一个正则表达式。 判断请求

cookie是否具有给定名称且值与正则表达式匹配。

-Cookie=chocolate, ch.

l 基于Header的断言工厂

HeaderRoutePredicateFactory:接收两个参数,标题名称和正则表达式。 判断请求Header是否

具有给定名称且值与正则表达式匹配。

-Header=X-Request-Id, \d+

l 基于Host的断言工厂

HostRoutePredicateFactory:接收一个参数,主机名模式。判断请求的Host是否满足匹配规则。

-Host=**.testhost.org

l 基于Method请求方法的断言工厂

MethodRoutePredicateFactory:接收一个参数,判断请求类型是否跟指定的类型匹配。

-Method=GET

l 基于Path请求路径的断言工厂

PathRoutePredicateFactory:接收一个参数,判断请求的URI部分是否满足路径规则。

-Path=/foo/{segment}基于Query请求参数的断言工厂

QueryRoutePredicateFactory :接收两个参数,请求param和正则表达式, 判断请求参数是否具

有给定名称且值与正则表达式匹配。

-Query=baz, ba.

l 基于路由权重的断言工厂

WeightRoutePredicateFactory:接收一个[组名,权重], 然后对于同一个组内的路由按照权重转发 

内置断言的使用

4.自定义断言

搜索文件

复制,重建,修改

自定义age的断言

package com.example.config;//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
import java.time.ZonedDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import javax.validation.constraints.NotNull;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.GatewayPredicate;
import org.springframework.http.HttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;
@Component
public class AgeRoutePredicateFactory extends AbstractRoutePredicateFactory<AgeRoutePredicateFactory.Config> {public static final String MIN_AGE = "minAge";public static final String MAX_AGE = "maxAge";public AgeRoutePredicateFactory() {super(Config.class);}public List<String> shortcutFieldOrder() {return Arrays.asList("minAge", "maxAge");}public Predicate<ServerWebExchange> apply(final Config config) {// Assert.isTrue(config.getDatetime1().isBefore(config.getDatetime2()), config.getDatetime1() + " must be before " + config.getDatetime2());return new GatewayPredicate() {public boolean test(ServerWebExchange serverWebExchange) {// 年龄是不是在最小值和最大值之间// age 作为一个参数传过来ServerHttpRequest request = serverWebExchange.getRequest();List<String> age = request.getQueryParams().get("age");System.out.println("________________________"+age);String s = age.get(0);int i = Integer.parseInt(s);// 》=minAge&&<=maxAgereturn i>=config.getMinAge()&&i<= config.getMaxAge(); // true   false}
//            public String toString() {
//                return String.format("Between: %s and %s", config.getDatetime1(), config.getDatetime2());
//            }};}@Validatedpublic static class Config {private @NotNull Integer minAge;private @NotNull Integer maxAge;public Config() {}public Integer getMinAge() {return minAge;}public void setMinAge(Integer minAge) {this.minAge = minAge;}public Integer getMaxAge() {return maxAge;}public void setMaxAge(Integer maxAge) {this.maxAge = maxAge;}}
}

修改yml

5.内置局部过滤器

局部过滤器是针对单个路由的过滤器。

在SpringCloud Gateway中内置了很多不同类型的网关路由过滤器。

https://www.cnblogs.com/zhaoxiangjun/p/13042189.html

过滤器工厂

作用

参数

AddRequestHeader

为原始请求添加Header

Header的名称及值

AddRequestParameter

为原始请求添加请求参数

参数名称及值

AddResponseHeader

为原始响应添加Header

Header的名称及值

DedupeResponseHeader

剔除响应头中重复的值

需要去重的Header名称及去重策略

Hystrix

为路由引入Hystrix的断路器保护

HystrixCommand的名称

FallbackHeaders

为fallbackUri的请求头中添加具体的异常信息

Header的名称

PrefixPath

为原始请求路径添加前缀

前缀路径

PreserveHostHeader

为请求添加一个preserveHostHeader=true的属性,路由过滤器会检查该属性以决定是否要发送原始的Host

RequestRateLimiter

用于对请求限流,限流算法为令牌桶

keyResolver、rateLimiter、statusCode、denyEmptyKey、emptyKeyStatus

RedirectTo

将原始请求重定向到指定的URL

http状态码及重定向的url

RemoveHopByHopHeadersFilter

为原始请求删除IETF组织规定的一系列Header

默认就会启用,可以通过配置指定仅删除哪些Header

RemoveRequestHeader

为原始请求删除某个Header

Header名称

RemoveResponseHeader

为原始响应删除某个Header

Header名称

RewritePath

重写原始的请求路径

原始路径正则表达式以及重写后路径的正则表达式

RewriteResponseHeader

重写原始响应中的某个Header

Header名称,值的正则表达式,重写后的值

SaveSession

在转发请求之前,强制执行WebSession::save操作

secureHeaders

为原始响应添加一系列起安全作用的响应头

无,支持修改这些安全响应头的值

SetPath

修改原始的请求路径

修改后的路径

SetResponseHeader

修改原始响应中某个Header的值

Header名称,修改后的值

SetStatus

修改原始响应的状态码

HTTP 状态码,可以是数字,也可以是字符串

StripPrefix

用于截断原始请求的路径

使用数字表示要截断的路径的数量

Retry

针对不同的响应进行重试

retries、statuses、methods、series

RequestSize

设置允许接收最大请求包的大小。如果请求包大小超过设置的值,则返回 413 Payload Too Large

请求包大小,单位为字节,默认值为5M

ModifyRequestBody

在转发请求之前修改原始请求体内容

修改后的请求体内容

ModifyResponseBody

修改原始响应体的内容

修改后的响应体内容

Default

为所有路由添加过滤器

过滤器工厂名称及值

内置局部过滤器的使用

6.自定义局部过滤器

搜索文件

能满足需要就直接用,满足不了需求就复制重写

修改yml文件 修改测试类

访问

7.内置全局过滤器

全局过滤器作用于所有路由, 无需配置。通过全局过滤器可以实现对权限的统一校验,安全性验证等功能。

SpringCloud Gateway内部也是通过一系列的内置全局过滤器对整个路由转发进行处理如下:

全局过滤器

作用

Combined Global Filter and GatewayFilter Ordering

对过滤器执行顺序进行排序

Forward Routing Filter

用于本地forward,也就是将请求在Gateway服务内进行转发,而不是转发到下游服务

Netty Routing Filter

使用Netty的 HttpClient 转发http、https请求

Netty Write Response Filter

将代理响应写回网关的客户端侧

RouteToRequestUrl Filter

将从request里获取的原始url转换成Gateway进行请求转发时所使用的url

Websocket Routing Filter

使用Spring Web Socket将转发 Websocket 请求

Gateway Metrics Filter

整合监控相关,提供监控指标

Marking An Exchange As Routed

防止重复的路由转发

8.自定义全局过滤器

内置的过滤器已经可以完成大部分的功能,但是对于企业开发的一些业务功能处理,还是需要我们自己编写过滤器来实现的,那么我们一起通过代码的形式自定义一个过滤器,去完成统一的认证校验。

开发中的鉴权逻辑:

l 当客户端第一次请求服务时,服务端对用户进行信息认证(登录)

l 认证通过,将用户信息进行加密形成token,返回给客户端,作为登录凭证

l 以后每次请求,客户端都携带认证的token

l 服务端对token进行解密,判断是否有效。

如上图,对于验证用户是否已经登录鉴权的过程可以在网关统一检验。

检验的标准就是请求中是否携带token凭证以及token的正确性。

下面的我们自定义一个GlobalFilter,去校验所有请求的请求参数中是否包含“token”,如何不包含请求参数“token”则不转发路由,否则执行正常的逻辑

自定义全局过滤器 要求:必须实现GlobalFilter,Ordered接口

创建配置文件

package com.example.filter;
import cn.hutool.json.JSONUtil;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.sun.xml.internal.ws.api.ha.HaInfo;
import org.apache.http.HttpResponse;
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.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
@Component
public class MyGlobalFilter implements GlobalFilter, Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {/*** token* 有 放行* 没有 json数据  code 500  msg ”“ ,data:null*/String token = exchange.getRequest().getHeaders().getFirst("token");// token不为空if(StringUtils.isNotBlank(token)){// 放行return  chain.filter(exchange);// 走下面的过滤器}else{// 返回json数据Map map =new HashMap<>();map.put("code",500);map.put("msg","错误!!!");map.put("data","sdfjdvhgs");// 转化为json数据String s = JSONUtil.toJsonStr(map);// 返回json数据ServerHttpResponse response = exchange.getResponse();//
//            Mono<Void> voidMono = response.setComplete();DataBuffer dataBuffer;try {byte[] bytes = s.getBytes("utf8");dataBuffer = response.bufferFactory().wrap(bytes);} catch (UnsupportedEncodingException e) {throw new RuntimeException(e);}return response.writeWith(Mono.just(dataBuffer));}//return null;}/**** @return*/@Overridepublic int getOrder() {return 0;}
}

测试访问

token为空不能访问 返回json数据 ,token有值可以访问

9.简写版yml

修改yml文件

spring:cloud:gateway:discovery:locator:enabled: truelower-case-service-id: true

enabled 表示 根据微服务的名字进行转发

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

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

相关文章

Spring Boot中配置文件生效位置

1. 配置文件位置 首先小伙伴们要明白&#xff0c;Spring Boot 默认加载的配置文件是 application.properties 或者 application.yaml&#xff0c;properties优先级高于yaml。默认的加载位置一共有五个&#xff0c;五个位置可以分为两类&#xff1a; 从 classpath 下加载&…

搭建内部知识库,解决企业内部琐碎信息问题

企业内部面临着大量琐碎的信息&#xff0c;这些信息可能分散在各个部门、员工之间&#xff0c;导致查找和共享变得困难。这种情况下&#xff0c;搭建一个内部知识库可以解决这一问题。通过内部知识库&#xff0c;企业可以将琐碎的信息整理、分类&#xff0c;并提供一个集中存储…

【信息安全】浅谈IDOR越权漏洞的原理、危害和防范:直接对象引用导致的越权行为

前言 ┌──────────────────────────────────┐ │ 正在播放《越权访问》 - Hanser │ ●━━━━━━─────── 00:00 / 03:05 │ ↻ ◁ ❚❚ ▷ ⇆ └───────────────────────────────…

Java拼图游戏

运行出的游戏界面如下&#xff1a; 按住A不松开&#xff0c;显示完整图片&#xff1b;松开A显示随机打乱的图片。 User类 package domain;/*** ClassName: User* Author: Kox* Data: 2023/2/2* Sketch:*/ public class User {private String username;private String password…

Michael Jordan最新报告:去中心化机器学习中的契约、不确定性和激励

‍ ‍导读 11月3日&#xff0c;智源研究院学术顾问委员会委员、机器学习泰斗Michael Jordan在以“新一代人工智能前沿”为主题的2023北京论坛 新工科专题论坛上&#xff0c;发表了题为Contracts, Uncertainty, and Incentives in Decentralized Machine Learning&#xff08;去…

Thrift协议详解

前言特点高效性的体现可拓展性的体现 应用场景示例拓展其他常用协议接口描述语言&#xff08;IDL&#xff09;TBinaryProtocolTCompactProtocolTDebugProtocolTDenseProtocolTJSONProtocol 前言 Thrift协议是一种接口描述语言和二进制通讯协议&#xff0c;它被用来定义和创建跨…

Linux procps-ng - top

procps-ng 是一个开源的进程管理工具集&#xff0c;它提供了一系列用于监控和管理系统进程的命令行工具。它是 procps 工具集的一个分支&#xff0c;旨在改进和增强原有的 procps 工具。 procps-ng 包括了一些常用的命令行工具&#xff0c;例如&#xff1a; ps&#xff1a;用于…

SVG的viewBox、width和height释义, 示例及代码

svg的是没有边界的&#xff0c;svg画布只是用于展示svg世界中某一个范围的内容&#xff0c;而对于超过了svg画布范围的内容&#xff0c;则会被遮挡。默认svg画布默认显示世界坐标下原点坐标的width*height面积的矩形视野。 ​ 我们可以通过viewBox来修改默认的显示配置&#…

测不准原理

测不准原理 算符的对易关系 commutation relation 测不准原理的矢量推导 Schwarz inequality: 设对易关系&#xff1a; 设一个新态&#xff1a; 投影&#xff1a; 那么有&#xff1a; 代回Schwarz inequality 即可证明&#xff1a;

创建谷歌账号 绕过手机验证(2023.11亲测有效)

如何成功注册谷歌账号&#xff1a;一个详细实用指南 写在最前面谷歌注册全流程环境配置切换至全英文环境 开通foxmail.com邮箱在英文环境下注册验证邮箱注册过程中的注意事项完成&#xff01;总结 写在最前面 在这个数字化迅速发展的时代&#xff0c;谷歌账号几乎成为了我们日…

Linux非阻塞等待示例

Linux非阻塞等待实例 非阻塞等待的意义&#xff1a;简单的多进程编程示例代码解释 非阻塞等待的意义&#xff1a; 非阻塞等待在多进程编程中的意义主要体现在提高系统的响应性、实现异步任务执行、动态任务管理和多任务协同工作等方面。它允许父进程在等待子进程退出的同时&…

windows nodejs 15.0.0下载安装

下载 Node v15.0.0 (Current) | Node.js (nodejs.org) 下载地址 https://nodejs.org/dist/v15.0.0/node-v15.0.0-x64.msi 安装 双击运行 等待安装完成 确认安装成功 管理员运行cmd 查看版本号

python算法例15 合并数字

1. 问题描述 给出n个数&#xff0c;将这n个数合并成一个数&#xff0c;每次只能选择两个数a、b合并&#xff0c;合并需要消耗的能量为ab&#xff0c;输出将n个数合并成一个数后消耗的最小能量。 2. 问题示例 给出[1&#xff0c;2&#xff0c;3&#xff0c;4]&#xff0c;返回…

【作业】操作系统实验一:进程和线程

文章目录 实验内容一、进程的创建1、编辑源程序2、编辑结果3、编译和运行程序4、解释运行结果 二、进程共享1、运行2、解释运行结果 三、进程终止1、运行2、解释运行结果 四、进程同步1、运行2、解释运行结果 五、Linux中子进程映像的重新装入1、运行2、解释运行结果 六、线程1…

多因素方差分析(Multi-way Analysis of Variance) R实现

1, data0507 flower 是某种植物在两个海拔和两个气温下的开花高度&#xff0c;采用合适 的统计方法&#xff0c;检验该种植物的开花高度在不同的海拔之间和不同的气温之间有无差异&#xff1f;如果有差异&#xff0c;具体如何差异的&#xff1f;&#xff08;说明依据、结论等关…

GSVA,GSEA,KEGG,GO学习

目录 GSVA 1&#xff1a;获取注释基因集 2&#xff1a;运行 GSEA 1,示例数据集 2,运行 GSEA_KEGG富集分析 GSEA_GO富集分析 DO数据库GSEA MSigDB数据库选取GSEA KEGG 1&#xff1a;运行 2&#xff1a;绘图 bar图 气泡图 绘图美化 GO GSVA 1&#xff1a;获取注…

【网络通信】探索UDP与TCP协议、IP地址和端口号的奥妙

&#x1f33a;个人主页&#xff1a;Dawn黎明开始 &#x1f380;系列专栏&#xff1a;网络奇幻之旅 ⭐每日一句&#xff1a;往前走&#xff0c;朝着光 &#x1f4e2;欢迎大家&#xff1a;关注&#x1f50d;点赞&#x1f44d;评论&#x1f4dd;收藏⭐️ 文章目录 &#x1f4cb;前…

4.2 Windows驱动开发:内核中进程线程与模块

内核进程线程和模块是操作系统内核中非常重要的概念。它们是操作系统的核心部分&#xff0c;用于管理系统资源和处理系统请求。在驱动安全开发中&#xff0c;理解内核进程线程和模块的概念对于编写安全的内核驱动程序至关重要。 内核进程是在操作系统内核中运行的程序。每个进…

可燃气体监测仪|燃气管网监测解决办法

可燃气体监测仪是城市生命线中&#xff0c;燃气监测运行系统的前端监测设备&#xff0c;其主要作用是对燃气管网的安全状况进行实时监测。燃气管道在使用过程中&#xff0c;由于老化、裂纹、锈蚀等问题&#xff0c;容易导致燃气出现泄漏问题&#xff0c;从而引发一系列的安全事…

MySQL/Oracle用逗号分割的id怎么实现in (逗号分割的id字符串)。find_in_set(`id`, ‘1,2,3‘) 函数,

1.MySQL 1.1.正确写法 select * from student where find_in_set(s_id, 1,2,3); 1.2.错误示范 select * from student where find_in_set(s_id, 1,2 ,3); -- 注意&#xff0c;中间不能有空格。1、3 select * from student where find_in_set(s_id, 1,2, 3); -- 注意…