Spring Cloud Gateway 扩展支持动态限流
之前分享过 一篇 《Spring Cloud Gateway 原生的接口限流该怎么玩》, 核心是依赖Spring Cloud Gateway 默认提供的限流过滤器来实现
原生RequestRateLimiter 的不足
- 配置方式
spring: cloud: gateway: routes: - id: requestratelimiter_route uri: lb://pigx-upms order: 10000 predicates: - Path=/admin/** filters: - name: RequestRateLimiter args: redis-rate-limiter.replenishRate: 1 redis-rate-limiter.burstCapacity: 3 key-resolver: "#{@remoteAddrKeyResolver}" #SPEL表达式去的对应的bean - StripPrefix=1
- RequestRateLimiterGatewayFilterFactory
public GatewayFilter apply(Config config) { KeyResolver resolver = getOrDefault(config.keyResolver, defaultKeyResolver); RateLimiter<object> limiter = getOrDefault(config.rateLimiter, defaultRateLimiter); boolean denyEmpty = getOrDefault(config.denyEmptyKey, this.denyEmptyKey); HttpStatusHolder emptyKeyStatus = HttpStatusHolder .parse(getOrDefault(config.emptyKeyStatus, this.emptyKeyStatusCode)); return (exchange, chain) -> { return exchange.getResponse().setComplete(); }); }); }; }
-
在实际生产过程中,必定不能满足我们的需求
生产中路由信息是保存数据库持久化或者配置中心,
RequestRateLimiterGatewayFilterFactory
并不能随着持久化数据的改变而动态改变限流参数,不能做到实时根据流量来改变流量阈值
Sentinel Spring Cloud Gateway 流控支持
Sentinel 是什么?
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性,分布式系统的流量防卫兵。
从 1.6.0 版本开始,Sentinel 提供了 Spring Cloud Gateway 的适配模块,可以提供两种资源维度的限流: route 维度:即在 Spring 配置文件中配置的路由条目,资源名为对应的 routeId 自定义 API 维度:用户可以利用 Sentinel 提供的 API 来自定义一些 API 分组
pom 依赖
<!--Spring Cloud Alibaba 封装的 sentinel 模块--> <dependency> <groupid>com.alibaba.cloud</groupid> <artifactid>spring-cloud-alibaba-sentinel-gateway</artifactid> </dependency> <!--使用nacos 保存限流规则--> <dependency> <groupid>com.alibaba.csp</groupid> <artifactid>sentinel-datasource-nacos</artifactid> </dependency>
配置本地路由规则及其sentinel数据源
spring: application: name: sentinel-spring-cloud-gateway cloud: gateway: enabled: true discovery: locator: lower-case-service-id: true routes: - id: pigx_route uri: https://api.readhub.cn predicates: - Path=/topic/** sentinel: datasource.ds1.nacos: server-addr: 127.0.0.1:8848 data-id: gw-flow group-id: DEFAULT_GROUP ruleType: gw-api-group filter: enabled: true
配置nacos数据源中的限流策略
- 常用限流策略 常量
以客户端IP作为限流因子 public static final int PARAM_PARSE_STRATEGY_CLIENT_IP = 0; 以客户端HOST作为限流因子 public static final int PARAM_PARSE_STRATEGY_HOST = 1; 以客户端HEADER参数作为限流因子 public static final int PARAM_PARSE_STRATEGY_HEADER = 2; 以客户端请求参数作为限流因子 public static final int PARAM_PARSE_STRATEGY_URL_PARAM = 3; 以客户端请求Cookie作为限流因子 public static final int PARAM_PARSE_STRATEGY_COOKIE = 4;
- 核心源码解析 SentinelGatewayFilter
sentinel通过扩展Gateway的过滤器,通过选择的不同GatewayParamParser
过处理请求限流因子和数据源中的配置进行比较 源码如下:
public Mono<void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { Route route = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR); Mono<void> asyncResult = chain.filter(exchange); if (route != null) { String routeId = route.getId(); Object[] params = paramParser.parseParameterFor(routeId, exchange, r -> r.getResourceMode() == SentinelGatewayConstants.RESOURCE_MODE_ROUTE_ID); String origin = Optional.ofNullable(GatewayCallbackManager.getRequestOriginParser()) .map(f -> f.apply(exchange)) .orElse(""); asyncResult = asyncResult.transform( new SentinelReactorTransformer<>(new EntryConfig(routeId, EntryType.IN, 1, params, new ContextConfig(contextName(routeId), origin))) ); } Set<string> matchingApis = pickMatchingApiDefinitions(exchange); for (String apiName : matchingApis) { Object[] params = paramParser.parseParameterFor(apiName, exchange, r -> r.getResourceMode() == SentinelGatewayConstants.RESOURCE_MODE_CUSTOM_API_NAME); asyncResult = asyncResult.transform( new SentinelReactorTransformer<>(new EntryConfig(apiName, EntryType.IN, 1, params)) ); } return asyncResult; }
效果演示
-
以上nacos 配置为 每秒只能通过5个请求,我们使用
jmeter 4.0
来并发10个线程测试一下 -
通过上图可以结果证明sentinel限流确实有效
动态修改限流参数
sentinel-datasource-nacos
作为sentinel的数据源,可以从如上 nacos 管理台实时刷新限流参数及其阈值- 目前sentinel dashboard 1.6.2 暂未实现gateway 流控图形化控制 ,
1.7.0
会增加此功能
总结
欢迎关注我们获得更多的好玩JavaEE 实践
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
通过OpenGL理解前端渲染原理(1)
通过OpenGL理解前端渲染原理,本文着重介绍渲染管线工作流程。 一、OpenGL OpenGL,是一套绘制3D图形的API,当然它也可以用来绘制2D的物体。OpenGL有一大套可以用来操作模型和图片的函数,通常编写OpenGL库的人是显卡的制造者。我们买的显卡都支持特定版本的OpenGL。 下图是用OpenGL做的旋转的立方体。 二、渲染原理 2.1 渲染管道 在OpenGL中,所有东西都在一个3D的空间里,而我们的屏幕和窗口都是2D的,所以OpenGL需要将3D的坐标转换成2D的坐标,做这件事的是OpenGL中的渲染管道(graphics pipeline)。 渲染管道可以分成两大部分:第一部分将3D坐标转换成2D坐标;第二部分把2D的坐标转换成实际的像素。 2.2 着色器 通常来说,渲染管道把一组3D坐标转换成屏幕上带有颜色的2D像素需要经过很多步。上一步的输出作为下一步的输入,所有步骤都是高度专一的,每步都有一个特定的函数,且可以很容易地并发执行。显卡有数千个处理核心来快速处理渲染管道中的数据,而这些是在每个步骤中通过运行在GPU上的多个小程序来处理的,这些小的程序被称之为程序...
- 下一篇
JAVA并发容器-ConcurrentHashMap 1.7和1.8 源码解析
HashMap是一个线程不安全的类,在并发情况下会产生很多问题,详情可以参考HashMap 源码解析;HashTable是线程安全的类,但是它使用的是synchronized来保证线程安全,线程竞争激烈的情况下效率非常低下。在jdk1.5的时候引入了ConcurrentHashMap,这也是一个线程安全的类,它使用了分段锁的技术来提升并发访问效率。 HashTable容器在竞争激烈的并发环境下表现出效率低下的原因是所有访问HashTable的 线程都必须竞争同一把锁,假如容器里有多把锁,每一把锁用于锁容器其中一部分数据,那么 当多线程访问容器里不同数据段的数据时,线程间就不会存在锁竞争,从而可以有效提高并 发访问效率,这就是ConcurrentHashMap所使用的锁分段技术。 在jdk1.7及以前ConcurrentHashMap采用Segment数组结构和HashEntry数组结构组成,之后采用的是和HashMap一样的结构。 ConcurrentHashMap jdk1.7 结构图 采用Segment数组结构和HashEntry数组结构组成,Segment数组的大小就是Concu...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS8编译安装MySQL8.0.19
- MySQL8.0.19开启GTID主从同步CentOS8
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS7,CentOS8安装Elasticsearch6.8.6
- Red5直播服务器,属于Java语言的直播服务器
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- CentOS6,CentOS7官方镜像安装Oracle11G