Add HTTP command for modifying global state and client config

- Add several command handlers
- Update cluster state manager

Signed-off-by: Eric Zhao <sczyh16@gmail.com>
This commit is contained in:
Eric Zhao 2018-12-09 22:56:56 +08:00
parent 2d1313f220
commit a5819e092d
8 changed files with 186 additions and 21 deletions

View File

@ -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<String> {
@Override
public CommandResponse<String> handle(CommandRequest request) {
ClusterClientConfig config = new ClusterClientConfig()
.setServerHost(ClusterClientConfigManager.getServerHost())
.setServerPort(ClusterClientConfigManager.getServerPort())
.setRequestTimeout(ClusterClientConfigManager.getRequestTimeout());
return CommandResponse.ofSuccess(JSON.toJSONString(config));
}
}

View File

@ -15,28 +15,42 @@
*/ */
package com.alibaba.csp.sentinel.command.handler; 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.ClusterClientConfig;
import com.alibaba.csp.sentinel.cluster.client.config.ClusterClientConfigManager; import com.alibaba.csp.sentinel.cluster.client.config.ClusterClientConfigManager;
import com.alibaba.csp.sentinel.command.CommandHandler; import com.alibaba.csp.sentinel.command.CommandHandler;
import com.alibaba.csp.sentinel.command.CommandRequest; import com.alibaba.csp.sentinel.command.CommandRequest;
import com.alibaba.csp.sentinel.command.CommandResponse; import com.alibaba.csp.sentinel.command.CommandResponse;
import com.alibaba.csp.sentinel.command.annotation.CommandMapping; 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 * @author Eric Zhao
* @since 1.4.0 * @since 1.4.0
*/ */
@CommandMapping(name = "modifyClusterConfig") @CommandMapping(name = "cluster/client/modifyConfig")
public class ModifyClusterClientConfigHandler implements CommandHandler<String> { public class ModifyClusterClientConfigHandler implements CommandHandler<String> {
@Override @Override
public CommandResponse<String> handle(CommandRequest request) { public CommandResponse<String> 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; return CommandResponse.ofSuccess("ok");
ClusterClientConfig clusterClientConfig = null; } catch (Exception e) {
ClusterClientConfigManager.applyNewConfig(clusterClientConfig); RecordLog.warn("[ModifyClusterClientConfigHandler] Decode client cluster config error", e);
return CommandResponse.ofFailure(e, "decode client cluster config error");
return CommandResponse.ofSuccess("ok"); }
} }
} }

View File

@ -1 +1,2 @@
com.alibaba.csp.sentinel.command.handler.ModifyClusterClientConfigHandler com.alibaba.csp.sentinel.command.handler.ModifyClusterClientConfigHandler
com.alibaba.csp.sentinel.command.handler.FetchClusterClientConfigHandler

View File

@ -43,6 +43,8 @@ public final class ClusterStateManager {
private static volatile SentinelProperty<Integer> stateProperty = new DynamicSentinelProperty<Integer>(); private static volatile SentinelProperty<Integer> stateProperty = new DynamicSentinelProperty<Integer>();
private static final PropertyListener<Integer> PROPERTY_LISTENER = new ClusterStatePropertyListener(); private static final PropertyListener<Integer> PROPERTY_LISTENER = new ClusterStatePropertyListener();
private static final Object UPDATE_LOCK = new Object();
static { static {
InitExecutor.doInit(); InitExecutor.doInit();
stateProperty.addListener(PROPERTY_LISTENER); stateProperty.addListener(PROPERTY_LISTENER);
@ -75,9 +77,9 @@ public final class ClusterStateManager {
* it will be turned off. Then the cluster client will be started. * it will be turned off. Then the cluster client will be started.
* </p> * </p>
*/ */
public static void setToClient() { public static boolean setToClient() {
if (mode == CLUSTER_CLIENT) { if (mode == CLUSTER_CLIENT) {
return; return true;
} }
mode = CLUSTER_CLIENT; mode = CLUSTER_CLIENT;
sleepIfNeeded(); sleepIfNeeded();
@ -91,11 +93,14 @@ public final class ClusterStateManager {
if (tokenClient != null) { if (tokenClient != null) {
tokenClient.start(); tokenClient.start();
RecordLog.info("[ClusterStateManager] Changing cluster mode to client"); RecordLog.info("[ClusterStateManager] Changing cluster mode to client");
return true;
} else { } else {
RecordLog.warn("[ClusterStateManager] Cannot change to client (no client SPI found)"); RecordLog.warn("[ClusterStateManager] Cannot change to client (no client SPI found)");
return false;
} }
} catch (Exception ex) { } catch (Exception ex) {
RecordLog.warn("[ClusterStateManager] Error when changing cluster mode to client", 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. * it will be turned off. Then the cluster server will be started.
* </p> * </p>
*/ */
public static void setToServer() { public static boolean setToServer() {
if (mode == CLUSTER_SERVER) { if (mode == CLUSTER_SERVER) {
return; return true;
} }
mode = CLUSTER_SERVER; mode = CLUSTER_SERVER;
sleepIfNeeded(); sleepIfNeeded();
@ -121,11 +126,14 @@ public final class ClusterStateManager {
if (server != null) { if (server != null) {
server.start(); server.start();
RecordLog.info("[ClusterStateManager] Changing cluster mode to server"); RecordLog.info("[ClusterStateManager] Changing cluster mode to server");
return true;
} else { } else {
RecordLog.warn("[ClusterStateManager] Cannot change to server (no server SPI found)"); RecordLog.warn("[ClusterStateManager] Cannot change to server (no server SPI found)");
return false;
} }
} catch (Exception ex) { } catch (Exception ex) {
RecordLog.warn("[ClusterStateManager] Error when changing cluster mode to server", 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) { public void configUpdate(Integer value) {
applyState(value); applyState(value);
} }
}
private synchronized void applyState(Integer state) { public static boolean applyState(Integer state) {
if (state == null || state < 0) { if (state == null || state < 0) {
return; return false;
} }
synchronized (UPDATE_LOCK) {
switch (state) { switch (state) {
case CLUSTER_CLIENT: case CLUSTER_CLIENT:
setToClient(); return setToClient();
break;
case CLUSTER_SERVER: case CLUSTER_SERVER:
setToServer(); return setToServer();
break;
default: default:
RecordLog.warn("[ClusterStateManager] Ignoring unknown cluster state: " + state); RecordLog.warn("[ClusterStateManager] Ignoring unknown cluster state: " + state);
return false;
} }
} }
} }

View File

@ -13,7 +13,7 @@
<packaging>jar</packaging> <packaging>jar</packaging>
<properties> <properties>
<nacos.version>0.4.0</nacos.version> <nacos.version>0.2.1</nacos.version>
</properties> </properties>
<dependencies> <dependencies>

View File

@ -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<String> {
@Override
public CommandResponse<String> 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;
}
}

View File

@ -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<String> {
@Override
public CommandResponse<String> 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);
}
}
}

View File

@ -12,3 +12,5 @@ com.alibaba.csp.sentinel.command.handler.OnOffGetCommandHandler
com.alibaba.csp.sentinel.command.handler.OnOffSetCommandHandler com.alibaba.csp.sentinel.command.handler.OnOffSetCommandHandler
com.alibaba.csp.sentinel.command.handler.SendMetricCommandHandler com.alibaba.csp.sentinel.command.handler.SendMetricCommandHandler
com.alibaba.csp.sentinel.command.handler.VersionCommandHandler com.alibaba.csp.sentinel.command.handler.VersionCommandHandler
com.alibaba.csp.sentinel.command.handler.FetchClusterModeCommandHandler
com.alibaba.csp.sentinel.command.handler.ModifyClusterModeCommandHandler