Understanding Sentinel Cluster Rate Limiting: Principles, Modes, and Implementation Guide
This article explains the underlying principles of Sentinel's cluster rate‑limiting feature, compares embedded and independent deployment modes, and provides a step‑by‑step Java/SpringBoot implementation with Apollo dynamic configuration and sample test code.
Cluster Rate Limiting Principles
Sentinel adds a clusterMode flag to the normal flow‑control rule; when set to true the rule operates in cluster mode, otherwise it works as a single‑node limiter. In cluster mode a client communicates with a server to enforce the limit across multiple instances.
Embedded Mode
In the embedded (or token‑client) mode one micro‑service instance is elected as the token‑server while the remaining instances act as token‑clients. This avoids deploying a separate server, reduces cost and simplifies maintenance, but it lacks automatic fail‑over and is only suitable for a single micro‑service cluster.
Key drawbacks of embedded mode:
No automatic fault‑tolerance – if the server node crashes, the cluster falls back to single‑node limiting and manual re‑configuration is required.
Only works within a single micro‑service cluster; cross‑service clustering is not realistic.
The server node bears additional load because all clients must communicate with it.
Independent Mode
Independent mode deploys a dedicated token‑server outside the micro‑service cluster. It solves the two drawbacks of embedded mode: the server’s performance impact is isolated and the setup can serve multiple micro‑service clusters.
However, it introduces extra resource costs and the default server is single‑point, so a custom high‑availability solution must be implemented.
Running the Demo
The following Maven dependencies are required:
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-aspectj</artifactId>
<version>1.8.4</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>1.8.4</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-cluster-client-default</artifactId>
<version>1.8.4</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-cluster-server-default</artifactId>
<version>1.8.4</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-apollo</artifactId>
<version>1.8.4</version>
</dependency>Implement an InitFunc (e.g., com.irving.demo.init.DemoClusterInitFunc) and register it under META-INF/services/com.alibaba.csp.sentinel.init.InitFunc. The init function configures dynamic rule properties, client settings, server transport, and cluster state using Apollo data sources.
public class DemoClusterInitFunc implements InitFunc {
private final String namespace = "application";
private final String ruleKey = "demo_sentinel";
private final String ruleServerKey = "demo_cluster";
private final String defaultRuleValue = "[]";
@Override
public void init() throws Exception {
initDynamicRuleProperty();
initClientConfigProperty();
initClientServerAssignProperty();
registerClusterRuleSupplier();
initServerTransportConfigProperty();
initStateProperty();
}
// ... (other helper methods omitted for brevity)
}Sample Apollo JSON configuration for rules and cluster nodes:
demo_sentinel=[
{
"resource": "test_res",
"count": 20,
"clusterMode": true,
"clusterConfig": {"flowId":111,"thresholdType":1}
}
]
demo_cluster=[
{"ip":"192.168.3.20","machineId":"192.168.3.20@8720","port":9999,"state":1},
{"ip":"192.168.3.20","machineId":"192.168.3.20@8721","state":0},
{"ip":"192.168.3.20","machineId":"192.168.3.20@8722","state":0}
]Start the application with JVM arguments to set ports, e.g.:
-Dserver.port=9100 -Dcsp.sentinel.api.port=8720 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dcsp.sentinel.log.use.pid=trueA simple SpringBoot entry class launches the demo traffic generator:
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
new FlowQpsDemo();
}
}The traffic simulator creates multiple threads that repeatedly call SphU.entry(KEY), counting passed, blocked and total requests, and prints per‑second QPS statistics.
public class FlowQpsDemo {
private static final String KEY = "test_res";
private static final AtomicInteger pass = new AtomicInteger();
private static final AtomicInteger block = new AtomicInteger();
private static final AtomicInteger total = new AtomicInteger();
private static volatile boolean stop = false;
private static final int threadCount = 32;
private static int seconds = 100;
public FlowQpsDemo() { tick(); simulateTraffic(); }
// ... (timer and task classes omitted for brevity)
}After launching, the Sentinel dashboard shows the embedded token‑server and the aggregated QPS. Adding another client (e.g., port 9200, API port 8721) demonstrates automatic client reconnection and the effect of server fail‑over.
For independent deployment, start a dedicated token‑server and configure the client to point to its address using ClusterClientAssignConfig and ClusterServerConfigManager.loadGlobalTransportConfig(...).
Overall, the article provides a complete walkthrough of Sentinel cluster rate limiting, covering theory, deployment options, dynamic configuration via Apollo, and a runnable Java demo.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Wukong Talks Architecture
Explaining distributed systems and architecture through stories. Author of the "JVM Performance Tuning in Practice" column, open-source author of "Spring Cloud in Practice PassJava", and independently developed a PMP practice quiz mini-program.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
