热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

SpringCloudGateway集成Sentinel规则持久化以及自定义谓词和filter(过滤器)

springCloudGateway集成ribbon负载均衡:  gateway集成ribbon的原理是在全局LoadBalancerClientF

spring Cloud Gateway集成ribbon负载均衡:

  gateway集成ribbon的原理是在全局LoadBalancerClientFilter中进行拦截,然后该过滤器当中依赖LoadBalancerClient loadBalancer,然而负载均衡接口的具体实现是RibbonLoadBalancerClient implements LoadBalancerClient,所以gateway已经整合了ribbon,实现了负载均衡,不需要任何处理网关对微服务的请求转发已经具有负载均衡。
过滤器当中依赖loadBalancerClient
RibbonLoadBalancerClient实现LoadBalanceeClient


Spring Cloud Gateway集成Sentinel:

  网关集成Sentinel是为了流控熔断降级
1、添加依赖

<!-- sentinel-spring-cloud-gateway-adapter -->

com.alibaba.csp</groupId>
sentinel-spring-cloud-gateway-adapter</artifactId>
1.7.2</version>
</dependency>
<!--sentinel-datasource-extension数据源扩展-->

com.alibaba.csp</groupId>
sentinel-datasource-extension</artifactId>
</dependency>
<!--sentinel数据持久化-->

com.alibaba.csp</groupId>
sentinel-datasource-nacos</artifactId>
</dependency>

2、添加Sentinel控制台配置

#sentinel dashboard管理后台
sentinel:
eager: true
transport:
dashboard: 192.168.25.1:8080
#配置sentinel规则持久化到nacos
datasource:
flow: #流控
nacos:
server-addr: 47.110.237.194:80
data-id: ${spring.application.name}-flow.json
group-id: DEFAULT_GROUP
rule-type: flow
data-type: json
degrade:
nacos: #降级
server-addr: 47.110.237.194:80
data-id: ${spring.application.name}-degrade.json
group-id: DEFAULT_GROUP
rule-type: degrade
data-type: json

3、在Spring容器当中配置一个Sentinel的全局过滤器

/**
* 配置一个Sentinel的全局过滤器;
* @return
*/

@Bean
@Order(-1)
public GlobalFilter sentinelGatewayFilter(){
return new SentinelGatewayFilter();
}

两种持久化规则:

  第一种:持久化到本地文件
  第二种:在application.yaml配置持久化规则

#配置sentinel规则持久化到nacos
datasource:
flow: #流控
nacos:
server-addr: 47.110.237.194:80
data-id: ${spring.application.name}-flow.json
group-id: DEFAULT_GROUP
rule-type: flow
data-type: json
degrade:
nacos: #降级
server-addr: 47.110.237.194:80
data-id: ${spring.application.name}-degrade.json
group-id: DEFAULT_GROUP
rule-type: degrade
data-type: json

在nacos配置中心配置流控规则:

[
{
"resource": "route1",
"controlBehavior": 0,
"count": 1.0,
"grade": 1,
"limitApp": "default",
"strategy": 0
}
,
{
"resource": "route2",
"controlBehavior": 0,
"count": 2.0,
"grade": 1,
"limitApp": "default",
"strategy": 0
}
,
{
"resource": "route3",
"controlBehavior": 0,
"count": 3.0,
"grade": 1,
"limitApp": "default",
"strategy": 0
}
]

Spring Cloud Gateway内部流程源码分析:

gateway流程
(1)根据自动装配spring-cloud-gateway-core.jar的spring.factories;
(2)GatewayClassPathWarningAutoConfiguration检查前端控制器;
(3)网关自动配置GatewayAutoConfiguration;
(4)RoutePredicateHandlerMapping.getHandlerInternal(…)获取Route;
(5)执行FilteringWebHandler


Spring Cloud Gateway自定义谓词:

  Spring Cloud Gateway内置了一系列的路由谓词工厂,但是如果这些内置的路由谓词工厂不能满足业务需求的话,可以自定义路由谓词工厂来实现特定的需求;
举例如下:
1、要求请求必须携带一个token,并且token值等于指定的值,才能访问;


自定义谓词具体步骤:

(1)首先定义一个配置类,用于承载配置参数;

cloud:
#配置网关
gateway:
discovery:
locator:
enabled: true #启用DiscoveryClient网关集成,可以实现服务的发现
#配置网关路由转发规则
routes:
- id: route1
uri: lb://29-nacos-discovery-customer
predicates: #谓词:判断,是不是?对不对?是否匹配?
- Path=/test2, /notFound-feign, /index, /echo
- Token=123456

(2)定义一个路由谓词工厂;
注:TokenRoutePredicateFactory类,前面的Token与.yml配置文件里面配置的名字对应,后面的RoutePredicateFactory名字是固定的,不能随便写,这是Spring Cloud Gateway的约定,类名须为“谓词工厂名(比如:Token)” + RoutePredicateFactory

@Slf4j
@Component
public class TokenRoutePredicateFactory extends AbstractRoutePredicateFactory<TokenConfig> {
public TokenRoutePredicateFactory() {
super(TokenConfig.class);
}
@Override
public List<String> shortcutFieldOrder() {
return Collections.singletonList("token");
}
@Override
public Predicate<ServerWebExchange> apply(TokenConfig tokenConfig) {
// (T t) -> true
return exchange -> {
MultiValueMap<String, String> valueMap = exchange.getRequest().getQueryParams();
boolean flag = false;
List<String> list = new ArrayList<>();
valueMap.forEach((k, v) -> {
list.addAll(v);
});
for (String s : list) {
log.info("Token -> {} ", s);
if (StringUtils.equalsIgnoreCase(s, tokenConfig.getToken())) {
flag = true;
break;
}
}
return flag;
};
}
}

结果如下所示


Spring Cloud Gateway谓词不匹配404处理:

处理的顶层接口是WebExceptionHandler
默认实现是DefaultErrorWebExceptionHandler
在这里插入图片描述

/**
* @author
* @Description: 自定义错误页面
* @date 2021/1/12 23:44
*/

public class MyErrorWebExceptionHandler extends DefaultErrorWebExceptionHandler {
/**
* Create a new {@code DefaultErrorWebExceptionHandler} instance.
*
* @param errorAttributes the error attributes
* @param resourceProperties the resources configuration properties
* @param errorProperties the error configuration properties
* @param applicationContext the current application context
*/

public MyErrorWebExceptionHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties, ErrorProperties errorProperties, ApplicationContext applicationContext) {
super(errorAttributes, resourceProperties, errorProperties, applicationContext);
}
/**
* 指定响应处理方法为JSON处理的方法
*
* @param errorAttributes
*/

@Override
protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
}
/**
* 根据code获取对应的HttpStatus
* @param errorAttributes
* @return
*/

@Override
protected int getHttpStatus(Map<String, Object> errorAttributes){
int status = (int)errorAttributes.get("status");
return status;
}
/**
* 构建异常信息
* @param request
* @param ex
* @return
*/

private String buildMessage(ServerRequest request, Throwable ex) {
StringBuilder message = new StringBuilder("Failed to handle request [");
message.append(request.methodName());
message.append(" ");
message.append(request.uri());
message.append("]");
if (ex != null) {
message.append(": ");
message.append(ex.getMessage());
}
return message.toString();
}
/**
* 构建返回的JSON数据格式
*
* @param status 状态码
* @param errorMessage 异常信息
* @return
*/

public static Map<String, Object> response(int status, String errorMessage) {
Map<String, Object> map = new HashMap<>();
map.put("status",status);
map.put("errorMessage",errorMessage);
map.put("data",null);
return map;
}
}

Spring Cloud Gateway全局过滤器:

在这里插入图片描述
  过滤器工厂是执行在指定路由之上,可以称为路由过滤器(或者局部过滤器),而全局过滤器是作用于所有的路由上,对所有的路由进行过滤;
  全局过滤器的顶层接口是GlobalFilter ,和GatewayFilter 有一样的接口定义,只不过GlobalFilter 会作用于所有路由;
  全局过滤器有执行顺序问题,通过getOrder()方法的返回值决定执行顺序,数值越小越靠前执行;

/**
* @author
* @Description: 自定义全局Filter
* @date 2021/1/13 0:16
*/

@Slf4j
@Component
public class CustomGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("自定义全局Filter......");
MultiValueMap<String, String> valueMap = exchange.getRequest().getQueryParams();
valueMap.forEach((k,v) -> {
log.info("全局filter参数: ,{}",k);
v.forEach( s -> {
log.info("全局filter参数值:,{}",s);
});
});
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}

Spring Cloud Gateway自定义网关路由过滤器:

  网关过滤器的顶层接口GatewayFilterFactory,通常继承AbstractGatewayFilterFactory实现自定义网关过滤器;或者继承AbstractNameValueGatewayFilterFactory,该方式配置方式更简单,然后覆盖里面的一个方法

/**
* @author
* @Description: 自定义过滤器
* @date 2021/1/12 23:56
*/

@Slf4j
@Component
public class RequestLogGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {
@Override
public GatewayFilter apply(NameValueConfig config) {
return (ServerWebExchange exchange, GatewayFilterChain chain) -> {
log.info("请求网关:,{},{}",config.getName(),config.getValue());
MultiValueMap<String, String> valueMap = exchange.getRequest().getQueryParams();
valueMap.forEach((k,v) -> {
log.info("自定义过滤器请求参数:{}",k);
v.forEach(s -> {
log.info("自定义过滤器请求参数值 {}",s);
});
});
return chain.filter(exchange);
};
}
}

cloud:
#配置网关
gateway:
discovery:
locator:
enabled: true #启用DiscoveryClient网关集成,可以实现服务的发现
#配置网关路由转发规则
routes:
- id: route1
uri: lb://29-nacos-discovery-customer
predicates: #谓词:判断,是不是?对不对?是否匹配?
- Path=/test2, /notFound-feign, /index
- Token=123456
filters:
- AddRequestParameter=color, black
- RequestLog=prefix, gatewaytest #自定义的filter

请求结果


Spring cloud gateway跨域CORS:

  CORS是一个W3C标准,全称是&#8221;跨域资源共享&#8221;(Cross-origin resource sharing),它允许浏览器向跨域的另一台服务器发出XMLHttpRequest请求,从而克服了AJAX只能访问同域名下的资源的限制。


同源与非同源的定义(跨域和不跨域):

  如果 访问协议、端口(如果指定了端口的话)、host都相同,则称之为同源(不跨域),否则为非同源(跨域);
源链接:http://www.mydown.com/soft/453/473302453.shtml
































URL是否同源原因
http://www.mydown.com/soft/227/1506342727.shtml
https://www.mydown.com/soft/453/473302453.shtml协议不同
http://www.mydown.com:81/soft/227/1506342727.shtml端口不同
http://www.bear20.com/window/4531/473302453.htmlhost不同

Spring Cloud Gateway解决跨域问题,只需要配置如下代码即可:

/**
* @author
* @Description: 解决跨域问题
* @date 2021/1/13 23:46
*/

@Configuration
public class CorsConfig {
@Bean
public CorsWebFilter corsWebFilter(){
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedMethod("*"); //是什么请求方法,比如 GET POST PUT DELETE .....
corsConfiguration.addAllowedOrigin("*"); //来自哪个域名的请求,*号表示所有
corsConfiguration.addAllowedHeader("*"); //是什么请求头
org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
source.registerCorsConfiguration("/**", corsConfiguration);
return new CorsWebFilter(source);
}
}


推荐阅读
  • 如何实现JDK版本的切换功能,解决开发环境冲突问题
    本文介绍了在开发过程中遇到JDK版本冲突的情况,以及如何通过修改环境变量实现JDK版本的切换功能,解决开发环境冲突的问题。通过合理的切换环境,可以更好地进行项目开发。同时,提醒读者注意不仅限于1.7和1.8版本的转换,还要适应不同项目和个人开发习惯的需求。 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • 开发笔记:spring boot项目打成war包部署到服务器的步骤与注意事项
    本文介绍了将spring boot项目打成war包并部署到服务器的步骤与注意事项。通过本文的学习,读者可以了解到如何将spring boot项目打包成war包,并成功地部署到服务器上。 ... [详细]
  • Spring框架《一》简介
    Spring框架《一》1.Spring概述1.1简介1.2Spring模板二、IOC容器和Bean1.IOC和DI简介2.三种通过类型获取bean3.给bean的属性赋值3.1依赖 ... [详细]
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • 本文介绍了在Python3中如何使用选择文件对话框的格式打开和保存图片的方法。通过使用tkinter库中的filedialog模块的asksaveasfilename和askopenfilename函数,可以方便地选择要打开或保存的图片文件,并进行相关操作。具体的代码示例和操作步骤也被提供。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • 本文介绍了深入浅出Linux设备驱动编程的重要性,以及两种加载和删除Linux内核模块的方法。通过一个内核模块的例子,展示了模块的编译和加载过程,并讨论了模块对内核大小的控制。深入理解Linux设备驱动编程对于开发者来说非常重要。 ... [详细]
  • 本文讨论了如何使用Web.Config进行自定义配置节的配置转换。作者提到,他将msbuild设置为详细模式,但转换却忽略了带有替换转换的自定义部分的存在。 ... [详细]
  • Vagrant虚拟化工具的安装和使用教程
    本文介绍了Vagrant虚拟化工具的安装和使用教程。首先介绍了安装virtualBox和Vagrant的步骤。然后详细说明了Vagrant的安装和使用方法,包括如何检查安装是否成功。最后介绍了下载虚拟机镜像的步骤,以及Vagrant镜像网站的相关信息。 ... [详细]
author-avatar
KisS汐唲
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有