- Add several command handlers - Update cluster state manager Signed-off-by: Eric Zhao <sczyh16@gmail.com>master
@@ -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)); | |||
} | |||
} | |||
@@ -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<String> { | |||
@Override | |||
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; | |||
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"); | |||
} | |||
} | |||
} | |||
@@ -1 +1,2 @@ | |||
com.alibaba.csp.sentinel.command.handler.ModifyClusterClientConfigHandler | |||
com.alibaba.csp.sentinel.command.handler.ModifyClusterClientConfigHandler | |||
com.alibaba.csp.sentinel.command.handler.FetchClusterClientConfigHandler |
@@ -43,6 +43,8 @@ public final class ClusterStateManager { | |||
private static volatile SentinelProperty<Integer> stateProperty = new DynamicSentinelProperty<Integer>(); | |||
private static final PropertyListener<Integer> 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. | |||
* </p> | |||
*/ | |||
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. | |||
* </p> | |||
*/ | |||
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; | |||
} | |||
} | |||
} | |||
@@ -13,7 +13,7 @@ | |||
<packaging>jar</packaging> | |||
<properties> | |||
<nacos.version>0.4.0</nacos.version> | |||
<nacos.version>0.2.1</nacos.version> | |||
</properties> | |||
<dependencies> | |||
@@ -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; | |||
} | |||
} |
@@ -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); | |||
} | |||
} | |||
} |
@@ -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 | |||
com.alibaba.csp.sentinel.command.handler.VersionCommandHandler | |||
com.alibaba.csp.sentinel.command.handler.FetchClusterModeCommandHandler | |||
com.alibaba.csp.sentinel.command.handler.ModifyClusterModeCommandHandler |