From f83ea428ff2f72f485f18733e9c8239b6938e6d9 Mon Sep 17 00:00:00 2001 From: Eric Zhao Date: Tue, 27 Nov 2018 13:07:20 +0800 Subject: [PATCH] Update token client interface and default implementation Signed-off-by: Eric Zhao --- .../sentinel-cluster-client-default/pom.xml | 16 +++ .../client/DefaultClusterTokenClient.java | 88 ++++++++++++-- .../cluster/client/NettyTransportClient.java | 28 +++-- .../codec/DefaultRequestEntityWriter.java | 4 +- .../codec/netty/NettyRequestEncoder.java | 1 + .../client/config/ClusterClientConfig.java | 10 ++ .../config/ClusterClientConfigManager.java | 111 +++++++++++++++++- .../client/config/ServerChangeObserver.java | 30 +++++ .../client/handler/TokenClientHandler.java | 8 +- .../ModifyClusterClientConfigHandler.java | 42 +++++++ ...ba.csp.sentinel.cluster.ClusterTokenClient | 1 + ...libaba.csp.sentinel.command.CommandHandler | 1 + .../cluster/ClusterTransportClient.java | 21 ++++ .../sentinel/cluster/ClusterTokenClient.java | 2 +- .../cluster/TokenServerDescriptor.java | 17 +-- .../alibaba/csp/sentinel/util/AssertUtil.java | 6 + 16 files changed, 345 insertions(+), 41 deletions(-) create mode 100644 sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/config/ServerChangeObserver.java create mode 100644 sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/command/handler/ModifyClusterClientConfigHandler.java create mode 100644 sentinel-cluster/sentinel-cluster-client-default/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.cluster.ClusterTokenClient create mode 100755 sentinel-cluster/sentinel-cluster-client-default/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.command.CommandHandler diff --git a/sentinel-cluster/sentinel-cluster-client-default/pom.xml b/sentinel-cluster/sentinel-cluster-client-default/pom.xml index 42b89d43..de189630 100644 --- a/sentinel-cluster/sentinel-cluster-client-default/pom.xml +++ b/sentinel-cluster/sentinel-cluster-client-default/pom.xml @@ -17,6 +17,11 @@ com.alibaba.csp sentinel-core + + com.alibaba.csp + sentinel-transport-common + provided + com.alibaba.csp sentinel-cluster-common-default @@ -26,5 +31,16 @@ io.netty netty-all + + + junit + junit + test + + + org.mockito + mockito-core + test + \ No newline at end of file diff --git a/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/DefaultClusterTokenClient.java b/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/DefaultClusterTokenClient.java index 668f43bd..1d7bc646 100644 --- a/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/DefaultClusterTokenClient.java +++ b/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/DefaultClusterTokenClient.java @@ -24,32 +24,92 @@ import com.alibaba.csp.sentinel.cluster.TokenResult; import com.alibaba.csp.sentinel.cluster.TokenResultStatus; import com.alibaba.csp.sentinel.cluster.TokenServerDescriptor; 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.ServerChangeObserver; import com.alibaba.csp.sentinel.cluster.log.ClusterStatLogUtil; import com.alibaba.csp.sentinel.cluster.request.ClusterRequest; import com.alibaba.csp.sentinel.cluster.request.data.FlowRequestData; import com.alibaba.csp.sentinel.cluster.request.data.ParamFlowRequestData; import com.alibaba.csp.sentinel.cluster.response.ClusterResponse; import com.alibaba.csp.sentinel.cluster.response.data.FlowTokenResponseData; +import com.alibaba.csp.sentinel.log.RecordLog; +import com.alibaba.csp.sentinel.util.StringUtil; /** + * Default implementation of {@link ClusterTokenClient}. + * * @author Eric Zhao * @since 1.4.0 */ public class DefaultClusterTokenClient implements ClusterTokenClient { private ClusterTransportClient transportClient; + private TokenServerDescriptor serverDescriptor; public DefaultClusterTokenClient() { - // TODO: load and create transport client here. + ClusterClientConfigManager.addServerChangeObserver(new ServerChangeObserver() { + @Override + public void onRemoteServerChange(ClusterClientConfig clusterClientConfig) { + changeServer(clusterClientConfig); + } + }); + initNewConnection(); } public DefaultClusterTokenClient(ClusterTransportClient transportClient) { + // TODO: only for test, remove this constructor. this.transportClient = transportClient; } + private boolean serverEqual(TokenServerDescriptor descriptor, ClusterClientConfig config) { + if (descriptor == null || config == null) { + return false; + } + return descriptor.getHost().equals(config.getServerHost()) && descriptor.getPort() == config.getServerPort(); + } + + private void initNewConnection() { + if (transportClient != null) { + return; + } + String host = ClusterClientConfigManager.getServerHost(); + int port = ClusterClientConfigManager.getServerPort(); + if (StringUtil.isBlank(host) || port <= 0) { + return; + } + + try { + this.transportClient = new NettyTransportClient(host, port); + this.serverDescriptor = new TokenServerDescriptor(host, port); + transportClient.start(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + private void changeServer(/*@Valid*/ ClusterClientConfig config) { + if (serverEqual(serverDescriptor, config)) { + return; + } + try { + // TODO: what if the client is pending init? + if (transportClient != null && transportClient.isReady()) { + transportClient.stop(); + } + // Replace with new, even if the new client is not ready. + this.transportClient = new NettyTransportClient(config); + this.serverDescriptor = new TokenServerDescriptor(config.getServerHost(), config.getServerPort()); + transportClient.start(); + RecordLog.info("[DefaultClusterTokenClient] New client created: " + serverDescriptor); + } catch (Exception ex) { + RecordLog.warn("[DefaultClusterTokenClient] Failed to change remote token server", ex); + ex.printStackTrace(); + } + } + @Override public TokenServerDescriptor currentServer() { - return new TokenServerDescriptor(); + return serverDescriptor; } @Override @@ -84,15 +144,11 @@ public class DefaultClusterTokenClient implements ClusterTokenClient { } } - private boolean notValidRequest(Long id, int count) { - return id == null || id <= 0 || count <= 0; - } - - private TokenResult badRequest() { - return new TokenResult(TokenResultStatus.BAD_REQUEST); - } - private TokenResult sendTokenRequest(ClusterRequest request) throws Exception { + if (transportClient == null) { + RecordLog.warn("[DefaultClusterTokenClient] Client not created, please check your config for cluster client"); + return clientFail(); + } ClusterResponse response = transportClient.sendRequest(request); TokenResult result = new TokenResult(response.getStatus()); if (response.getData() != null) { @@ -102,4 +158,16 @@ public class DefaultClusterTokenClient implements ClusterTokenClient { } return result; } + + private boolean notValidRequest(Long id, int count) { + return id == null || id <= 0 || count <= 0; + } + + private TokenResult badRequest() { + return new TokenResult(TokenResultStatus.BAD_REQUEST); + } + + private TokenResult clientFail() { + return new TokenResult(TokenResultStatus.FAIL); + } } diff --git a/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/NettyTransportClient.java b/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/NettyTransportClient.java index 676f4d44..6fd21379 100644 --- a/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/NettyTransportClient.java +++ b/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/NettyTransportClient.java @@ -23,6 +23,7 @@ import com.alibaba.csp.sentinel.cluster.ClusterTransportClient; import com.alibaba.csp.sentinel.cluster.client.codec.netty.NettyRequestEncoder; import com.alibaba.csp.sentinel.cluster.client.codec.netty.NettyResponseDecoder; 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.handler.TokenClientHandler; import com.alibaba.csp.sentinel.cluster.client.handler.TokenClientPromiseHolder; import com.alibaba.csp.sentinel.cluster.exception.SentinelClusterException; @@ -55,20 +56,25 @@ import io.netty.util.concurrent.GenericFutureListener; */ public class NettyTransportClient implements ClusterTransportClient { - private ClusterClientConfig clientConfig; - private String host; - private int port; + private final String host; + private final int port; private Channel channel; private NioEventLoopGroup eventLoopGroup; private TokenClientHandler clientHandler; private AtomicInteger idGenerator = new AtomicInteger(0); - private AtomicInteger failConnectedTime = new AtomicInteger(0); - public NettyTransportClient(ClusterClientConfig clientConfig, String host, int port) { - this.clientConfig = clientConfig; + public NettyTransportClient(ClusterClientConfig clientConfig) { + AssertUtil.notNull(clientConfig, "client config cannot be null"); + this.host = clientConfig.getServerHost(); + this.port = clientConfig.getServerPort(); + } + + public NettyTransportClient(String host, int port) { + AssertUtil.assertNotBlank(host, "remote host cannot be blank"); + AssertUtil.isTrue(port > 0, "port should be positive"); this.host = host; this.port = port; } @@ -117,11 +123,13 @@ public class NettyTransportClient implements ClusterTransportClient { }); } - public void start() { + @Override + public void start() throws Exception { connect(initClientBootstrap()); } - public void stop() { + @Override + public void stop() throws Exception { if (channel != null) { channel.close(); channel = null; @@ -138,6 +146,7 @@ public class NettyTransportClient implements ClusterTransportClient { return request != null && request.getType() >= 0; } + @Override public boolean isReady() { return channel != null && clientHandler != null && clientHandler.hasStarted(); } @@ -159,8 +168,7 @@ public class NettyTransportClient implements ClusterTransportClient { ChannelPromise promise = channel.newPromise(); TokenClientPromiseHolder.putPromise(xid, promise); - // TODO: timeout - if (!promise.await(20)) { + if (!promise.await(ClusterClientConfigManager.getRequestTimeout())) { throw new SentinelClusterException(ClusterErrorMessages.REQUEST_TIME_OUT); } diff --git a/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/codec/DefaultRequestEntityWriter.java b/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/codec/DefaultRequestEntityWriter.java index c4a3ce91..f3dad331 100644 --- a/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/codec/DefaultRequestEntityWriter.java +++ b/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/codec/DefaultRequestEntityWriter.java @@ -37,8 +37,8 @@ public class DefaultRequestEntityWriter implements RequestEntityWriter, dropping the request", type); + RecordLog.warn("[DefaultRequestEntityWriter] Cannot find matching request writer for type <{0}>," + + " dropping the request", type); return; } // Write head part of request. diff --git a/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/codec/netty/NettyRequestEncoder.java b/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/codec/netty/NettyRequestEncoder.java index bc8b05cb..50a0476e 100644 --- a/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/codec/netty/NettyRequestEncoder.java +++ b/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/codec/netty/NettyRequestEncoder.java @@ -27,6 +27,7 @@ import io.netty.handler.codec.MessageToByteEncoder; /** * @author Eric Zhao + * @since 1.4.0 */ public class NettyRequestEncoder extends MessageToByteEncoder { diff --git a/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/config/ClusterClientConfig.java b/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/config/ClusterClientConfig.java index 81a0edf0..87f048e9 100644 --- a/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/config/ClusterClientConfig.java +++ b/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/config/ClusterClientConfig.java @@ -62,4 +62,14 @@ public class ClusterClientConfig { this.connectTimeout = connectTimeout; return this; } + + @Override + public String toString() { + return "ClusterClientConfig{" + + "serverHost='" + serverHost + '\'' + + ", serverPort=" + serverPort + + ", requestTimeout=" + requestTimeout + + ", connectTimeout=" + connectTimeout + + '}'; + } } diff --git a/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/config/ClusterClientConfigManager.java b/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/config/ClusterClientConfigManager.java index 94ade2d9..834bdcd7 100644 --- a/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/config/ClusterClientConfigManager.java +++ b/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/config/ClusterClientConfigManager.java @@ -15,16 +15,125 @@ */ package com.alibaba.csp.sentinel.cluster.client.config; +import java.util.ArrayList; +import java.util.List; + import com.alibaba.csp.sentinel.cluster.ClusterConstants; +import com.alibaba.csp.sentinel.log.RecordLog; +import com.alibaba.csp.sentinel.property.DynamicSentinelProperty; +import com.alibaba.csp.sentinel.property.PropertyListener; +import com.alibaba.csp.sentinel.property.SentinelProperty; +import com.alibaba.csp.sentinel.util.AssertUtil; +import com.alibaba.csp.sentinel.util.StringUtil; /** * @author Eric Zhao + * @since 1.4.0 */ public final class ClusterClientConfigManager { - private static volatile String serverIp; + /** + * Client config properties. + */ + private static volatile String serverHost = null; private static volatile int serverPort = ClusterConstants.DEFAULT_CLUSTER_SERVER_PORT; private static volatile int requestTimeout = ClusterConstants.DEFAULT_REQUEST_TIMEOUT; + private static final PropertyListener PROPERTY_LISTENER = new ClientConfigPropertyListener(); + private static SentinelProperty currentProperty = new DynamicSentinelProperty<>(); + + private static final List SERVER_CHANGE_OBSERVERS = new ArrayList<>(); + + static { + currentProperty.addListener(PROPERTY_LISTENER); + } + + public static void register2Property(SentinelProperty property) { + synchronized (PROPERTY_LISTENER) { + RecordLog.info("[ClusterClientConfigManager] Registering new property to cluster client config manager"); + currentProperty.removeListener(PROPERTY_LISTENER); + property.addListener(PROPERTY_LISTENER); + currentProperty = property; + } + } + + public static void addServerChangeObserver(ServerChangeObserver observer) { + AssertUtil.notNull(observer, "observer cannot be null"); + SERVER_CHANGE_OBSERVERS.add(observer); + } + + /** + * Apply new {@link ClusterClientConfig}, while the former config will be replaced. + * + * @param config new config to apply + */ + public static void applyNewConfig(ClusterClientConfig config) { + currentProperty.updateValue(config); + } + + private static class ClientConfigPropertyListener implements PropertyListener { + + @Override + public void configUpdate(ClusterClientConfig config) { + applyConfig(config); + } + + @Override + public void configLoad(ClusterClientConfig config) { + if (config == null) { + RecordLog.warn("[ClusterClientConfigManager] Empty initial config"); + return; + } + applyConfig(config); + } + + private synchronized void applyConfig(ClusterClientConfig config) { + if (!isValidConfig(config)) { + RecordLog.warn( + "[ClusterClientConfigManager] Invalid cluster client config, ignoring: " + config); + return; + } + RecordLog.info("[ClusterClientConfigManager] Updating new config: " + config); + if (config.getRequestTimeout() != requestTimeout) { + requestTimeout = config.getRequestTimeout(); + } + updateServer(config); + } + } + + public static boolean isValidConfig(ClusterClientConfig config) { + return config != null && StringUtil.isNotBlank(config.getServerHost()) + && config.getServerPort() > 0 + && config.getRequestTimeout() > 0; + } + + public static void updateServer(ClusterClientConfig config) { + String host = config.getServerHost(); + int port = config.getServerPort(); + AssertUtil.assertNotBlank(host, "token server host cannot be empty"); + AssertUtil.isTrue(port > 0, "token server port should be valid (positive)"); + if (serverPort == port && host.equals(serverHost)) { + return; + } + for (ServerChangeObserver observer : SERVER_CHANGE_OBSERVERS) { + observer.onRemoteServerChange(config); + } + + serverHost = host; + serverPort = port; + } + + public static String getServerHost() { + return serverHost; + } + + public static int getServerPort() { + return serverPort; + } + + public static int getRequestTimeout() { + return requestTimeout; + } + private ClusterClientConfigManager() {} } diff --git a/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/config/ServerChangeObserver.java b/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/config/ServerChangeObserver.java new file mode 100644 index 00000000..30908476 --- /dev/null +++ b/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/config/ServerChangeObserver.java @@ -0,0 +1,30 @@ +/* + * 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.cluster.client.config; + +/** + * @author Eric Zhao + * @since 1.4.0 + */ +public interface ServerChangeObserver { + + /** + * Callback on remote server address change. + * + * @param clusterClientConfig new cluster client config + */ + void onRemoteServerChange(ClusterClientConfig clusterClientConfig); +} diff --git a/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/handler/TokenClientHandler.java b/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/handler/TokenClientHandler.java index fc14cd35..564b9bb5 100644 --- a/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/handler/TokenClientHandler.java +++ b/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/handler/TokenClientHandler.java @@ -19,6 +19,7 @@ import java.util.concurrent.atomic.AtomicInteger; import com.alibaba.csp.sentinel.cluster.client.ClientConstants; import com.alibaba.csp.sentinel.cluster.response.ClusterResponse; +import com.alibaba.csp.sentinel.log.RecordLog; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; @@ -34,6 +35,7 @@ public class TokenClientHandler extends ChannelInboundHandlerAdapter { @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { currentState.set(ClientConstants.CLIENT_STATUS_STARTED); + RecordLog.info("[TokenClientHandler] Client handler active, remote address: " + ctx.channel().remoteAddress()); } @Override @@ -48,13 +50,13 @@ public class TokenClientHandler extends ChannelInboundHandlerAdapter { @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - super.exceptionCaught(ctx, cause); - cause.printStackTrace(); + // TODO: should close the connection when an exception is raised. + RecordLog.warn("[TokenClientHandler] Client exception caught", cause); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { - super.channelInactive(ctx); + RecordLog.info("[TokenClientHandler] Client handler inactive, remote address: " + ctx.channel().remoteAddress()); } @Override 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 new file mode 100644 index 00000000..5cc5b4f8 --- /dev/null +++ b/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/command/handler/ModifyClusterClientConfigHandler.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; + +/** + * @author Eric Zhao + * @since 1.4.0 + */ +@CommandMapping(name = "modifyClusterConfig") +public class ModifyClusterClientConfigHandler implements CommandHandler { + + @Override + public CommandResponse handle(CommandRequest request) { + + // TODO: parse the new config; + ClusterClientConfig clusterClientConfig = null; + ClusterClientConfigManager.applyNewConfig(clusterClientConfig); + + return CommandResponse.ofSuccess("ok"); + } +} + diff --git a/sentinel-cluster/sentinel-cluster-client-default/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.cluster.ClusterTokenClient b/sentinel-cluster/sentinel-cluster-client-default/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.cluster.ClusterTokenClient new file mode 100644 index 00000000..3070db6a --- /dev/null +++ b/sentinel-cluster/sentinel-cluster-client-default/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.cluster.ClusterTokenClient @@ -0,0 +1 @@ +com.alibaba.csp.sentinel.cluster.client.DefaultClusterTokenClient \ No newline at end of file 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 new file mode 100755 index 00000000..a0af73b5 --- /dev/null +++ b/sentinel-cluster/sentinel-cluster-client-default/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.command.CommandHandler @@ -0,0 +1 @@ +com.alibaba.csp.sentinel.command.handler.ModifyClusterClientConfigHandler \ No newline at end of file diff --git a/sentinel-cluster/sentinel-cluster-common-default/src/main/java/com/alibaba/csp/sentinel/cluster/ClusterTransportClient.java b/sentinel-cluster/sentinel-cluster-common-default/src/main/java/com/alibaba/csp/sentinel/cluster/ClusterTransportClient.java index 26af3c20..23ba9014 100644 --- a/sentinel-cluster/sentinel-cluster-common-default/src/main/java/com/alibaba/csp/sentinel/cluster/ClusterTransportClient.java +++ b/sentinel-cluster/sentinel-cluster-common-default/src/main/java/com/alibaba/csp/sentinel/cluster/ClusterTransportClient.java @@ -26,6 +26,20 @@ import com.alibaba.csp.sentinel.cluster.response.ClusterResponse; */ public interface ClusterTransportClient { + /** + * Start the client. + * + * @throws Exception some error occurred (e.g. initialization failed) + */ + void start() throws Exception; + + /** + * Stop the client. + * + * @throws Exception some error occurred (e.g. shutdown failed) + */ + void stop() throws Exception; + /** * Send request to remote server and get response. * @@ -34,4 +48,11 @@ public interface ClusterTransportClient { * @throws Exception some error occurs */ ClusterResponse sendRequest(ClusterRequest request) throws Exception; + + /** + * Check whether the client has been started and ready for sending requests. + * + * @return true if the client is ready to send requests, otherwise false + */ + boolean isReady(); } diff --git a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/cluster/ClusterTokenClient.java b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/cluster/ClusterTokenClient.java index 6a230c07..c0243974 100644 --- a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/cluster/ClusterTokenClient.java +++ b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/cluster/ClusterTokenClient.java @@ -26,7 +26,7 @@ public interface ClusterTokenClient extends TokenService { /** * Get descriptor of current token server. * - * @return current token server + * @return current token server if connected, otherwise null */ TokenServerDescriptor currentServer(); } \ No newline at end of file diff --git a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/cluster/TokenServerDescriptor.java b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/cluster/TokenServerDescriptor.java index 98739179..98636346 100644 --- a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/cluster/TokenServerDescriptor.java +++ b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/cluster/TokenServerDescriptor.java @@ -23,11 +23,10 @@ package com.alibaba.csp.sentinel.cluster; */ public class TokenServerDescriptor { - private String host; - private int port; - private String type; + private final String host; + private final int port; - public TokenServerDescriptor() {} + private String type = "default"; public TokenServerDescriptor(String host, int port) { this.host = host; @@ -38,20 +37,10 @@ public class TokenServerDescriptor { return host; } - public TokenServerDescriptor setHost(String host) { - this.host = host; - return this; - } - public int getPort() { return port; } - public TokenServerDescriptor setPort(int port) { - this.port = port; - return this; - } - public String getType() { return type; } diff --git a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/util/AssertUtil.java b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/util/AssertUtil.java index 46dcc11e..4c67b738 100644 --- a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/util/AssertUtil.java +++ b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/util/AssertUtil.java @@ -28,6 +28,12 @@ public class AssertUtil { } } + public static void assertNotBlank(String string, String message) { + if (StringUtil.isBlank(string)) { + throw new IllegalArgumentException(message); + } + } + public static void notNull(Object object, String message) { if (object == null) { throw new IllegalArgumentException(message);