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:
parent
2d1313f220
commit
a5819e092d
|
|
@ -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;
|
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");
|
||||||
// TODO: parse the new config;
|
if (StringUtil.isBlank(data)) {
|
||||||
ClusterClientConfig clusterClientConfig = null;
|
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);
|
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 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) {
|
|
||||||
if (state == null || state < 0) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean applyState(Integer state) {
|
||||||
|
if (state == null || state < 0) {
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
Loading…
Reference in New Issue