Implementing Rate Limiting with Alibaba Sentinel
Deploying the Sentinel Dashboard
To set up the Sentinel dashboard, download the standalone JAR file and start it with the following command, which specifies the server port and the dashboard location for client heartbeats.
java -Dserver.port=8080 \
-Dcsp.sentinel.dashboard.server=localhost:8080 \
-Dproject.name=sentinel-dashboard \
-jar sentinel-dashboard-1.8.0.jar
- -Dserver.port: Configures the dashboard's web interface port.
- -Dcsp.sentinel.dashboard.server: Specifies the dashboard address where clients will send heartbeat signals.
- -Dproject.name: Sets the application name for this dashboard instance.
Once running, access the dashboard at http://localhost:8080 using the default credentials (username: sentinel, password: sentinel).
Integrating Sentinel with Spring Boot Applications
Sentinel's core functionality is leveraged through its integration libraries. The following example uses Spring Boot 2.3.13.RELEASE with Spring Cloud Alibaba 2.2.6.RELEASE.
1. Add Maven Dependency
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
2. Create a Service with Sentinel Protection
Define a service method and specify a fallback handler for rate limit exceptions using the @SentinelResource annotation.
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
@Service
public class DataProcessingService {
@SentinelResource(value = "fetchData", blockHandler = "rateLimitHandler")
public String fetchData() {
return "Data processed at: " + new Date();
}
public String rateLimitHandler(BlockException ex) {
return "Request rate limited. Please try again later.";
}
}
3. Create a REST Controller
@RestController
public class ApiController {
@Autowired
private DataProcessingService dataService;
@GetMapping("/data")
public String getData() {
return dataService.fetchData();
}
}
4. Initialize Flow Control Rules
Implement an InitFunc to define and load rate limiting rules, such as limiting the fetchData resource to 2 requests per second (QPS).
import com.alibaba.csp.sentinel.init.InitFunc;
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;
public class RuleInitializer implements InitFunc {
@Override
public void init() {
FlowRule rule = new FlowRule();
rule.setResource("fetchData");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setCount(2);
List<FlowRule> rules = new ArrayList<>();
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
}
Register this initializer by creating a file named com.alibaba.csp.sentinel.init.InitFunc in the src/main/resources/META-INF/services/ directory and adding the fully qualified class name: com.yourpackage.RuleInitializer.
Applying Sentinel to Apache Dubbo Services
Sentinel provides adapters for Apache Dubbo. For Dubbo 2.7.x and above, use the sentinel-apache-dubbo-adapter.
1. Add Dependencies
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-apache-dubbo-adapter</artifactId>
<version>1.8.1</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>1.8.1</version>
</dependency>
2. Configure Dubbo Resource Rules
Create a rule initializer targeting the Dubbo service interface. Resources can be defined at the interface or method level.
public class DubboRuleInitializer implements InitFunc {
@Override
public void init() {
FlowRule rule = new FlowRule();
// Rule for the entire service interface
rule.setResource("com.example.api.UserService");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setCount(2);
List<FlowRule> rules = new ArrayList<>();
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
}
Resource Naming Convention:
- Service Interface:
<interface_full_name>(e.g.,com.example.api.UserService) - Service Method:
<interface_full_name>:<method_signature>(e.g.,com.example.api.UserService:getUserById(java.lang.Long))
Register this initializer as described previously and add the dashboard connection to your application.properties:
spring.cloud.sentinel.transport.dashboard=localhost:8080
3. Handling Dubbo Rate Limit Exceptions
When a Dubbo service call is rate-limited, a SentinelBlockException wrapping a FlowException is thrown to the caller. Client code should catch this BlockException to implement appropriate fallback logic.
try {
userService.getUserById(id);
} catch (BlockException e) {
// Handle the rate-limited request
log.warn("Service call rate limited: " + e.getMessage());
}