首页 > 其他分享 >Springboot整合Sentinel实现流控

Springboot整合Sentinel实现流控

时间:2022-09-01 20:25:01浏览次数:82  
标签:name 流控 spring nacos sentinel Sentinel id Springboot

在Springboot项目中整合Sentinel实现流控,Gateway整合Sentinel见Gateway整合Sentinel,Sentinel-daahboard的改造见Sentinel-dashboard改造(普通流控和网关流控规则持久化到Nacos)

本文章节如下,有兴趣可以自行跳转

1、sentinel资源的定义
2、依赖的引入
3、增加过滤器配置(将controller自动定义为资源)
4、增加UrlCleaner(url资源清洗)
5、Sentinel的BlockException统一处理
6、WebCallbackManager设置统一异常处理和Url清洗
7、Sentinel控制台和规则数据源(nacos)配置
8、Sentinel整合Feign实现服务降级熔断

1、sentinel资源的定义

sentinel里面有一个很重要的定义:资源。其实就是一段给包围起来的代码块,和java里面的关键字synchronized很想,可以支持加在方法上则对整个方法加锁,加在代码块上则是对代码块加锁。

sentinel是对资源实施流控,其提供了三种方式来定义资源:

1、为了适配web servlet,将每个controller接口自动定义为一个资源,资源名称就是接口的路径

2、方法上添加@SentinelResource注解,将整个方法定义为一个资源,资源名称自己定义

3、就是在代码中针对某一个代码块来定义,被SphU.entry()和e0.exit()包裹的代码块就是一个资源,下面给出代码示例:

private void doSomethingWithEntry() {
    Entry e0 = null;
    try {
        e0 = SphU.entry("benchmark");
        doSomething();
    } catch (BlockException e) {
    } finally {
        if (e0 != null) {
            e0.exit();
        }
    }
}

对于已经存在的项目,此时采用方式1就非常方便,基本无代码入侵,整合的工作量小很多,如果是对网关进行流控,则更加的方便,其他的微服务完全不需要修改。

2、依赖的引入

<!--sentinel相关start-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-sentinel-datasource</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
    <version>3.0.1</version>
</dependency>
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
  
<!--使其主动对所有的url进行统计,把所有的controller接口识别成资源-->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-web-servlet</artifactId>
</dependency>

<!--sentinel相关end-->

3、增加过滤器配置(将controller自动定义为资源)

@Configuration
public class FilterConfig {
    @Bean
    public FilterRegistrationBean sentinelFilterRegistration() {
        FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>();
        registration.setFilter(new CommonFilter());
        registration.addUrlPatterns("/*");
        registration.setName("sentinelFilter");
        registration.setOrder(1);
        return registration;
    }
}

4、增加UrlCleaner(url资源清洗)

/**
 * 一些接口采用了 @PathVariable 注解,每一个url都会被识别成资源,但是sentinel最多支持6000个,所以需要处理
 * 例如:/name/{id}可能会有/name/1、/name/2、/name/3,如果不处理就是三个资源,但是其实这是一个资源,所有在这里统一处理
 *
 * @Date 2022/8/3 16:31
 */
public class WebUrlCleaner implements UrlCleaner {
 
    /**
     * 正则匹配
     */
    private static String PATTERN_SENTINEL_TEST_NAME = "^/name/[0-9a-zA-Z]+$";
    private static String SENTINEL_RESOURCE_SENTINEL_TEST_NAME = "/name/*";
 
    private static Pattern pattern = Pattern.compile(PATTERN_SENTINEL_TEST_NAME);
 
 
    @Override
    public String clean(String originUrl) {
        if (pattern.matcher(originUrl).matches()) {
            return SENTINEL_RESOURCE_SENTINEL_TEST_NAME;
        } else {
            return originUrl;
        }
    }
}


5、Sentinel的BlockException统一处理

因为其默认的异常提示不友好,也不符合项目中的统一返回定义,所以需要针对该情况做修改,示例代码如下:

public class WebUrlBlockHandler implements UrlBlockHandler {
 
    @Override
    public void blocked(HttpServletRequest request, HttpServletResponse response, BlockException e) throws IOException {
        HashMap<Object, Object> result = new HashMap<>(2);
        String msg = null;
        Integer code = 0;
        if (e instanceof FlowException) {
            msg = "小主慢一点,处理不过来啦!";
            code = 1;
        } else if (e instanceof DegradeException) {
            msg = "当前服务不可用,请稍后重试!";
            code = 2;
        } else if (e instanceof ParamFlowException) {
            msg = "热点参数限流";
            code = 3;
        } else if (e instanceof SystemBlockException) {
            msg = "系统规则(负载/....)不满足要求";
            code = 4;
        } else if (e instanceof AuthorityException) {
            msg = "授权规则不通过";
            code = 5;
        }
        result.put("code", code);
        result.put("msg", msg);
        response.setStatus(HttpStatus.SC_INTERNAL_SERVER_ERROR);
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/json;charset=utf-8");
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        objectMapper.writeValue(response.getWriter(), result);
    }
}


6、WebCallbackManager设置统一异常处理和Url清洗

WebCallbackManager里面提供的set方法都是静态的,所以可以在程序启动时就将自定义的异常处理和Url清洗设置进去

@Configuration
public class SentinelConfig {
 
    static {
        //设置自定义的Block异常处理
        WebCallbackManager.setUrlBlockHandler(new WebUrlBlockHandler());
        //设置url清洗
        WebCallbackManager.setUrlCleaner(new WebUrlCleaner());
    }
}

7、Sentinel控制台和规则数据源(nacos)配置

关于sentinel的配置分为控制台和数据源,这部分的数据中涉及到ip,所以可以将这部分配置放到nocas上,这样就可以实现动态修改了

注意:

1、配置的nacos命名空间需要和sentinel控制台中配置的nacos命名空间保持一致

2、data-id:${spring.application.name}-flow-rules,这些名称,是在改造sentinel控制台源码时自己定义的,名称不重要,重要的是和sentinel控制台源码保持一致,控制台在向Nacos保存规则时是什么data-id,则此处就需要配置什么data-id

spring:
  application:
    name: sentinel
  cloud:
    sentinel:
      transport:
        #Sentinel控制台地址
        dashboard: 127.0.0.1:8080
        eager: true
        #当前服务的ip
        clientIp: 127.0.0.1
        port: 8719
      datasource:
        #================流控===============
        flow:
          nacos:
            server-addr: 127.0.0.1:8848
            #与sentinel控制台的namespeace统一
            namespace: 6db12247-153b-4d0c-bef6-5c7c5e48faa3
            #nacos中存储规则的dataId,对于dataId使用了${spring.application.name}变量,这样可以根据应用名来区分不同的规则配置
            data-id: ${spring.application.name}-flow-rules
            #nacos中存储规则的groupId(可以自己定义)
            group-id: SENTINEL_GROUP
            #具体的类型见,org.springframework.cloud.alibaba.sentinel.datasource.RuleType
            rule-type: flow
            #nacos的用户名和密码
            username: nacos
            password: nacos
        #================流控===============
        degrade:
          nacos:
            server-addr: 127.0.0.1:8848
            namespace: 6db12247-153b-4d0c-bef6-5c7c5e48faa3
            data-id: ${spring.application.name}-degrade-rules
            group-id: SENTINEL_GROUP
            rule-type: degrade
            username: nacos
            password: nacos
        #================系统规则===============
        system:
          nacos:
            server-addr: 127.0.0.1:8848
            namespace: 6db12247-153b-4d0c-bef6-5c7c5e48faa3
            data-id: ${spring.application.name}-system-rules
            group-id: SENTINEL_GROUP
            rule-type: system
            username: nacos
            password: nacos
        #================授权规则===============
        authority:
          nacos:
            server-addr: 127.0.0.1:8848
            namespace: 6db12247-153b-4d0c-bef6-5c7c5e48faa3
            data-id: ${spring.application.name}-authority-rules
            group-id: SENTINEL_GROUP
            rule-type: authority
            username: nacos
            password: nacos
        #================热点规则===============
        param-flow:
          nacos:
            server-addr: 127.0.0.1:8848
            namespace: 6db12247-153b-4d0c-bef6-5c7c5e48faa3
            data-id: ${spring.application.name}-param-flow-rules
            group-id: SENTINEL_GROUP
            rule-type: param-flow
            username: nacos
            password: nacos

8、Sentinel整合Feign实现服务降级熔断

Sentinel已经和Feign实现整合,可以采用Feign封装Http请求,然后在sentinel控制台的簇点链路中找到该资源,增加降级和熔断规则,当满足条件时,就可以实现服务的熔断

注意:feign调用的微服务和当前微服务需要在nacos中需要注册在同一个命名空间里面

开启Feign熔断需要开启配置,如下:

feign:
  sentinel:
    enabled: true

标签:name,流控,spring,nacos,sentinel,Sentinel,id,Springboot
From: https://www.cnblogs.com/zhaodalei/p/16647683.html

相关文章

  • SpringBoot上传文件
    前端使用ElementUI+Vue后端使用SpringBoot1前端代码1.0组件导入&初始化导入ElementUI、Axios、Vue的资源。完成Vue的初始化和生效区域的设置。这些资源都能找到,把......
  • SpringBoot-Http请求工具类
    一、编写请求配置类importcom.alibaba.fastjson.JSONObject;importorg.springframework.context.annotation.Configuration;importorg.springframework.http.*;imp......
  • springboot整合redis,设置缓存过期时间
    注:redis服务器要先开启!或者连接远程服务器上的Redis,但是依然要开启服务,不然会一直TimeOut!Pom文件添加依赖<dependency><groupId>org.springframework.boot</......
  • SpringBoot项目引入Swagger接口文档
    一、在项目中引入Swagger依赖<!--swagger--><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifa......
  • springboot+Vue项目允许跨域
    packagecom.example.demo.itkb.user.config;importorg.springframework.context.annotation.Configuration;importorg.springframework.web.servlet.config.annotat......
  • SpringBoot简单使用(1)
    1:xml文件与javaconfig 1.1.1什么是javaconfig:是spring提供的使用java类配置容器。配置springIOC容器的纯java方法优点:可以使用面向对象的方式,一个配置类可以继承配置......
  • 轻量级SpringBoot Office文档在线预览框架
    框架简介介绍:基于开源项目KkFileView源码提取出,封装成仅用于Office文档预览(格式转换)功能的一个通用组件;原理是把Word转成PDF,PPT转成PDF,Excel转成HTML;利用浏览......
  • Linux基础知识(14)- Docker (七) | 使用 Docker 部署 SpringBoot 项目
    本文将完全复制“Springboot基础知识(08)-spring-boot-starter-web(Web启动器)”里的SpringbootWeb项目的代码和配置到新项目SpringbootWebDocker。在新项目Springboot......
  • SpringBoot使用@Async和@Transactional注解优化接口
    1、业务背景:项目上有一个接口需要按照前端传递的时间段范围修改6个表的数据,接口V1版本开发完成是使用的同步方式全局@Transactional注解的方式去做的,但存在一个问题就......
  • SpringBoot整合Shiro
    11、SpringBoot整合Shiro11.1、什么是ShiroApacheShiro是一个Java的安全(权限)框架。Shiro可以非常容易的开发出足够好的应用,其不仅可以用在JavaSE环境,也可以用在Jav......