前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >使用Sentinel对Spring MVC接口进行限流

使用Sentinel对Spring MVC接口进行限流

作者头像
码农小胖哥
发布于 2020-10-10 02:28:43
发布于 2020-10-10 02:28:43
2K00
代码可运行
举报
运行总次数:0
代码可运行

1.前言

Spring Cloud Alibaba提供了中间件Sentinel,它以流量为切入点,提供了流量控制、熔断降级、系统负载保护等多个功能来保护服务的稳定性。今天就来尝试一下。

本文是在 Spring Boot 2.3.4.RELEASE 的基础之上构建的

2.依赖引入

和其它教程通过Spring Cloud Starter引入的不同,这里使用更加底层一些的依赖引入来让我们深入的了解一些Sentinel,这里引入的是1.8.0版本。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!--Sentinel 核心包-->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-core</artifactId>
    <version>${sentinel.version}</version>
</dependency>
<!--@SentinelResource注解AOP切面支持-->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-annotation-aspectj</artifactId>
    <version>${sentinel.version}</version>
</dependency>
<!--针对Spring MVC的适配器 Spring Webflux 可引入对应的适配器-->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-spring-webmvc-adapter</artifactId>
    <version>${sentinel.version}</version>
</dependency>
<!--负责同 dashboard 进行通信  如果你没有使用 sentinel dashboard 它是可选的-->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-transport-simple-http</artifactId>
    <version>${sentinel.version}</version>
</dependency>

这里引入了SentinelSpring MVC的相关适配器和注解支持。

3. 使用

Sentinel的限流首先要制定限流规则,然后针对规则进行资源的标记。通过监控标记资源流量的 QPS 或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。

流控规则

规则被封装到FlowRule对象中,需要声明的属性说明如下:

属性

说明

默认值

resource

资源名,资源名是限流规则的作用对象,不建议使用默认值

count

限流阈值,可以是 QPS 阈值,也可以是并发线程数阈值

grade

限流阈值类型,QPS 模式(1)或并发线程数模式(0)

QPS 模式

limitApp

可针对性的对特定客户端的请求进行流控

default,代表不区分调用来源

strategy

调用关系限流策略:直接、链路、关联

根据资源本身(直接)

controlBehavior

流控效果(直接拒绝/WarmUp/匀速+排队等待),不支持按调用关系限流

直接拒绝

clusterMode

是否集群限流

下面定义了一个规则并加载到内存中:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 规则对应的类为FlowRule,用List保存,可以有多个规则
List<FlowRule> rules = new ArrayList<>();
FlowRule flowRule = new FlowRule();
// 设置资源名称
flowRule.setResource("bar");
// QPS为2
flowRule.setCount(2);
// 需要在限流过滤器中设置对应的解析策略来获取
// flowRule.setLimitApp(appName);
//限流的类型
flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
flowRule.setControlBehavior(CONTROL_BEHAVIOR_DEFAULT);
rules.add(flowRule);
FlowRuleManager.loadRules(rules);

上面这种硬编码方式 一般仅用于测试和演示,生产上一般通过动态规则源的方式来动态管理规则。详细参考官方文档中关于动态流控规则的描述[1]

标记限流资源

传统情况下使用SphU 包含了 try-catch 风格的 API 进行限流操作。当资源发生了限流之后会抛出 BlockException。这个时候可以捕捉异常,进行限流之后的逻辑处理。基本范式如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 1.5.0 版本开始可以利用 try-with-resources 特性(使用有限制)
// 资源名可使用任意有业务语义的字符串,比如方法名、接口名或其它可唯一标识的字符串。
try (Entry entry = SphU.entry("resourceName")) {
  // 被保护的业务逻辑
  // do something here...
} catch (BlockException ex) {
  // 资源访问阻止,被限流或被降级
  // 在此处进行相应的处理操作
}

这种样板代码并不是非常优雅,所以Sentinel提供了@SentinelResource注解来简化开发,需要依赖sentinel-annotation-aspectj模块并显式的启用AOP切面类:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Bean
public SentinelResourceAspect sentinelResourceAspect() {
    return new SentinelResourceAspect();
}

然后我们可以在Spring MVC接口上进行如下标记即可:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@SentinelResource(value = "bar", entryType = EntryType.IN)
@GetMapping("/bar")
public String bar() {
    return "bar";
}

无论异常处理还是注解都只建议在学习中使用,实际生产中配合sentinel-dashboard可以更加方便地、集中地进行标记配置限流资源。详情参考控制台文档[2]

全局配置

我们还可以通过SentinelWebInterceptor或者SentinelWebTotalInterceptor来配置一些全局特性。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package cn.felord.sentinel.configuration;

import com.alibaba.csp.sentinel.adapter.spring.webmvc.SentinelWebInterceptor;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.config.SentinelWebMvcConfig;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class GlobalSentinelWebMvcConfiguration implements WebMvcConfigurer {


    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        SentinelWebMvcConfig sentinelWebMvcConfig = new SentinelWebMvcConfig();
        //指定 请求方法 POST  GET 等等
        sentinelWebMvcConfig.setHttpMethodSpecify(true);
        //默认使用统一Web上下文   如果希望支持链路关系的流控策略则应该设置为false
        sentinelWebMvcConfig.setWebContextUnify(true);
        // 统一的 BlockException 处理  FlowException(BlockException) 会被 JVM 的 UndeclaredThrowableException 包裹一层  某种原因并不能捕获到异常
//        sentinelWebMvcConfig.setBlockExceptionHandler(new DefaultBlockExceptionHandler());
        // 用来标识来源 可针对性的对特定客户端的请求进行流控   limitApp
//        sentinelWebMvcConfig.setOriginParser(request -> request.getHeader("X-Client"));
 //       sentinelWebMvcConfig.setOriginParser(request -> request.getParameter("app"));

        //对原始的URL进行处理,比如去掉锚点之类的    /foo/bar?a=3#title  ->   /foo/bar?a=3
//        sentinelWebMvcConfig.setUrlCleaner( );
        registry.addInterceptor(new SentinelWebInterceptor(sentinelWebMvcConfig)).addPathPatterns("/**");
    }
}

流控规则中提到的limitApp就是通过setOriginParser 来配置获取策略的。

异常处理

虽然在全局配置中可以进行异常处理,但是经过胖哥测试提供的异常处理还是有些问题的,有时候无法捕捉到BlockException。我们可以通过控制器通知来切面捕获到它:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * 捕获BlockException异常.
 */
@Slf4j
@ControllerAdvice
@Order(0)
public class SentinelControllerAdvice {
    /**
     * 异常处理.
     *
     * @param request the request
     * @param e       the e
     * @return the object
     */
    @ExceptionHandler(BlockException.class)
    @ResponseBody
    public ResponseEntity<?> sentinelBlockHandler(HttpServletRequest request, BlockException e) {
        log.warn("Blocked by Sentinel: {}", e.getRule());
        // Return the customized result.
        HashMap<String, Object> map = new HashMap<>();
        map.put("path", request.getServletPath());
        map.put("msg", "limited by sentinel");
        return ResponseEntity.status(HttpStatus.TOO_MANY_REQUESTS).body(map);
    }
}

控制台

其实到这里限流功能已经可以使用了。不过配合控制台使用还是很简单的,先下载或者打包控制台的jar文件,通过下面的命令启动:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
java  -Dserver.port=8088     -jar .\sentinel-dashboard-1.8.0.jar

客户端这时就可以移除注解相关的配置和样板代码了,但是拦截器GlobalSentinelWebMvcConfiguration配置务必保留。

客户端 ,例如sentinel-spring-boot.jar注册时,执行命令:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
java -Dcsp.sentinel.dashboard.server=localhost:8088  -Dproject.name=sentinel-app -jar .\sentinel-spring-boot.jar

localhost:8088服务器地址,sentinel-app为客户端名称。

注册完毕后,控制台依旧是白板。务必确保客户端有访问量Sentinel 会在客户端首次调用的时候进行初始化,开始向控制台发送心跳包。你可以访问客户端的接口几次,然后刷新控制台,出现下面的

sentinel dashboard控制台

然后点击 +流控对接口GET:/foo/bar新增流控规则。以下是属性对照图:

FlowRule 属性对照

添加完毕针对GET:/foo/bar的限流就生效了。

控制台的实时流量监控数据只在内存保留 5 分钟,如果需要查历史流量甚至对接 Grafana 平台,就必须将监控数据持久化,网上有很多方案,有需要的可以自行搜索资料。

4.总结

今天对Sentinel的流控功能进行了简单的学习,其实它还可以实现很多有用的功能,熔断降级、热点参数限流、系统自适应限流、黑白名单控制等等。中文文档也算比较完备,有兴趣可以了解。好了今天就到这里,多多关注:码农小胖哥 获取更多的编程干货。

本文DEMO可通过关注公众号:码农小胖哥 回复 sentinel 获取。

参考资料

[1]

关于动态流控规则的描述: https://github.com/alibaba/Sentinel/wiki/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%99%E6%89%A9%E5%B1%95

[2]

详情参考控制台文档: https://github.com/alibaba/Sentinel/wiki/%E6%8E%A7%E5%88%B6%E5%8F%B0

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-09-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码农小胖哥 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
sentinel 系列-sentinel的介绍及简单使用
sentinel 是阿里开源的流量控制,熔断降级,系统负载保护的一个Java组件;
六个核弹
2022/12/23
7510
sentinel 系列-sentinel的介绍及简单使用
Spring-Clould-Alibaba-sentinel控制台
启动服务访问 :http://localhost:8000/getGoodsWithID/1
JokerDJ
2023/11/27
2340
Spring-Clould-Alibaba-sentinel控制台
Spring Cloud Alibaba:将 Sentinel 熔断限流规则持久化到 Nacos 配置中心
服务容错的必要性与Spring Cloud Alibaba Sentinel 限流配置实战
行百里er
2022/11/22
1.4K1
Spring Cloud Alibaba:将 Sentinel 熔断限流规则持久化到 Nacos 配置中心
SpringCloud Alibaba学习笔记 ——(六、Sentinel 服务保护框架)
Sentinel 限流的规则默认情况下是没有持久化,如果需要持久化的话用 zk、nacos、携程阿波罗
Gorit
2021/12/30
7250
SpringCloud Alibaba学习笔记 ——(六、Sentinel 服务保护框架)
Spring Cloud Alibaba之服务容错组件 - Sentinel存储规则(十八)
通过之前的介绍,大家对Sentinel已经有了初步认识。在Spring Cloud Alibaba的整合封装下,接口限流这件事非常轻易的应用到我们的Spring Cloud应用中。但是这依然不能完美满足我们的日常生产需求。其中,非常重要的一点就是限流规则持久化的问题。默认情况下Dashboard中设置的限流规则在应用重启之后就会丢失。那么,接下来我们就Sentinel的规则持久化问题加以实现。
用户1212940
2022/04/13
3330
Spring Cloud Alibaba之服务容错组件 - Sentinel存储规则(十八)
Sentinel
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
大忽悠爱学习
2021/12/07
1.1K0
Sentinel
Spring Cloud Alibaba生态之Sentinel
这篇继续总结Spring Cloud Alibaba生态中的Sentinel,它是微服务的哨兵。
小冷coding
2023/05/24
2170
《一起学sentinel》一、一起搭建sentinel服务
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
M4Y
2020/09/22
7640
《一起学sentinel》一、一起搭建sentinel服务
SpringCloud 实战|SpringCloud 整合Sentinel-轻轻松松实现限流
在common-web子模块下添加sentinel相关依赖,使用nacos作为数据源,目的是为了能够让配置的规则能够持久化到nacos中。
AI码师
2022/09/19
7571
SpringCloud 实战|SpringCloud 整合Sentinel-轻轻松松实现限流
服务流控(Sentinel)
问天丶天问
2024/02/17
1020
服务流控(Sentinel)
使用Nacos存储Sentinel的限流规则
要通过 Sentinel 控制台配置集群流控规则,需要对控制台进行改造。主要改造规则可以参考:
BUG弄潮儿
2020/07/21
3.5K0
面试官:Sentinel是如何实现限流的?
限流是一种通过控制系统对外提供的资源、服务或接口的访问数量或速率,以保护系统免受过载的一种策略。
磊哥
2024/02/04
1.7K0
面试官:Sentinel是如何实现限流的?
SpringBoot集成Sentinel实现接口流量控制
Hello,大家好,我是麦洛,今天带大家来了解一下SpringBoot如何继承Sentinel来实现接口流量控制
麦洛
2021/03/23
4.3K0
SpringBoot集成Sentinel实现接口流量控制
微服务(十五)——Sentinel 高可用流量管理框架
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
不愿意做鱼的小鲸鱼
2022/09/27
1.2K0
微服务(十五)——Sentinel 高可用流量管理框架
Spring cloud 之多种方式限流(实战)
在频繁的网络请求时,服务有时候也会受到很大的压力,尤其是那种网络攻击,非法的。这样的情形有时候需要作一些限制。例如:限制对方的请求,这种限制可以有几个依据:请求IP、用户唯一标识、请求的接口地址等等。
程序猿Damon
2020/05/25
3.3K0
限流与熔断降级
发送一次localhost:8087/hello请求(控制台将输出异常信息),比如
程裕强
2019/07/11
1.2K0
限流与熔断降级
Sentinel: 使用注解限流
在前面我们对Sentinel做了一个详细的介绍,可以手动的通过Sentinel提供的SphU类来保护资源。
猿天地
2019/05/07
1.2K0
Springboot使用Sentinel限流,集成zookeeper完成规则的持久化
上一篇简单介绍了sentinel限流的基本配置和使用,这一篇我们来稍微深入一点,看看如何将zookeeper继承进来,用以保存添加的流控规则。
天涯泪小武
2019/07/04
3K0
Springboot使用Sentinel限流,集成zookeeper完成规则的持久化
SpringCloud微服务:Sentinel哨兵组件,管理服务限流和降级
Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。包括核心的独立类库,监控台,丰富的使用场景验证。(这似乎是阿里开源组件的一贯作风,极其有特点,且特点很规律)
知了一笑
2020/03/26
1K0
SpringCloud微服务:Sentinel哨兵组件,管理服务限流和降级
springCloud --- 高级篇(2)
本系列笔记涉及到的代码在GitHub上,地址:https://github.com/zsllsz/cloud
贪挽懒月
2020/06/08
1.2K0
springCloud --- 高级篇(2)
相关推荐
sentinel 系列-sentinel的介绍及简单使用
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文