Spring Cloud Gateway 整合阿里 Sentinel 网关限流实战

开发 前端
Spring Cloud Gateway本身自带的限流实现,过滤器是RequestRateLimiterGatewayFilterFactory,不过这种上不了台面的就不再介绍了,有兴趣的可以实现下。

[[433195]]

前一篇文章介绍了Spring Cloud Gateway的一些基础知识点,今天陈某就来唠一唠网关层面如何做限流?

文章目录如下:

网关如何限流?

Spring Cloud Gateway本身自带的限流实现,过滤器是RequestRateLimiterGatewayFilterFactory,不过这种上不了台面的就不再介绍了,有兴趣的可以实现下。

今天的重点是集成阿里的Sentinel实现网关限流,sentinel有不懂的可以看陈某的文章:阿里限流神器Sentinel夺命连环 17 问?

从1.6.0版本开始,Sentinel提供了SpringCloud Gateway的适配模块,可以提供两种资源维度的限流:

  • route维度:即在配置文件中配置的路由条目,资源名为对应的routeId,这种属于粗粒度的限流,一般是对某个微服务进行限流。
  • 自定义API维度:用户可以利用Sentinel提供的API来自定义一些API分组,这种属于细粒度的限流,针对某一类的uri进行匹配限流,可以跨多个微服务。

sentinel官方文档:https://github.com/alibaba/Sentinel/wiki/%E7%BD%91%E5%85%B3%E9%99%90%E6%B5%81

Spring Cloud Gateway集成Sentinel实现很简单,这就是阿里的魅力,提供简单、易操作的工具,让程序员专注于业务。

新建项目

新建一个gateway-sentinel9026模块,添加如下依赖:

  1. <!--nacos注册中心--> 
  2.     <dependency> 
  3.       <groupId>com.alibaba.cloud</groupId> 
  4.       <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> 
  5.     </dependency> 
  6.  
  7.     <!--spring cloud gateway--> 
  8.     <dependency> 
  9.       <groupId>org.springframework.cloud</groupId> 
  10.       <artifactId>spring-cloud-starter-gateway</artifactId> 
  11.     </dependency> 
  12.  
  13.     <!--    spring cloud gateway整合sentinel的依赖--> 
  14.     <dependency> 
  15.       <groupId>com.alibaba.cloud</groupId> 
  16.       <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId> 
  17.     </dependency> 
  18.  
  19.     <!--    sentinel的依赖--> 
  20.     <dependency> 
  21.       <groupId>com.alibaba.cloud</groupId> 
  22.       <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> 
  23.     </dependency> 

注意:这依然是一个网关服务,不要添加WEB的依赖

配置文件

配置文件中主要指定以下三种配置:

  • nacos的地址
  • sentinel控制台的地址
  • 网关路由的配置

配置如下:

  1. spring: 
  2.   cloud: 
  3.     ## 整合sentinel,配置sentinel控制台的地址 
  4.     sentinel: 
  5.       transport: 
  6.         ## 指定控制台的地址,默认端口8080 
  7.         dashboard: localhost:8080 
  8.     nacos: 
  9.       ## 注册中心配置 
  10.       discovery: 
  11.         # nacos的服务地址,nacos-server中IP地址:端口号 
  12.         server-addr: 127.0.0.1:8848 
  13.     gateway: 
  14.       ## 路由 
  15.       routes: 
  16.         ## id只要唯一即可,名称任意 
  17.         - id: gateway-provider 
  18.           uri: lb://gateway-provider 
  19.           ## 配置断言 
  20.           predicates: 
  21.             ## Path Route Predicate Factory断言,满足/gateway/provider/**这个请求路径的都会被路由到http://localhost:9024这个uri中 
  22.             - Path=/gateway/provider/** 

上述配置中设置了一个路由gateway-provider,只要请求路径满足/gateway/provider/**都会被路由到gateway-provider这个服务中。

限流配置

经过上述两个步骤其实已经整合好了Sentinel,此时访问一下接口:http://localhost:9026/gateway/provider/port

然后在sentinel控制台可以看到已经被监控了,监控的路由是gateway-provider,如下图:

此时我们可以为其新增一个route维度的限流,如下图:

上图中对gateway-provider这个路由做出了限流,QPS阈值为1。

此时快速访问:http://localhost:9026/gateway/provider/port,看到已经被限流了,如下图:

以上route维度的限流已经配置成功,小伙伴可以自己照着上述步骤尝试一下。

API分组限流也很简单,首先需要定义一个分组,API管理-> 新增API分组,如下图:

匹配模式选择了精确匹配(还有前缀匹配,正则匹配),因此只有这个uri:http://xxxx/gateway/provider/port会被限流。

第二步需要对这个分组添加流控规则,流控规则->新增网关流控,如下图:

API名称那里选择对应的分组即可,新增之后,限流规则就生效了。

陈某不再测试了,小伙伴自己动手测试一下吧...............

陈某这里只是简单的配置一下,至于限流规则持久化一些内容请看陈某的Sentinel文章,这里就不再过多的介绍了。

如何自定义限流异常信息?

从上面的演示中可以看到默认的异常返回信息是:"Block.........",这种肯定是客户端不能接受的,因此需要定制自己的异常返回信息。

下面介绍两种不同的方式定制异常返回信息,开发中自己选择其中一种。

直接配置文件中定制

开发者可以直接在配置文件中直接修改返回信息,配置如下:

  1. spring: 
  2.   cloud: 
  3.     ## 整合sentinel,配置sentinel控制台的地址 
  4.     sentinel: 
  5.       #配置限流之后,响应内容 
  6.       scg: 
  7.         fallback: 
  8.           ## 两种模式,一种是response返回文字提示信息, 
  9.           ## 一种是redirect,重定向跳转,需要同时配置redirect(跳转的uri) 
  10.           mode: response 
  11.           ## 响应的状态 
  12.           response-status: 200 
  13.           ## 响应体 
  14.           response-body: '{"code": 200,"message": "请求失败,稍后重试!"}' 

上述配置中mode配置的是response,一旦被限流了,将会返回JSON串。

  1.     "code": 200, 
  2.     "message""请求失败,稍后重试!" 

重定向的配置如下:

  1. spring: 
  2.   cloud: 
  3.     ## 整合sentinel,配置sentinel控制台的地址 
  4.     sentinel: 
  5.       #配置限流之后,响应内容 
  6.       scg: 
  7.         fallback: 
  8.           ## 两种模式,一种是response返回文字提示信息,一种是redirect,重定向跳转,需要同时配置redirect(跳转的uri) 
  9.           mode: redirect 
  10.           ## 跳转的URL 
  11.           redirect: http://www.baidu.com 

一旦被限流,将会直接跳转到:http://www.baidu.com

编码定制

这种就不太灵活了,通过硬编码的方式,完整代码如下:

  1. @Configuration 
  2. public class GatewayConfig { 
  3.     /** 
  4.      * 自定义限流处理器 
  5.      */ 
  6.     @PostConstruct 
  7.     public void initBlockHandlers() { 
  8.         BlockRequestHandler blockHandler = (serverWebExchange, throwable) -> { 
  9.             Map map = new HashMap(); 
  10.             map.put("code",200); 
  11.             map.put("message","请求失败,稍后重试!"); 
  12.             return ServerResponse.status(HttpStatus.OK) 
  13.                     .contentType(MediaType.APPLICATION_JSON_UTF8) 
  14.                     .body(BodyInserters.fromObject(map)); 
  15.         }; 
  16.         GatewayCallbackManager.setBlockHandler(blockHandler); 
  17.     } 

两种方式介绍完了,根据业务需求自己选择适合的方式,当然陈某更喜欢第一种,理由:约定>配置>编码。

网关限流了,服务就安全了吗?

很多人认为只要网关层面做了限流,躲在身后的服务就可以高枕无忧了,你是不是也有这种想法?

很显然这种想法是错误的,复杂的微服务架构一个独立服务不仅仅被一方调用,往往是多方调用,如下图:

商品服务不仅仅被网关层调用,还被内部订单服务调用,这时候仅仅在网关层限流,那么商品服务还安全吗?

一旦大量的请求订单服务,比如大促秒杀,商品服务不做限流会被瞬间击垮。

因此需要根据公司业务场景对自己负责的服务也要进行限流兜底,最常见的方案:网关层集群限流+内部服务的单机限流兜底,这样才能保证不被流量冲垮。

总结 

文章介绍了Spring Cloud Gateway整合Sentinel对网关层进行限流,以及关于限流的一些思考。

责任编辑:武晓燕 来源: 码猿技术专栏
相关推荐

2021-05-21 08:30:26

Sentinel GateWay 微服务

2024-09-06 13:53:28

2024-04-03 08:08:15

谓词网关开发

2022-04-11 07:34:46

OAuth2UAA节点

2022-05-12 08:21:13

项目网关模块

2021-03-16 08:31:59

微服务Sentinel雪崩效应

2023-04-26 09:16:17

2023-11-09 08:31:56

Spring微服务网关

2022-05-03 19:38:15

限流微服务Sentinel

2023-02-13 08:10:40

Gateway网关Spring

2023-04-14 09:01:25

2023-09-15 08:18:49

cookie网关代理

2018-12-19 15:05:55

Spring Clou网关 Gateway

2022-01-07 07:29:08

Rbac权限模型

2022-05-19 10:52:20

云原生网关技术

2023-03-08 09:03:55

2023-09-12 07:19:06

微服务网关架构

2021-05-14 07:45:07

Sentinel 接口限流

2022-05-29 21:38:11

限流熔断流量

2022-05-09 07:35:48

动态集群限流
点赞
收藏

51CTO技术栈公众号