A Guide to Spring Cloud Alibaba Sentinel

Sentinel is an open-source project for circuit breaker in Spring Cloud Alibaba. It mainly includes the following functions: flow control, circuit breaker, and system adaptive protection.

In this post, I will cover common uses of Spring Cloud Alibaba Sentinel. This post is based on Java 21, Spring Boot 3.2.12, Spring Cloud Alibaba 2023.0.3.3, and Sentinel 1.8.8.

Next, I will use a simple example application to show it in action.

Running Sentinel Dashboard

1. Download Sentinel JAR file from GitHub

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

2. Running Sentinel Dashboard

java -Dserver.port=8081 \
-Dcsp.sentinel.dashboard.server="localhost:8081" \
-Dproject.name=sentinel-dashboard \
-jar sentinel-dashboard-{VERSION}.jar

3. Open Sentinel Dashboard

Visiting http://localhost:8081 to see the Sentinel Dashboard.

The default username and password:

  • Username: sentinel
  • Password: sentinel

Spring Cloud Alibaba Sentinel Application

1. Create Project and Add Dependencies

Using Gradle

1. Create a Java application with the gradle init command.

$ mkdir spring-cloud-alibaba-sentinel-demo && cd spring-cloud-alibaba-sentinel-demo
$ gradle --configuration-cache \
init --use-defaults \
--type java-application \
--package com.taogen.springcloud

2. Gradle configuration

app/build.gradle.kts

plugins {
java
id("org.springframework.boot") version "3.2.12"
// Use the Spring Dependency Management plugin to manage Spring Cloud dependencies.
id("io.spring.dependency-management") version "1.1.7"
}

extra["springCloudAlibabaVersion"] = "2023.0.3.3"
extra["springCloudVersion"] = "2023.0.6"

java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}

repositories {
mavenCentral()
}

dependencies {
implementation("com.alibaba.cloud:spring-cloud-starter-alibaba-sentinel")
implementation("com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-config")
implementation("com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-discovery")
implementation("org.springframework.cloud:spring-cloud-starter-loadbalancer")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-actuator")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}

dependencyManagement {
imports {
mavenBom("com.alibaba.cloud:spring-cloud-alibaba-dependencies:${property("springCloudAlibabaVersion")}")
mavenBom("org.springframework.cloud:spring-cloud-dependencies:${property("springCloudVersion")}")
}
}

tasks.withType<Test> {
useJUnitPlatform()
}

Using Maven

1. Create a Java application with mvn command.

$ mvn -B archetype:generate \
-DgroupId=com.taogen.springcloud \
-DartifactId=spring-cloud-alibaba-sentinel-demo \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DarchetypeVersion=1.5

2. Maven configuration

pom.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>

<groupId>com.taogen.springcloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-demo</artifactId>
<version>1.0-SNAPSHOT</version>

<name>spring-cloud-alibaba-sentinel-demo</name>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>21</maven.compiler.release>
<java.version>21</java.version>
<spring-boot.version>3.2.12</spring-boot.version>
<spring-cloud-alibaba.version>2023.0.3.3</spring-cloud-alibaba.version>
<spring-cloud.version>2023.0.6</spring-cloud.version>
</properties>

<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</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-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<dependencyManagement>
<dependencies>
<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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

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

Using Alibaba Initializr

Go to https://start.aliyun.com/

Project Metadata

  • Group: com.taogen.springcloud
  • Artifact: spring-cloud-alibaba-nacos-config-demo

Add dependencies

  • Spring Cloud Alibaba Sentinel
  • Nacos Configuration
  • Nacos Service Discovery
  • Cloud LoadBalancer
  • Spring Web
  • Spring Boot Actuator

2. Spring Configuration

The spring configuration mainly contains Nacos and Sentinel configurations.

application.yml

spring:
application:
name: spring-cloud-alibaba-sentinel-demo
profiles:
active: dev
config:
import: optional:nacos:${spring.application.name}-${spring.profiles.active}.properties?group=DEFAULT_GROUP
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
discovery:
server-addr: 127.0.0.1:8848
sentinel:
transport:
dashboard: localhost:8081
port: 8719
eager: true

server:
port: 8090
  • spring.cloud.sentinel.transport.port: A custom port for starting an HTTP server that interacts with the Sentinel Dashboard. 在应用对应的机器上启动一个 Http Server,该 Server 会与 Sentinel 控制台做交互。比如 Sentinel 控制台添加了一个限流规则,会把规则数据 push 给这个 Http Server 接收,Http Server 再将规则注册到 Sentinel 中。
  • spring.cloud.sentinel.eager: Whether to trigger Sentinel initialization in advance.

More Spring Cloud Alibaba Sentinel Configuration to see Spring Cloud Alibaba Sentinel provides these configuration options

3. Sentinel Application

SpringCloudAlibabaSentinelApplication.java

package com.taogen.springcloud;  

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

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

MyController.java

package com.taogen.springcloud;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {
@Autowired
private MyService myService;

@GetMapping("/test")
public String test() {
return myService.service1();
}
}

MyService.java

package com.taogen.springcloud;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.stereotype.Service;

import java.util.Date;

@Service
public class MyService {
@SentinelResource(value = "MyService#service1", fallback = "service1Fallback")
public String service1() {
// Simulate exceptions to trigger Sentinel's Circuit Breaker
int i = 1 / 0;
return "test" + System.currentTimeMillis();
}

public String service1Fallback(Throwable t) {
if (BlockException.isBlockException(t)) {
// Circuit breaker or traffic limitation. If there is a blockHandler in `@SentinelResource(blockHandler="xxx")` then it will not be executed here
return "Blocked by Sentinel: " + t.getClass().getSimpleName() + new Date();
}
// Service degradation (not reaching the exception threshold)
return "Oops, failed: " + t.getClass().getCanonicalName();
}
}

4. Start and Verification

Start Nacos and Sentinel

Before running the application, you must ensure Nacos and Sentinel are running.

In the preceding section, we have already started a Sentinel Dashboard. For running Nacos, you can refer to Running Nacos with Docker.

Starting the Application

Running the main() method in the SpringCloudAlibabaSentinelApplication to start the application.

When you visit http://localhost:8090/test you will see a fallback (degrade) response. Because there is an exception thrown in MyService#service1(), and the @SentinelResource annotation is added to the method MyService#service1().

The fallback (degrade) response:

Oops, failed: java.lang.ArithmeticException

Add flow rules and degrade rules to Sentinel

Visiting http://localhost:8081 to open the Sentinel Dashboard. After you login the Sentinel Dashboard, you can see the application spring-cloud-alibaba-sentinel-demo appears in the left sidebar. If you can’t see the application in the left side bar, you can visit http://localhost:8090/test to trigger Sentinel to work.

Add flow rules and degrade rules on the Sentinel Dashboard:

On the left sidebar, expand your application -> Click the menu “簇(cù)点链路” -> Add flow rules and circuit breaker (degrade) rules to the resource MyService#service1.

Test circuit breaker

Add the following circuit breaker (degrade) rules to the resource MyService#service1 on Sentinel Dashboard:

新增熔断规则

  • 资源名:MyService#service1
  • 熔断策略:异常比例
  • 比例阈值:0.6
  • 熔断时长:5
  • 最小请求数:5

After adding the above circuit breaker rule, when you request http://localhost:8090/test more than 5 times, the circuit breaker is open. The response message is:

Blocked by Sentinel: DegradeException

Test flow control

Add the following flow rules to the resource MyService#service1 on the Sentinel Dashboard:

新增流控规则

  • 资源名:MyService#service1
  • 阈值类型:QPS
  • 单机阈值:1

After adding the above circuit breaker rule, if the rate of requests to http://localhost:8090/test is over 1 request(s) per second, the circuit breaker is open. The response message is:

Blocked by Sentinel: DegradeException

Sentinel DataSource

The Sentinel rule configurations created by the Sentinel Dashboard are stored in memory. If you restart the application, the rule configurations will be lost.

Sentinel supports reading rules from files, databases, and configuration centers. For example:

  • Pull-based: file, Consul, Eureka.
  • Push-based: ZooKeeper, Redis, Nacos, Apollo, etcd.

Read Sentinel Rules from Nacos

1. Add dependencies

Gradle

implementation("com.alibaba.csp:sentinel-datasource-nacos")

Maven

<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

2. Add Sentinel rule configurations to Nacos

Add Circuit Break rule configurations on Nacos Dashboard:

  • Data ID: spring-cloud-alibaba-sentinel-demo-degrade-rules
  • Group: SENTINEL_GROUP
  • Format: JSON
  • Configuration content
[
{
"resource":"MyService#service1",
"grade":2,
"count":3,
"timeWindow":2,
"minRequestAmount":5
}
]

JSON field description:

  • resource: 资源名
  • grade: 熔断策略:0 慢调用比例,1 异常比例,2 异常数
  • count:异常数
  • timeWindow:熔断时长(秒)
  • minRequestAmount:最小请求数

For more details, see com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule

Add flow rule configurations on Nacos Dashboard:

  • Data ID: spring-cloud-alibaba-sentinel-demo-flow-rules
  • Group: SENTINEL_GROUP
  • Format: JSON
  • Configuration content
[
{
"resource":"MyService#service1",
"limitApp":"default",
"grade":1,
"count":2,
"strategy":0,
"controlBehavior":0,
"clusterMode":false
}
]

JSON field description:

  • resource :资源名,资源名是限流规则的作用对象。
  • limitApp :流控针对的调用来源。默认就是 default ,代表不区分调用来源。
  • grade :限流阈值类型:QPS 或线程数模式。0 表示线程数,1 表示 QPS。默认为 1,即 QPS 模式。
  • count :限流阈值。比如值为 2 表示 1 秒超过 2 个请求就限流。
  • strategy :流控模式:0 直接,1 链路,2 关联。默认 0 直接 。
  • controlBehavior :流控效果(直接拒绝 / 排队等待 / 慢启动模式),0 表示快速失败,1 表示 Warm Up,2 表示排队等待。

More details see com.alibaba.csp.sentinel.slots.block.degrade.FlowRule

3. Spring Configuration

Add the following configuration to application.yml.

spring:
application:
name: spring-cloud-alibaba-sentinel-demo
cloud:
// ...
sentinel:
// ...
datasource:
my-degrade-ds:
nacos:
server-addr: 127.0.0.1:8848
data-id: ${spring.application.name}-degrade-rules
group-id: SENTINEL_GROUP
data-type: json
rule-type: degrade
my-flow-ds:
nacos:
server-addr: 127.0.0.1:8848
data-id: ${spring.application.name}-flow-rules
group-id: SENTINEL_GROUP
data-type: json
rule-type: flow

4. Start and Verification

Running the main() method in the SpringCloudAlibabaSentinelApplication to start the application.

Login to Sentinel Dashboard to view the degrade and flow rules that read from Nacos.

References

[1] Spring Cloud Alibaba 限流降级

[2] Sentinel 文档

[3] Spring Cloud Alibaba 微服务原理与实战 by 谭锋

[4] java系列 Sentinel集成Nacos作为规则源实现规则持久化

[5] 将 Sentinel 熔断限流规则持久化到 Nacos 配置中心