Sentinel 限流示例

 

首先下载  sentinel-dashboard-1.8.1.jar

下载地址

https://github.com/alibaba/Sentinel/releases

 

 

 

cmd 到 jar包目录 , 运行命令 :

java -Dserver.port=8088 -Dcsp.sentinel.dashboard.server=localhost:8088 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.1.jar

 

运行结果:

 

 

代码:

 

调用入口 Controller :

package com..sentinel;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphO;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.fastjson.JSONObject;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;


@RestController
@RequestMapping("/user")
public class SentinelController {

    @Resource
    private UserService userService;

    public static final String RESOURCE_NAME = "userList";


    /**
     * 1.采用异常处理的形式 (控制台根据 userList 限流)
     * @return
     */
    @RequestMapping("/exception")
    public List<User> exception(){
        System.out.println(" exception 请求 进来 ....");
        List<User> userList = null;

        Entry entry = null;

        try {
            entry = SphU.entry(RESOURCE_NAME);
            userList = userService.getList();
        } catch (BlockException e) {
            List<User> list = new ArrayList<>();
            list.add(new User("exception", "访问资源被限流!"));
            return list;
        }finally {
            if(entry != null){
                System.out.println("执行 finally .....");
                entry.exit();
            }
        }

            return userList;
    }


    /**
     * 2.采用返回布尔值的方式 (控制台根据 userList 限流)
     * @return
     */
    @RequestMapping("/booLean")
    public List<User> booLean(){

        System.out.println(" booLean 请求 进来 ....");

        List<User> userList = null;
        if(SphO.entry(RESOURCE_NAME)){

            try{
                userList = userService.getList();
            }finally {
                System.out.println("执行 finally .....");
                SphO.exit();
            }
        }else {
            List<User> list = new ArrayList<>();
            list.add(new User("booLean", "访问资源被限流!"));
            return list;
        }

        return userList;
    }


    /**
     * 3.采用注解形式,代码无侵入性 (控制台根据 userList 限流)
     * @return
     */
    @RequestMapping("/annotation")
    public List<User> annotation(){

        List<User> userList = userService.queryAllAnnotation();

    return userList;
    }


    /**
     * 4.熔断 降级 (控制台根据 userList 限流)
     * @return
     */
    @RequestMapping("/fallback")
    public List<User> fallback(){

        List<User> userList = userService.queryAllFallback();

        return userList;
    }


    //============================  以下为根据地址限流 ===============================


    /**
     * 5. (控制台根据 /user/dashboard 地址限流)
     * @return
     */
    @RequestMapping("/dashboard")
    public List<User> dashboard(){

        List<User> userList = userService.queryAllDashboard();

        return userList;
    }


    /**
     * 6. (控制台根据 /user/newTest 地址限流)
     * @return
     */
    @RequestMapping("/newTest")
    public List<User> newTest(){

        List<User> userList = userService.NewTest();

        return userList;
    }

    /**
     * 7. (控制台根据 /user/newJson 地址限流)
     * @return
     */
    @RequestMapping("/newJson")
    public @ResponseBody String newJson(){

        JSONObject userList = userService.NewJson();

        return userList.toString();
    }


}

 

配置类 :

package com..sentinel;

import com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.CompositeFilter;
import javax.servlet.Filter;


@Configuration
public class SentinelConfig {

    /**
     * 用于注解限流
     * 将SentinelResourceAspect注册为一个Bean
     *
     */
    @Bean
    public SentinelResourceAspect sentinelResourceAspect(){

        return new SentinelResourceAspect();
    }


    /**
     * 配置filter
     * 与 Sentinel 控制台进行通信,
     * 把所有访问的 Web URL 自动统计为 Sentinel 的资源.
     * @return
     */
    public FilterRegistrationBean sentinelFilterRegistration(){

        FilterRegistrationBean<Filter> registrationBean = new FilterRegistrationBean<>();

        registrationBean.setFilter(new CompositeFilter());
        registrationBean.addUrlPatterns("/*");
        registrationBean.setName("sentinelFilter");
        registrationBean.setOrder(1);

        return registrationBean;
    }

}

 

简单的实体类:

package com..sentinel;

public class User {

    String id;

    String name;

    User(String id,String name){

        this.id = id;
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setId(String id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                '}';
    }

}

 

接口 和 接口实现类:

 

package com..sentinel;

import com.alibaba.fastjson.JSONObject;
import java.util.List;

public interface UserService {

    public List<User> getList();

    public List<User> queryAllAnnotation();

    public List<User> queryAllFallback();

    public List<User> queryAllDashboard();

    public List<User> NewTest();

    public JSONObject NewJson();
}





package com..sentinel;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;

@Service
public class UserServiceImpl implements UserService {

    @Override
    public List<User> getList() {

        List<User> list = new ArrayList<>();

        list.add(new User("1", "zhangsan"));
        list.add(new User("2", "liusi"));
        list.add(new User("3", "wangwu"));

        return list;
    }


    //注解形式   value是资源名称,是必填项。blockHandler填限流处理的方法名称
    @Override
    @SentinelResource(value=SentinelController.RESOURCE_NAME,blockHandler = "annotation")
    public List<User> queryAllAnnotation() {
        System.out.println("正常请求.....");
        List<User> list = new ArrayList<>();

        list.add(new User("1", "zhangsan"));
        list.add(new User("2", "liusi"));
        list.add(new User("3", "wangwu"));

        return list;
    }

    //注解限流处理方法
    public List<User> annotation(BlockException ex){

        System.out.println("请求频繁,进入注解限流.....");
        List<User> list = new ArrayList<>();
        list.add(new User("annotation", "访问资源被限流!"));
        return list;
    }


    // 抛出非 BlockException 的异常时,就会进入到fallback方法中,实现熔断机制
    @Override
    @SentinelResource(value=SentinelController.RESOURCE_NAME,fallback = "fallback")
    public List<User> queryAllFallback() {
        System.out.println("正常请求.....");
        List<User> list = new ArrayList<>();

        list.add(new User("1", "zhangsan"));
        list.add(new User("2", "liusi"));
        list.add(new User("3", "wangwu"));
        if(list.size()!=0){

            throw new RuntimeException("list is not null ...");
        }

        return list;
    }

    //熔断降级处理方法
    public List<User> fallback(Throwable ex){

        System.out.println("访问资源异常,进入 fallback .....");
        System.out.println("异常信息---> : ");
        ex.printStackTrace();
        List<User> list = new ArrayList<>();
        list.add(new User("fallback", "访问资源异常,降级处理!"));
        return list;
    }


    @Override
    @SentinelResource(value="queryAllDashboard",fallback = "dashboardFallback")
    public List<User> queryAllDashboard() {
        System.out.println("Dashboard正常请求.....");
        List<User> list = new ArrayList<>();

        list.add(new User("1", "zhangsan"));
        list.add(new User("2", "liusi"));
        list.add(new User("3", "wangwu"));

        return list;
    }

    public List<User> dashboardFallback(){

        System.out.println("Dashboard访问资源频繁,进入 fallback .....");

        List<User> list = new ArrayList<>();
        list.add(new User("Dashboard-fallback", "访问资源频繁,降级处理!"));
        return list;
    }


    @Override
    @SentinelResource(value= "NewTest" ,fallback ="newFallback" )
    public List<User> NewTest() {
        System.out.println("NewTest正常请求.....");
        List<User> list = new ArrayList<>();

        list.add(new User("1", "zhangsan"));
        list.add(new User("2", "liusi"));
        list.add(new User("3", "wangwu"));

        return list;
    }



    public List<User> newFallback(){

        System.out.println("NewTest访问资源频繁,进入 fallback .....");

        List<User> list = new ArrayList<>();
        list.add(new User("NewTest-fallback", "访问资源频繁,降级处理!"));
        return list;
    }


    public List<User> exceptionHandler(BlockException ex) {

        System.out.println("NewTest 异常......");
        ex.printStackTrace();
        List<User> list = new ArrayList<>();
        list.add(new User("NewTest-Exception", "访问资源异常,降级处理!"));
        return list;
    }



    @Override
    @SentinelResource(value = "NewJson",fallback = "JsonFallback")
    public JSONObject NewJson() {

        System.out.println("NewJson 正常请求.....");
       JSONObject json = new JSONObject();

        json.put("1","zhangsan");
        json.put("2","liusi");
        json.put("3","wangwu");

        return json;
    }


    public JSONObject JsonFallback(){

        System.out.println("NewJson 访问资源频繁,进入 fallback .....");

        JSONObject json = new JSONObject();
        json.put("fallback","访问资源频繁,降级处理!");
        return json;
    }

}

 

application.properties :

spring.application.name=ac-Sentinel
spring.cloud.sentinel.transport.dashboard=(本机地址):8088

 

pom  groupId 需完善  ) :

 

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.</groupId> <!-- groupId 需完善 -->
    <artifactId>ac-sentinel</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>ac-sentinel</name>
    <description>ac-sentinel</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- Sentinel 依赖 -->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-core</artifactId>
            <version>1.8.1</version>
        </dependency>

        <!-- Sentinel 注解支持 对应Spring 中的切面 -->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-annotation-aspectj</artifactId>
            <version>1.8.1</version>
        </dependency>

        <!--  Transport 模块来与 Sentinel 控制台进行通信-->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-transport-simple-http</artifactId>
            <version>1.8.1</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

 

服务启动添加 参数 :

 

-Dserver.port=8080 -Dcsp.sentinel.dashboard.server=(本机地址):8088 -Dcsp.sentinel.api.port=8720 -Dproject.name=Test

注:
###(-Dproject.name=Test Test根据业务改,这里用来测试)

 

访问   http://(本机地址):8088

用户名 密码 都是   sentinel

 

 

 

点击登录  多了个Test  ( 看不到就 刷新 或 重新登录 )

 

 

 

点开,里面有 个 簇点链路 ,可以把入口的几个方法调用一遍  结果 :

 

 

 

 

点击 流控 ,把 单机阈值 调成 2   点击新增 ,会进入到  流控规则  :

 

测试: 

对入口的几个方法 一秒内多调用几遍   查看结果

 

posted @ 2021-05-12 16:48  Li&Fan  阅读(419)  评论(0编辑  收藏  举报