From a5819e092dafaa097606fb37bc7cd8256276882b Mon Sep 17 00:00:00 2001 From: Eric Zhao Date: Sun, 9 Dec 2018 22:56:56 +0800 Subject: [PATCH] Add HTTP command for modifying global state and client config - Add several command handlers - Update cluster state manager Signed-off-by: Eric Zhao --- .../FetchClusterClientConfigHandler.java | 42 +++++++++++++++ .../ModifyClusterClientConfigHandler.java | 26 +++++++--- ...libaba.csp.sentinel.command.CommandHandler | 3 +- .../sentinel/cluster/ClusterStateManager.java | 33 +++++++----- .../sentinel-datasource-nacos/pom.xml | 2 +- .../FetchClusterModeCommandHandler.java | 51 +++++++++++++++++++ .../ModifyClusterModeCommandHandler.java | 46 +++++++++++++++++ ...libaba.csp.sentinel.command.CommandHandler | 4 +- 8 files changed, 186 insertions(+), 21 deletions(-) create mode 100644 sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/command/handler/FetchClusterClientConfigHandler.java create mode 100644 sentinel-transport/sentinel-transport-common/src/main/java/com/alibaba/csp/sentinel/command/handler/FetchClusterModeCommandHandler.java create mode 100644 sentinel-transport/sentinel-transport-common/src/main/java/com/alibaba/csp/sentinel/command/handler/ModifyClusterModeCommandHandler.java diff --git a/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/command/handler/FetchClusterClientConfigHandler.java b/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/command/handler/FetchClusterClientConfigHandler.java new file mode 100644 index 00000000..407d7311 --- /dev/null +++ b/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/command/handler/FetchClusterClientConfigHandler.java @@ -0,0 +1,42 @@ +/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.csp.sentinel.command.handler; + +import com.alibaba.csp.sentinel.cluster.client.config.ClusterClientConfig; +import com.alibaba.csp.sentinel.cluster.client.config.ClusterClientConfigManager; +import com.alibaba.csp.sentinel.command.CommandHandler; +import com.alibaba.csp.sentinel.command.CommandRequest; +import com.alibaba.csp.sentinel.command.CommandResponse; +import com.alibaba.csp.sentinel.command.annotation.CommandMapping; +import com.alibaba.fastjson.JSON; + +/** + * @author Eric Zhao + * @since 1.4.0 + */ +@CommandMapping(name = "cluster/client/fetchConfig") +public class FetchClusterClientConfigHandler implements CommandHandler { + + @Override + public CommandResponse handle(CommandRequest request) { + ClusterClientConfig config = new ClusterClientConfig() + .setServerHost(ClusterClientConfigManager.getServerHost()) + .setServerPort(ClusterClientConfigManager.getServerPort()) + .setRequestTimeout(ClusterClientConfigManager.getRequestTimeout()); + return CommandResponse.ofSuccess(JSON.toJSONString(config)); + } +} + diff --git a/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/command/handler/ModifyClusterClientConfigHandler.java b/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/command/handler/ModifyClusterClientConfigHandler.java index 5cc5b4f8..8614fb8f 100644 --- a/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/command/handler/ModifyClusterClientConfigHandler.java +++ b/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/command/handler/ModifyClusterClientConfigHandler.java @@ -15,28 +15,42 @@ */ package com.alibaba.csp.sentinel.command.handler; +import java.net.URLDecoder; + import com.alibaba.csp.sentinel.cluster.client.config.ClusterClientConfig; import com.alibaba.csp.sentinel.cluster.client.config.ClusterClientConfigManager; import com.alibaba.csp.sentinel.command.CommandHandler; import com.alibaba.csp.sentinel.command.CommandRequest; import com.alibaba.csp.sentinel.command.CommandResponse; import com.alibaba.csp.sentinel.command.annotation.CommandMapping; +import com.alibaba.csp.sentinel.log.RecordLog; +import com.alibaba.csp.sentinel.util.StringUtil; +import com.alibaba.fastjson.JSON; /** * @author Eric Zhao * @since 1.4.0 */ -@CommandMapping(name = "modifyClusterConfig") +@CommandMapping(name = "cluster/client/modifyConfig") public class ModifyClusterClientConfigHandler implements CommandHandler { @Override public CommandResponse handle(CommandRequest request) { + String data = request.getParam("data"); + if (StringUtil.isBlank(data)) { + return CommandResponse.ofFailure(new IllegalArgumentException("empty data")); + } + try { + data = URLDecoder.decode(data, "utf-8"); + RecordLog.info("[ModifyClusterClientConfigHandler] Receiving cluster client config: " + data); + ClusterClientConfig clusterClientConfig = JSON.parseObject(data, ClusterClientConfig.class); + ClusterClientConfigManager.applyNewConfig(clusterClientConfig); - // TODO: parse the new config; - ClusterClientConfig clusterClientConfig = null; - ClusterClientConfigManager.applyNewConfig(clusterClientConfig); - - return CommandResponse.ofSuccess("ok"); + return CommandResponse.ofSuccess("ok"); + } catch (Exception e) { + RecordLog.warn("[ModifyClusterClientConfigHandler] Decode client cluster config error", e); + return CommandResponse.ofFailure(e, "decode client cluster config error"); + } } } diff --git a/sentinel-cluster/sentinel-cluster-client-default/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.command.CommandHandler b/sentinel-cluster/sentinel-cluster-client-default/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.command.CommandHandler index a0af73b5..80d3582c 100755 --- a/sentinel-cluster/sentinel-cluster-client-default/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.command.CommandHandler +++ b/sentinel-cluster/sentinel-cluster-client-default/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.command.CommandHandler @@ -1 +1,2 @@ -com.alibaba.csp.sentinel.command.handler.ModifyClusterClientConfigHandler \ No newline at end of file +com.alibaba.csp.sentinel.command.handler.ModifyClusterClientConfigHandler +com.alibaba.csp.sentinel.command.handler.FetchClusterClientConfigHandler \ No newline at end of file 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 2800b2f6..2a27c745 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 @@ -43,6 +43,8 @@ public final class ClusterStateManager { 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); @@ -75,9 +77,9 @@ public final class ClusterStateManager { * it will be turned off. Then the cluster client will be started. *

*/ - public static void setToClient() { + public static boolean setToClient() { if (mode == CLUSTER_CLIENT) { - return; + return true; } mode = CLUSTER_CLIENT; sleepIfNeeded(); @@ -91,11 +93,14 @@ public final class ClusterStateManager { if (tokenClient != null) { tokenClient.start(); RecordLog.info("[ClusterStateManager] Changing cluster mode to client"); + return true; } else { RecordLog.warn("[ClusterStateManager] Cannot change to client (no client SPI found)"); + return false; } } catch (Exception ex) { RecordLog.warn("[ClusterStateManager] Error when changing cluster mode to client", ex); + return false; } } @@ -105,9 +110,9 @@ public final class ClusterStateManager { * it will be turned off. Then the cluster server will be started. *

*/ - public static void setToServer() { + public static boolean setToServer() { if (mode == CLUSTER_SERVER) { - return; + return true; } mode = CLUSTER_SERVER; sleepIfNeeded(); @@ -121,11 +126,14 @@ public final class ClusterStateManager { if (server != null) { server.start(); RecordLog.info("[ClusterStateManager] Changing cluster mode to server"); + return true; } else { RecordLog.warn("[ClusterStateManager] Cannot change to server (no server SPI found)"); + return false; } } catch (Exception ex) { RecordLog.warn("[ClusterStateManager] Error when changing cluster mode to server", ex); + return false; } } @@ -163,20 +171,21 @@ public final class ClusterStateManager { public void configUpdate(Integer value) { applyState(value); } + } - private synchronized void applyState(Integer state) { - if (state == null || state < 0) { - return; - } + public static boolean applyState(Integer state) { + if (state == null || state < 0) { + return false; + } + synchronized (UPDATE_LOCK) { switch (state) { case CLUSTER_CLIENT: - setToClient(); - break; + return setToClient(); case CLUSTER_SERVER: - setToServer(); - break; + return setToServer(); default: RecordLog.warn("[ClusterStateManager] Ignoring unknown cluster state: " + state); + return false; } } } diff --git a/sentinel-extension/sentinel-datasource-nacos/pom.xml b/sentinel-extension/sentinel-datasource-nacos/pom.xml index 54f686d5..dd0b0444 100644 --- a/sentinel-extension/sentinel-datasource-nacos/pom.xml +++ b/sentinel-extension/sentinel-datasource-nacos/pom.xml @@ -13,7 +13,7 @@ jar - 0.4.0 + 0.2.1 diff --git a/sentinel-transport/sentinel-transport-common/src/main/java/com/alibaba/csp/sentinel/command/handler/FetchClusterModeCommandHandler.java b/sentinel-transport/sentinel-transport-common/src/main/java/com/alibaba/csp/sentinel/command/handler/FetchClusterModeCommandHandler.java new file mode 100644 index 00000000..11eac68f --- /dev/null +++ b/sentinel-transport/sentinel-transport-common/src/main/java/com/alibaba/csp/sentinel/command/handler/FetchClusterModeCommandHandler.java @@ -0,0 +1,51 @@ +/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.csp.sentinel.command.handler; + +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; +import com.alibaba.csp.sentinel.command.annotation.CommandMapping; +import com.alibaba.fastjson.JSONObject; + +/** + * @author Eric Zhao + * @since 1.4.0 + */ +@CommandMapping(name = "getClusterMode") +public class FetchClusterModeCommandHandler implements CommandHandler { + + @Override + public CommandResponse handle(CommandRequest request) { + JSONObject res = new JSONObject() + .fluentPut("mode", ClusterStateManager.getMode()) + .fluentPut("lastModified", ClusterStateManager.getLastModified()) + .fluentPut("clientAvailable", isClusterClientSpiAvailable()) + .fluentPut("serverAvailable", isClusterServerSpiAvailable()); + return CommandResponse.ofSuccess(res.toJSONString()); + } + + private boolean isClusterClientSpiAvailable() { + return TokenClientProvider.getClient() != null; + } + + private boolean isClusterServerSpiAvailable() { + return EmbeddedClusterTokenServerProvider.getServer() != null; + } +} diff --git a/sentinel-transport/sentinel-transport-common/src/main/java/com/alibaba/csp/sentinel/command/handler/ModifyClusterModeCommandHandler.java b/sentinel-transport/sentinel-transport-common/src/main/java/com/alibaba/csp/sentinel/command/handler/ModifyClusterModeCommandHandler.java new file mode 100644 index 00000000..1d67292e --- /dev/null +++ b/sentinel-transport/sentinel-transport-common/src/main/java/com/alibaba/csp/sentinel/command/handler/ModifyClusterModeCommandHandler.java @@ -0,0 +1,46 @@ +/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.csp.sentinel.command.handler; + +import com.alibaba.csp.sentinel.cluster.ClusterStateManager; +import com.alibaba.csp.sentinel.command.CommandHandler; +import com.alibaba.csp.sentinel.command.CommandRequest; +import com.alibaba.csp.sentinel.command.CommandResponse; +import com.alibaba.csp.sentinel.command.annotation.CommandMapping; + +/** + * @author Eric Zhao + * @since 1.4.0 + */ +@CommandMapping(name = "setClusterMode") +public class ModifyClusterModeCommandHandler implements CommandHandler { + + @Override + public CommandResponse handle(CommandRequest request) { + try { + int mode = Integer.valueOf(request.getParam("mode")); + if (ClusterStateManager.applyState(mode)) { + return CommandResponse.ofSuccess("success"); + } else { + return CommandResponse.ofSuccess("failed"); + } + } catch (NumberFormatException ex) { + return CommandResponse.ofFailure(new IllegalArgumentException("invalid mode")); + } catch (Exception ex) { + return CommandResponse.ofFailure(ex); + } + } +} diff --git a/sentinel-transport/sentinel-transport-common/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.command.CommandHandler b/sentinel-transport/sentinel-transport-common/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.command.CommandHandler index 1dd95c88..4cd2606e 100755 --- a/sentinel-transport/sentinel-transport-common/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.command.CommandHandler +++ b/sentinel-transport/sentinel-transport-common/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.command.CommandHandler @@ -11,4 +11,6 @@ com.alibaba.csp.sentinel.command.handler.ModifyRulesCommandHandler com.alibaba.csp.sentinel.command.handler.OnOffGetCommandHandler com.alibaba.csp.sentinel.command.handler.OnOffSetCommandHandler com.alibaba.csp.sentinel.command.handler.SendMetricCommandHandler -com.alibaba.csp.sentinel.command.handler.VersionCommandHandler \ No newline at end of file +com.alibaba.csp.sentinel.command.handler.VersionCommandHandler +com.alibaba.csp.sentinel.command.handler.FetchClusterModeCommandHandler +com.alibaba.csp.sentinel.command.handler.ModifyClusterModeCommandHandler \ No newline at end of file