diff --git a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/cluster/ClusterStateManager.java b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/cluster/ClusterStateManager.java
index 4a4b1334..3c15f87d 100644
--- a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/cluster/ClusterStateManager.java
+++ b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/cluster/ClusterStateManager.java
@@ -27,7 +27,10 @@ import com.alibaba.csp.sentinel.property.SentinelProperty;
import com.alibaba.csp.sentinel.util.TimeUtil;
/**
- *
Global tate manager for Sentinel cluster. This enables switching between cluster client and server.
+ *
+ * Global state manager for Sentinel cluster.
+ * This enables switching between cluster token client and server mode.
+ *
*
* @author Eric Zhao
* @since 1.4.0
@@ -36,15 +39,14 @@ public final class ClusterStateManager {
public static final int CLUSTER_CLIENT = 0;
public static final int CLUSTER_SERVER = 1;
+ public static final int CLUSTER_NOT_STARTED = -1;
- private static volatile int mode = -1;
+ private static volatile int mode = CLUSTER_NOT_STARTED;
private static volatile long lastModified = -1;
private static volatile SentinelProperty stateProperty = new DynamicSentinelProperty();
private static final PropertyListener PROPERTY_LISTENER = new ClusterStatePropertyListener();
- private static final Object UPDATE_LOCK = new Object();
-
static {
InitExecutor.doInit();
stateProperty.addListener(PROPERTY_LISTENER);
@@ -206,34 +208,62 @@ public final class ClusterStateManager {
private static class ClusterStatePropertyListener implements PropertyListener {
@Override
public synchronized void configLoad(Integer value) {
- applyState(value);
+ applyStateInternal(value);
}
@Override
public synchronized void configUpdate(Integer value) {
- applyState(value);
+ applyStateInternal(value);
}
}
- public static boolean applyState(Integer state) {
- if (state == null || state < 0) {
+ private static boolean applyStateInternal(Integer state) {
+ if (state == null || state < CLUSTER_NOT_STARTED) {
return false;
}
if (state == mode) {
return true;
}
- synchronized (UPDATE_LOCK) {
- switch (state) {
- case CLUSTER_CLIENT:
- return setToClient();
- case CLUSTER_SERVER:
- return setToServer();
- default:
- RecordLog.warn("[ClusterStateManager] Ignoring unknown cluster state: " + state);
- return false;
- }
+ switch (state) {
+ case CLUSTER_CLIENT:
+ return setToClient();
+ case CLUSTER_SERVER:
+ return setToServer();
+ case CLUSTER_NOT_STARTED:
+ setStop();
+ return true;
+ default:
+ RecordLog.warn("[ClusterStateManager] Ignoring unknown cluster state: " + state);
+ return false;
}
}
+ private static void setStop() {
+ if (mode == CLUSTER_NOT_STARTED) {
+ return;
+ }
+ RecordLog.info("[ClusterStateManager] Changing cluster mode to not-started");
+ mode = CLUSTER_NOT_STARTED;
+
+ sleepIfNeeded();
+ lastModified = TimeUtil.currentTimeMillis();
+
+ stopClient();
+ stopServer();
+ }
+
+ /**
+ * Apply given state to cluster mode.
+ *
+ * @param state valid state to apply
+ */
+ public static void applyState(Integer state) {
+ stateProperty.updateValue(state);
+ }
+
+ public static void markToServer() {
+ mode = CLUSTER_SERVER;
+ }
+
private static final int MIN_INTERVAL = 5 * 1000;
}
diff --git a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/cluster/client/TokenClientProvider.java b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/cluster/client/TokenClientProvider.java
index c46a75ec..def2f016 100644
--- a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/cluster/client/TokenClientProvider.java
+++ b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/cluster/client/TokenClientProvider.java
@@ -49,5 +49,9 @@ public final class TokenClientProvider {
}
}
+ public static boolean isClientSpiAvailable() {
+ return getClient() != null;
+ }
+
private TokenClientProvider() {}
}
diff --git a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/cluster/server/EmbeddedClusterTokenServerProvider.java b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/cluster/server/EmbeddedClusterTokenServerProvider.java
index bd3da760..6b76af93 100644
--- a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/cluster/server/EmbeddedClusterTokenServerProvider.java
+++ b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/cluster/server/EmbeddedClusterTokenServerProvider.java
@@ -44,5 +44,9 @@ public final class EmbeddedClusterTokenServerProvider {
return server;
}
+ public static boolean isServerSpiAvailable() {
+ return getServer() != null;
+ }
+
private EmbeddedClusterTokenServerProvider() {}
}
diff --git a/sentinel-transport/sentinel-transport-common/src/main/java/com/alibaba/csp/sentinel/command/handler/cluster/ModifyClusterModeCommandHandler.java b/sentinel-transport/sentinel-transport-common/src/main/java/com/alibaba/csp/sentinel/command/handler/cluster/ModifyClusterModeCommandHandler.java
index 072a52b0..9841c02f 100644
--- a/sentinel-transport/sentinel-transport-common/src/main/java/com/alibaba/csp/sentinel/command/handler/cluster/ModifyClusterModeCommandHandler.java
+++ b/sentinel-transport/sentinel-transport-common/src/main/java/com/alibaba/csp/sentinel/command/handler/cluster/ModifyClusterModeCommandHandler.java
@@ -16,6 +16,8 @@
package com.alibaba.csp.sentinel.command.handler.cluster;
import com.alibaba.csp.sentinel.cluster.ClusterStateManager;
+import com.alibaba.csp.sentinel.cluster.client.TokenClientProvider;
+import com.alibaba.csp.sentinel.cluster.server.EmbeddedClusterTokenServerProvider;
import com.alibaba.csp.sentinel.command.CommandHandler;
import com.alibaba.csp.sentinel.command.CommandRequest;
import com.alibaba.csp.sentinel.command.CommandResponse;
@@ -33,16 +35,24 @@ public class ModifyClusterModeCommandHandler implements CommandHandler {
public CommandResponse handle(CommandRequest request) {
try {
int mode = Integer.valueOf(request.getParam("mode"));
- RecordLog.info("[ModifyClusterModeCommandHandler] Modifying cluster mode to: " + mode);
- if (ClusterStateManager.applyState(mode)) {
- return CommandResponse.ofSuccess("success");
- } else {
- return CommandResponse.ofSuccess("failed");
+ if (mode == ClusterStateManager.CLUSTER_CLIENT && !TokenClientProvider.isClientSpiAvailable()) {
+ return CommandResponse.ofFailure(new IllegalStateException("token client mode not available: no SPI found"));
}
+ if (mode == ClusterStateManager.CLUSTER_SERVER && !isClusterServerSpiAvailable()) {
+ return CommandResponse.ofFailure(new IllegalStateException("token server mode not available: no SPI found"));
+ }
+ RecordLog.info("[ModifyClusterModeCommandHandler] Modifying cluster mode to: " + mode);
+
+ ClusterStateManager.applyState(mode);
+ return CommandResponse.ofSuccess("success");
} catch (NumberFormatException ex) {
- return CommandResponse.ofFailure(new IllegalArgumentException("invalid mode"));
+ return CommandResponse.ofFailure(new IllegalArgumentException("invalid parameter"));
} catch (Exception ex) {
return CommandResponse.ofFailure(ex);
}
}
+
+ private boolean isClusterServerSpiAvailable() {
+ return EmbeddedClusterTokenServerProvider.isServerSpiAvailable();
+ }
}