Skip to content

快速开始

欢迎来到 Sentinel 的世界!这篇新手指南将指引您快速入门 Sentinel。

Sentinel 的使用可以分为两个部分:

  • 核心库(Java 客户端): 不依赖任何框架/库,能够运行于 Java 7 及以上的版本的运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持(见 主流框架适配)。
  • 控制台(Dashboard):Dashboard 主要负责管理推送规则、监控、管理机器信息等。

1. 引入 Sentinel 依赖

  • 创建一个 SpringBoot 项目,命名为 sentinel-quick-start
  • 创建一个 pom.xml,添加以下 Spring Boot 依赖
xml
<?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 http://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.3.11.RELEASE</version>
        <relativePath/>
    </parent>

    <groupId>cn.calvin</groupId>
    <artifactId>sentinel-quick-start-01</artifactId>
    <version>1.0.0-SNAPSHOT</version>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!-- SpringBoot 启动器 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <!-- SpringBoot Web 请求控制器 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- SpringBoot 测试 -->
        <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>

        <!-- Sentinel 核心 -->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-core</artifactId>
            <version>1.8.2</version>
        </dependency>

        <!-- Lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>RELEASE</version>
            <scope>compile</scope>
        </dependency>

        <!-- Fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.56</version>
        </dependency>
    </dependencies>

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

</project>
xml
<!-- Sentinel 核心 -->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-core</artifactId>
    <version>1.8.2</version>
</dependency>

2. 定义资源

  • 资源 是 Sentinel 中的核心概念之一。

  • 在项目下创建包名:

    • cn.calvin.sentinel.controller
    • cn.calvin.sentinel.domain
  • 创建接口访问控制类: UserController.java

java
package cn.calvin.alibaba.sentinel.controller;

import cn.calvin.alibaba.sentinel.domain.User;
import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author Calvin
 * @date 2021/9/14
 * @since v1.0.0
 */
@Slf4j
@RestController
@RequestMapping(value = "/api/v1/user")
public class UserController {

    // 定义资源名称
    private static final String USER_RESOURCE_NAME = "/api/v1/user/getById";
    
    @GetMapping("/getById")
    public JSONObject getById(@RequestParam("id") String id) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code", 200);
        jsonObject.put("msg", "获取用户信息成功!");
        jsonObject.put("data", null);
        try {
            // 1.sentinel 针对定义资源进行限制
            Entry entry = SphU.entry(USER_RESOURCE_NAME);

            // 2.被保护的逻辑,执行的业务逻辑
            User calvinUser = User
                    .builder()
                    .id("1")
                    .username("Calvin")
                    .password("******")
                    .birthday("1994-12-14")
                    .genden(1)
                    .build();

            if (calvinUser.getId().equals(id)) {
                jsonObject.put("data", calvinUser);
            }
            return jsonObject;
        } catch (BlockException be){
            // 处理被流控的逻辑
            log.info("block!");

            jsonObject.put("code",500);
            jsonObject.put("msg", "当前被限流");
            jsonObject.put("data", null);
            return jsonObject;
        }
    }
}
  • 创建实体数据访问层: User.java
java
package cn.calvin.alibaba.sentinel.domain;


import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
 * 用户
 *
 * @author Calvin
 * @date 2021/9/14
 * @since v1.0.0
 */
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {

    /** 用户ID */
    private String id;

    /** 用户名 */
    private String username;

    /** 密码 */
    private String password;

    /** 生日 */
    private String birthday;

    /** 性别 */
    private Integer genden;

    /** 头像 */
    private String avater;
}
java

// 定义资源名称
private static final String USER_RESOURCE_NAME = "/api/v1/user/getById";

try {
    // 1.sentinel 针对资源进行限制的
    Entry entry = SphU.entry(USER_RESOURCE_NAME);
    // 2.被保护的逻辑,执行的业务逻辑
    User calvinUser = User
        .builder()
        .id("1")
        .username("Calvin")
        .password("******")
        .birthday("1994-12-14")
        .genden(1)
        .build();

    if (calvinUser.getId().equals(id)) {
        jsonObject.put("data", calvinUser);
    }
    return jsonObject;
} catch (BlockException be){
    // 处理被流控的逻辑
    log.info("block!");

    jsonObject.put("code",500);
    jsonObject.put("msg", "当前被限流");
    jsonObject.put("data", null);
    return jsonObject;
}

注意:资源定义

  • 资源定义一般针对某个接口上
  • 资源定义也可以在 @RequestMapping(value = "/api/v1/user") 上,但下面方法具体接口也受到限流。

3. 定义规则

  • 通过流控规则来指定允许该资源通过的请求次数。
  • 在项目下创建包名: cn.calvin.alibaba.sentinel.config
  • 创建Sentinel流控规则配置: SentinelRulesConfig.java
java
package cn.calvin.alibaba.sentinel.config;

import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;

/**
 * Sentinel 流控规则配置
 *
 * @author Calvin
 * @date 2021/9/14
 * @since v1.0.0
 */
@Slf4j
@Configuration
public class SentinelRulesConfig {

    // 定义资源名称
    private static final String RESOURCE_NAME = "/api/v1/user/getById";

    /**
     * 初始化流控规则
     */
    @PostConstruct
    public void initFlowRules() {
        // 添加: 流控规则
        List<FlowRule> rules = new ArrayList<>();
        // 构建流控规则: 资源名称、QPS规则、阈值(每秒最多只能通过1个请求。)
        FlowRule flowRule = this.flowRuleBuild(RESOURCE_NAME, RuleConstant.FLOW_GRADE_QPS, 1);
        rules.add(flowRule);
        // 加载配置好的规则
        FlowRuleManager.loadRules(rules);
        log.info(">>>>>>>>> 初始化流控规则: {} >>>>>>>>>", rules);
    }

    /**
     * 流控规则构建
     *
     * @param resourceName 资源名称
     * @param grade        流控规则
     * @param count        阈值
     * @return {@link FlowRule}
     */
    private FlowRule flowRuleBuild(String resourceName, int grade, double count) {
        // 创建:流控规则
        FlowRule rule = new FlowRule();
        // 设置规则对应的【资源名称】
        rule.setResource(resourceName);
        // 设置流控规则为: QPS
        rule.setGrade(grade);
        // 设置受保护的资源阈值
        rule.setCount(count);
        return rule;
    }
}

4. 项目启动

  • 创建一个启动类 SentinelQuickStartApplication.java
java
package cn.calvin.alibaba.sentinel;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SentinelQuickStartApplication {

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

}

5. 限流演示

6. 总结