使用Sentinel实现一个简单的限流功能

Sentinel: 分布式系统的流量防卫兵

Sentinel 是什么?

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

Sentinel 具有以下特征:

  • 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
  • 完备的实时监控:Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
  • 广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。
  • 完善的 SPI 扩展点:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。

当然了 Senteal不仅仅是用来限流的   我们慢慢研究 最开始先实现简单功能,会用才是最重要的

首先自己去创建一个springboot项目(别问我为什么不是springcloud项目,cloud并不是框架,他是微服务的解决方案,是方案! 用到的框架其实就是springboot)

不会建的话就随便就创建一个maven项目就行

引入pom文件   直接复制我的(注意观察我的pom  做好版本控制在微服务项目中很重要),这就是我们所需要引入的所有pom


    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR8</spring-cloud.version>
        <spring-boot.version>2.3.5.RELEASE</spring-boot.version>
        <spring-cloud-alibaba.version>2.2.1.RELEASE</spring-cloud-alibaba.version>
    </properties>


    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
            <version>2.3.3.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>


    </dependencies>


    <dependencyManagement>
        <dependencies>
            <!--spring boot-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--spring cloud -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--     SpringCloud Alibaba       -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>


        </dependencies>
    </dependencyManagement>

下面是我的项目启动类(没什么特别的)

@SpringBootApplication
public class BusinessInitializeApplication {
    public static void main(String[] args) {
        SpringApplication.run(BusinessInitializeApplication.class, args);
    }

}

下面是我的请求类(重点是这里,如果要实现某个接口的限流监听就需要加@SentinelResource注解,value是资源名,blockHandler是我们定义的异常处理方法,其实还有一个参数可以指定异常处理类,这里我们为了方便就写在一个类里了,所以就不需要那个参数了)

@Controller
@RequestMapping("/Test")
public class TestCloud {

    @SentinelResource(value = "res" ,blockHandler = "handleException")
    @RequestMapping(value = "/upload")
    @ResponseBody
    public String logUpload(){
        return "upload";
    }

    public  String handleException(BlockException ex) {
        System.out.println("被限流了");
        return “恭喜你被限流了" ;
    }
}

下面是我们项目的配置文件application.properties(啥都没有  这几个配置就是用来注册sentinel监听服务的)

spring.application.name=sentinel-WangZC
server.port=18083
spring.cloud.sentinel.transport.dashboard=localhost:8080

然后我们需要去官网下载sentinel的jar包(官网提供两种方式一种是下载源码去启动,一种是直接下载jar包启动,我们选择后者)

下载完成后直接  java -jar sentinel-dashboard.jar   启动sentinel 服务(放心,肯定会启动成功的)

然后访问控制台http://localhost:8080/ 

看到下面这个了吧 sentinel-WangZC就是我自己的实例

这个时候你需要先请求一下自己刚才写的那个接口 (sentinel是懒加载)才会看到自己要控制的那个限流资源(如下图)

然后我们点击控流(为了方便测试我们设置qps为1)然后点击新增

这个时候就可以测试了

考验手速的时候到了,利用你的鼠标后回车键飞速的请求你的那个接口http://localhost:18083/Test/upload

正常会返回这个 

当你每秒请求超过一次后

这样我们就完成了整个限流的功能,点个赞再走呗

有个问题就是Sentinel的规则在项目重启后就会消失

我发现一个解决方案就是通过spring的自动装配  通过代码注入  这样的话项目启动后规则会自动加载

@Configuration
public class SentinelMsg {

    @Bean
    public void setSenteal() {
        System.out.println("加载");
        List<FlowRule> rules = new ArrayList<FlowRule>();
        FlowRule rule = new FlowRule();
        rule.setResource("res");
        rule.setCount(2);
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule.setLimitApp("default");
        rules.add(rule);
        FlowRuleManager.loadRules(rules);
    }

}

这样的缺点就是代码是写死的,如果规则经常改变的话就不太好维护了

官方的方法好像是持久化到nacos里面,我觉得这才是最合理的

好像还可以持久化到redis中

 

猜你喜欢

转载自blog.csdn.net/wangzhichaogege/article/details/114114483