From a15ef8eb3ac177fc0bd15d84301b301e9fa0c973 Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Sun, 28 Aug 2022 17:35:39 +0800 Subject: [PATCH 01/55] Add the base interface and entity for ability control. --- .../api/ability/constant/AbilityKey.java | 111 ++++++++++++++++++ .../api/ability/constant/AbilityStatus.java | 46 ++++++++ .../api/ability/entity/AbilityTable.java | 98 ++++++++++++++++ .../nacos/api/utils/AbilityTableUtils.java | 100 ++++++++++++++++ .../handler/AbilityHandlePreProcessor.java | 36 ++++++ .../ability/handler/HandlerMapping.java | 41 +++++++ .../ability/inter/AbilityControlManager.java | 95 +++++++++++++++ .../ability/inter/AbilityHandlerRegistry.java | 81 +++++++++++++ .../inter/TraceableAbilityControlManager.java | 44 +++++++ 9 files changed, 652 insertions(+) create mode 100644 api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java create mode 100644 api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityStatus.java create mode 100644 api/src/main/java/com/alibaba/nacos/api/ability/entity/AbilityTable.java create mode 100644 api/src/main/java/com/alibaba/nacos/api/utils/AbilityTableUtils.java create mode 100644 common/src/main/java/com/alibaba/nacos/common/ability/handler/AbilityHandlePreProcessor.java create mode 100644 common/src/main/java/com/alibaba/nacos/common/ability/handler/HandlerMapping.java create mode 100644 common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityControlManager.java create mode 100644 common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityHandlerRegistry.java create mode 100644 common/src/main/java/com/alibaba/nacos/common/ability/inter/TraceableAbilityControlManager.java diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java new file mode 100644 index 000000000..0971ca7af --- /dev/null +++ b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java @@ -0,0 +1,111 @@ +/* + * Copyright 1999-2022 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.nacos.api.ability.constant; + +import com.alibaba.nacos.api.utils.AbilityTableUtils; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/**. + * @author Daydreamer + * @description Ability table key. It can be a replacement of {@link com.alibaba.nacos.api.ability.ServerAbilities} + * and {@link com.alibaba.nacos.api.ability.ClientAbilities}. + * @date 2022/7/12 19:23 + **/ +@SuppressWarnings("unchecked") +public class AbilityKey { + + private static final HashMap CURRENT_SERVER_SUPPORT_ABILITY = new HashMap<>(); + + private static final HashMap CURRENT_SERVER_ABILITY_OFFSET = new HashMap<>(); + + private static final byte[] ABILITY_BIT_FLAGS; + + private AbilityKey() { + } + + static { + /* + * example: + * There is a function named "compression". + * The key is "compression", the value is the offset of the flag bit of this ability in the ability table. The value should be unique. + * + * You can add a new public static field like: + * public static final String COMPRESSION = "compression"; + * This field can be used outside. + * + * And then you need to declare the offset of the flag bit of this ability in the ability table, you can: + * CURRENT_NODE_ABILITY_TABLE.put("compression", 1); means that is the first bit from left to right in the table. + * + */ + + // put ability here, which you want current server supports + + } + + /**. + * Return ability table of current node + * But this ability is static which means that this ability table is all function this node supports if no one to ask it to close some functions. + * If you want to get what function current node is supporting, you should call AbilityControlManager#getCurrentAbility + * By the way, AbilityControlManager is singleton, you can get it by static method + * + * @return ability table + */ + public static Map getCurrentNodeSupportAbility() { + return Collections.unmodifiableMap(CURRENT_SERVER_SUPPORT_ABILITY); + } + + /**. + * Return the static ability bit table + * + * @return ability bit table + */ + public static byte[] getAbilityBitFlags() { + return ABILITY_BIT_FLAGS.clone(); + } + + /**. + * Is it a legal key + * + * @param key input + * @return whether a legal key + */ + public static boolean isLegal(String key) { + return CURRENT_SERVER_SUPPORT_ABILITY.containsKey(key); + } + + static { + // init the bits table + ABILITY_BIT_FLAGS = AbilityTableUtils.getAbilityBitBy(CURRENT_SERVER_ABILITY_OFFSET.values()); + // init the ability table, default all true + CURRENT_SERVER_ABILITY_OFFSET.forEach((k, v) -> { + CURRENT_SERVER_SUPPORT_ABILITY.put(k, Boolean.TRUE); + }); + } + + /**. + * Return the ability bit offsets + * + * @return bit offset + */ + public static Map offset() { + return CURRENT_SERVER_ABILITY_OFFSET; + } + +} diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityStatus.java b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityStatus.java new file mode 100644 index 000000000..825e99a0a --- /dev/null +++ b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityStatus.java @@ -0,0 +1,46 @@ +/* + * Copyright 1999-2022 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.nacos.api.ability.constant; + +/**. + * @author Daydreamer + * @description This enum is used to track the status of the ability table. + * @date 2022/7/13 14:11 + **/ +public enum AbilityStatus { + + /** + * It means that the ability table does not exist in the current node. + */ + NOT_EXIST, + + /** + * It means that current node has received the ability table and the table is initializing by AbilityPostProcessor. + */ + INITIALIZING, + + /** + * It means that the ability table is ready. + */ + READY, + + /** + * It means that the ability table will be removed soon. + */ + EXPIRED + +} diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/entity/AbilityTable.java b/api/src/main/java/com/alibaba/nacos/api/ability/entity/AbilityTable.java new file mode 100644 index 000000000..921a092a7 --- /dev/null +++ b/api/src/main/java/com/alibaba/nacos/api/ability/entity/AbilityTable.java @@ -0,0 +1,98 @@ +/* + * Copyright 1999-2022 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.nacos.api.ability.entity; + +import com.alibaba.nacos.api.ability.constant.AbilityKey; + +import java.util.Map; + +/**. + * @author Daydreamer + * @description This table is linked to a server node or client node. + * @date 2022/7/12 19:25 + **/ +public class AbilityTable implements Cloneable { + + /**. + * id in connection instance + */ + private String connectionId; + + /**. + * ability table + * key: name from {@link AbilityKey} + * value: whether to turn on + */ + private Map ability; + + /**. + * whether it from a server node + */ + private boolean isServer; + + /**. + * version of the client corresponding to the connection + */ + private String version; + + public AbilityTable() { + } + + public boolean isServer() { + return isServer; + } + + public AbilityTable setServer(boolean server) { + isServer = server; + return this; + } + + public String getVersion() { + return version; + } + + public AbilityTable setVersion(String version) { + this.version = version; + return this; + } + + public AbilityTable(String connectionId, Map ability, boolean isServer, String version) { + this.connectionId = connectionId; + this.ability = ability; + this.isServer = isServer; + this.version = version; + } + + public String getConnectionId() { + return connectionId; + } + + public AbilityTable setConnectionId(String connectionId) { + this.connectionId = connectionId; + return this; + } + + public Map getAbility() { + return ability; + } + + public AbilityTable setAbility(Map ability) { + this.ability = ability; + return this; + } + +} diff --git a/api/src/main/java/com/alibaba/nacos/api/utils/AbilityTableUtils.java b/api/src/main/java/com/alibaba/nacos/api/utils/AbilityTableUtils.java new file mode 100644 index 000000000..11ad28cc0 --- /dev/null +++ b/api/src/main/java/com/alibaba/nacos/api/utils/AbilityTableUtils.java @@ -0,0 +1,100 @@ +/* + * Copyright 1999-2022 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.nacos.api.utils; + +import com.alibaba.nacos.api.ability.constant.AbilityKey; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/**. + * @author Daydreamer + * @description It is used to operate ability table. + * @date 2022/7/12 19:23 + **/ +public class AbilityTableUtils { + + private static final int BASE = 128; + + private AbilityTableUtils() { + } + + /**. + * get ability bit table from Collection + * + * @param bitCollection bit offset + * @return bit table + */ + public static byte[] getAbilityBitBy(Collection bitCollection) { + if (bitCollection.size() == 0) { + return new byte[1]; + } + Integer max = Collections.max(bitCollection); + // calculate byte[] + int mark = max % 8; + int length = max / 8 + (mark == 0 ? 0 : 1); + byte[] res = new byte[length]; + bitCollection.forEach(offset -> { + int index = offset / 8 + (offset % 8 == 0 ? -1 : 0); + int flag = offset % 8; + if (flag == 0) { + flag = 8; + } + byte x = (byte) (BASE >>> (flag - 1)); + res[index] = (byte) (res[index] | x); + }); + return res; + } + + /**. + * get ability table by bits + * + * @param bits bit flag + * @param offsetMap offset from {@link AbilityKey} + * @return Return the Map containing AbilityTableKey and isRunning. + */ + public static Map getAbilityTableBy(byte[] bits, Map offsetMap) { + if (bits == null || offsetMap.size() == 0) { + return Collections.emptyMap(); + } + int length = bits.length; + Set> entries = offsetMap.entrySet(); + Map res = new HashMap<>(offsetMap.size()); + for (Map.Entry entry : entries) { + String abilityKey = entry.getKey(); + Integer offset = entry.getValue(); + // if not exists + int index = offset / 8 + (offset % 8 == 0 ? -1 : 0); + if (index + 1 > length) { + res.put(abilityKey, Boolean.FALSE); + continue; + } + // find + int flag = offset % 8; + if (flag == 0) { + flag = 8; + } + byte x = (byte) (BASE >>> (flag - 1)); + byte tmp = (byte) (x & bits[index]); + res.put(abilityKey, x == tmp); + } + return res; + } +} diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/handler/AbilityHandlePreProcessor.java b/common/src/main/java/com/alibaba/nacos/common/ability/handler/AbilityHandlePreProcessor.java new file mode 100644 index 000000000..252f81123 --- /dev/null +++ b/common/src/main/java/com/alibaba/nacos/common/ability/handler/AbilityHandlePreProcessor.java @@ -0,0 +1,36 @@ +/* + * Copyright 1999-2022 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.nacos.common.ability.handler; + +import com.alibaba.nacos.api.ability.entity.AbilityTable; + +/**. + * @author Daydreamer + * @description This handler will should be invoked before ability table joining current node. + * @date 2022/7/12 19:24 + **/ +public interface AbilityHandlePreProcessor { + + /** + * Handling before joining current node. + * + * @param source source ability handler + * @return result table + */ + AbilityTable handle(AbilityTable source); + +} diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/handler/HandlerMapping.java b/common/src/main/java/com/alibaba/nacos/common/ability/handler/HandlerMapping.java new file mode 100644 index 000000000..e7623d5e0 --- /dev/null +++ b/common/src/main/java/com/alibaba/nacos/common/ability/handler/HandlerMapping.java @@ -0,0 +1,41 @@ +/* + * Copyright 1999-2022 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.nacos.common.ability.handler; + +/**. + * @author Daydreamer + * @description This component will be invoked if the ability of current node is turned on/off. + * @date 2022/7/12 19:21 + **/ +public interface HandlerMapping { + + /**. + * It will be invoked in order to enable this component after update the + * ability table key to true + */ + default void enable() { + // Nothing to do! + } + + /**. + * It will be invoked in order to disable this component after update the + * ability table key to false + */ + default void disable() { + // Nothing to do! + } +} diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityControlManager.java new file mode 100644 index 000000000..15adf7fc9 --- /dev/null +++ b/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityControlManager.java @@ -0,0 +1,95 @@ +/* + * Copyright 1999-2022 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.nacos.common.ability.inter; + +import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.entity.AbilityTable; +import com.alibaba.nacos.common.ability.handler.AbilityHandlePreProcessor; + +import java.util.Map; + +/**. + * @author Daydreamer + * @description This is a base interface to manage ability table + * @date 2022/8/10 23:18 + **/ +public interface AbilityControlManager { + + /** + * Whether the ability is supported for Connection. If the ability of current node is closed, it will return false. + * + * @param connectionId the connection range of ability table. + * @param abilityKey key name which comes from {@link AbilityKey}. + * @return whether the ability is supported in certain connection. + */ + boolean isSupport(String connectionId, String abilityKey); + + /** + * Whether the ability current node supporting is running. Return false if current node doesn't support. + * + * @param abilityKey ability key + * @return is running + */ + boolean isCurrentNodeAbilityRunning(String abilityKey); + + /** + * Register a new ability table. + * + * @param table the ability table. + */ + void addNewTable(AbilityTable table); + + /**. + * Remove a ability table + * + * @param connectionId the ability table which is removing. + */ + void removeTable(String connectionId); + + /**. + * whether contains this ability table + * + * @param connectionId connection id + * @return whether contains + */ + boolean contains(String connectionId); + + /**. + * Return ability table of current node + * + * @return ability table + */ + Map getCurrentRunningAbility(); + + /**. + * They will be invoked before updating ability table, but the order in which + * they are called cannot be guaranteed + * + * @param postProcessor PostProcessor instance + */ + void addPostProcessor(AbilityHandlePreProcessor postProcessor); + + /**. + * Initialize the manager + */ + void init(); + + /**. + * It should be invoked before destroy + */ + void destroy(); +} diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityHandlerRegistry.java b/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityHandlerRegistry.java new file mode 100644 index 000000000..c27254784 --- /dev/null +++ b/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityHandlerRegistry.java @@ -0,0 +1,81 @@ +/* + * Copyright 1999-2022 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.nacos.common.ability.inter; + +import com.alibaba.nacos.common.ability.AbstractAbilityControlManager; +import com.alibaba.nacos.common.ability.handler.HandlerMapping; + +/**. + * @author Daydreamer + * @description It provides the capability to notify components which interested in one ability for the {@link AbilityControlManager} + * @date 2022/8/10 23:43 + **/ +public interface AbilityHandlerRegistry { + + /**. + * Turn on the ability whose key is

abilityKey

+ * + * @param abilityKey ability key + * @return if turn success + */ + boolean enableCurrentNodeAbility(String abilityKey); + + /**. + * Turn off the ability whose key is

abilityKey

+ * + * @param abilityKey ability key + * @return if turn success + */ + boolean disableCurrentNodeAbility(String abilityKey); + + /**. + * Register the component which is managed by {@link AbstractAbilityControlManager}. + * if you are hoping that a component will be invoked when turn on/off the ability whose key is

abilityKey

. + * + * @param abilityKey component key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey} + * @param priority a positive number, the higher the priority is, the faster it will be called. `1` is the lowest priority. + * @param handlerMapping component instance. + */ + void registerComponent(String abilityKey, HandlerMapping handlerMapping, int priority); + + /**. + * Default method to register component with the lowest priority. + * + * @param abilityKey component key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey} + * @param handlerMapping component instance. + */ + default void registerComponent(String abilityKey, HandlerMapping handlerMapping) { + registerComponent(abilityKey, handlerMapping, 1); + } + + /** + * Remove the component instance of

handlerMappingClazz

. + * + * @param abilityKey ability key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey} + * @param handlerMappingClazz implement of {@link HandlerMapping} + * @return the count of components have removed + */ + int removeComponent(String abilityKey, Class handlerMappingClazz); + + /** + * Remove all {@link HandlerMapping} interested in the special ability. + * @param abilityKey abnility key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey} + * @return the count of components have removed + */ + int removeAll(String abilityKey); + +} diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/inter/TraceableAbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/inter/TraceableAbilityControlManager.java new file mode 100644 index 000000000..6b87b9b38 --- /dev/null +++ b/common/src/main/java/com/alibaba/nacos/common/ability/inter/TraceableAbilityControlManager.java @@ -0,0 +1,44 @@ +/* + * Copyright 1999-2022 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.nacos.common.ability.inter; + +import com.alibaba.nacos.api.ability.constant.AbilityStatus; + +/**. + * @author Daydreamer + * @description It provides the capability to trace the state of AbilityTable for the {@link AbilityControlManager} + * @date 2022/8/10 23:30 + **/ +public interface TraceableAbilityControlManager extends AbilityControlManager { + + /** + * Get the status of the ability table. + * + * @param connectionId connection id + * @return status of ability table {@link AbilityStatus} + */ + AbilityStatus trace(String connectionId); + + /**. + * Trace the status of connection if {@link AbilityStatus#INITIALIZING}, wake up if {@link AbilityStatus#READY} + * It will return if status is {@link AbilityStatus#EXPIRED} or {@link AbilityStatus#NOT_EXIST} + * + * @param connectionId connection id + * @return if success to {@link AbilityStatus#READY} + */ + boolean traceReadySyn(String connectionId); +} From 4098297e51832b00ac839fe28e199f296a48868b Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Sun, 28 Aug 2022 17:38:08 +0800 Subject: [PATCH 02/55] Add the base implements for ability control. --- .../AbstractAbilityControlManager.java | 401 ++++++++++++++++++ .../ability/DefaultAbilityControlManager.java | 343 +++++++++++++++ .../ability/discover/AbilityHandleLoader.java | 49 +++ .../discover/NacosAbilityManagerHolder.java | 92 ++++ 4 files changed, 885 insertions(+) create mode 100644 common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java create mode 100644 common/src/main/java/com/alibaba/nacos/common/ability/DefaultAbilityControlManager.java create mode 100644 common/src/main/java/com/alibaba/nacos/common/ability/discover/AbilityHandleLoader.java create mode 100644 common/src/main/java/com/alibaba/nacos/common/ability/discover/NacosAbilityManagerHolder.java diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java new file mode 100644 index 000000000..f78fd0a20 --- /dev/null +++ b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java @@ -0,0 +1,401 @@ +/* + * Copyright 1999-2022 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.nacos.common.ability; + +import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.constant.AbilityStatus; +import com.alibaba.nacos.api.ability.entity.AbilityTable; +import com.alibaba.nacos.common.ability.handler.AbilityHandlePreProcessor; +import com.alibaba.nacos.common.ability.inter.TraceableAbilityControlManager; +import com.alibaba.nacos.common.notify.Event; +import com.alibaba.nacos.common.notify.NotifyCenter; +import com.alibaba.nacos.common.utils.CollectionUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.locks.LockSupport; +import java.util.concurrent.locks.ReentrantLock; + +/**. + * @author Daydreamer + * @description Base class for ability control. It can only be used internally by Nacos.It showld be sington. + * @date 2022/7/12 19:18 + **/ +@SuppressWarnings("all") +public abstract class AbstractAbilityControlManager implements TraceableAbilityControlManager { + + + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractAbilityControlManager.class); + + /** + * Abilities current supporting + *

+ * key: ability key from {@link AbilityKey} + * value: whether to turn on + */ + protected final Map currentRunningAbility = new ConcurrentHashMap<>(); + + /** + * Ability table collections + *

+ * key: connectionId + * value: AbilityTable + */ + protected final Map nodeAbilityTable = new ConcurrentHashMap<>(); + + /**. + * These handlers will be invoke before combine the ability table + */ + private final List abilityHandlePreProcessors = new ArrayList<>(); + + /** + * This map is used to trace the status of ability table. + * Its status should be update after {@link #addNewTable(AbilityTable)} and {@link #removeTable(String)} + */ + protected final Map> abilityStatus = new ConcurrentHashMap<>(); + + private final ReentrantLock lockForProcessors = new ReentrantLock(); + + private final ReentrantLock lockForAbilityTable = new ReentrantLock(); + + protected AbstractAbilityControlManager() { + // register events + registerAbilityEvent(); + // put abilities + currentRunningAbility.putAll(AbilityKey.getCurrentNodeSupportAbility()); + // initialize + init(); + } + + + private void registerAbilityEvent(){ + // register events + NotifyCenter.registerToPublisher(AbilityComeEvent.class, 16384); + NotifyCenter.registerToPublisher(AbilityExpiredEvent.class, 16384); + } + + /** + * Whether the ability current node supporting is running. Return false if current node doesn't support. + * + * @param abilityKey ability key + * @return is running + */ + @Override + public boolean isCurrentNodeAbilityRunning(String abilityKey) { + return currentRunningAbility.getOrDefault(abilityKey, false); + } + + /** + * Register a new ability table. + * + * @param table the ability table. + */ + @Override + public final void addNewTable(AbilityTable table) { + // id should not be null + String connectionId = table.getConnectionId(); + // if exists + if (contains(connectionId) || connectionId == null) { + return; + } + lockForAbilityTable.lock(); + try { + // check + if (contains(connectionId)) { + return; + } + // update status + abilityStatus.put(connectionId, new AtomicReference<>(AbilityStatus.INITIALIZING)); + // handle ability table before joining current node + AbilityTable processed = process(table); + // hook method + add(processed); + // add to node + nodeAbilityTable.put(connectionId, table); + } finally { + lockForAbilityTable.unlock(); + } + // update status + AtomicReference abilityStatusAtomicReference = abilityStatus.get(table.getConnectionId()); + if (abilityStatusAtomicReference != null) { + // try one time + // do nothing if AbilityStatus == Expired + // if ready + if(abilityStatusAtomicReference.compareAndSet(AbilityStatus.INITIALIZING, AbilityStatus.READY)) { + // publish event to subscriber + AbilityComeEvent updateEvent = new AbilityComeEvent(); + updateEvent.setConnectionId(table.getConnectionId()); + updateEvent.setTable(table); + NotifyCenter.publishEvent(updateEvent); + } + } else { + LOGGER.warn("[AbiityControlManager] Cannot get connection status after processing ability table, possible reason is that the network is unstable"); + } + } + + /** + * Remove a ability table + * + * @param connectionId the ability table which is removing. + */ + @Override + public final void removeTable(String connectionId) { + // if not exists + if(connectionId == null || !nodeAbilityTable.containsKey(connectionId)){ + return; + } + AbilityTable removingTable = null; + lockForAbilityTable.lock(); + try { + // check + if (!nodeAbilityTable.containsKey(connectionId)) { + return; + } + nodeAbilityTable.get(connectionId); + // update status + abilityStatus.computeIfPresent(connectionId, (k, v) -> { + v.set(AbilityStatus.EXPIRED); + return v; + }); + // hook method + remove(connectionId); + // remove + nodeAbilityTable.remove(connectionId); + } finally { + lockForAbilityTable.unlock(); + } + // remove status + abilityStatus.remove(connectionId); + // publish event + if (removingTable != null) { + AbilityExpiredEvent expiredEvent = new AbilityExpiredEvent(); + expiredEvent.setTable(removingTable); + expiredEvent.setConnectionId(connectionId); + NotifyCenter.publishEvent(expiredEvent); + } + } + + + /** + * Register a new ability table. This is a ThreadSafe method for {@link AbstractAbilityControlManager#remove(String)}. + * + * @param table the ability table. + */ + protected abstract void add(AbilityTable table); + + + /** + * Remove a ability table. This is a ThreadSafe method for {@link AbstractAbilityControlManager#add(AbilityTable)}. + * + * @param connectionId the ability table which is removing. + */ + protected abstract void remove(String connectionId); + + + /** + * wthether contains this ability table + * + * @return + */ + @Override + public boolean contains(String connectionId) { + return nodeAbilityTable.containsKey(connectionId); + } + + + /** + * Get the status of the ability table. + * + * @param connectionId connection id + * @return status of ability table {@link AbilityStatus} + */ + @Override + public AbilityStatus trace(String connectionId) { + if (connectionId == null) { + return AbilityStatus.NOT_EXIST; + } + return abilityStatus.getOrDefault(connectionId, new AtomicReference<>(AbilityStatus.NOT_EXIST)).get(); + } + + /** + * Trace the status of connection if

{@link AbilityStatus#INITIALIZING}

, wake up if

{@link AbilityStatus#READY}

+ * It will return if status is

{@link AbilityStatus#EXPIRED}

or

{@link AbilityStatus#NOT_EXIST}

+ * + * @param connectionId connection id + * @param source source status + * @param target target status + * @return if success + */ + @Override + public boolean traceReadySyn(String connectionId) { + AbilityStatus source = AbilityStatus.INITIALIZING; + AbilityStatus target = AbilityStatus.READY; + AtomicReference atomicReference = abilityStatus.get(connectionId); + // return if null + if (atomicReference == null || atomicReference.get().equals(AbilityStatus.EXPIRED)) { + return false; + } else if (target == atomicReference.get()) { + return true; + } + // try if status legal + while (!atomicReference.get().equals(target) && atomicReference.get().equals(source)) { + LockSupport.parkNanos(100L); + // if expired + if (atomicReference.get().equals(AbilityStatus.EXPIRED)) { + return false; + } + } + return atomicReference.get().equals(target); + } + + /**. + * Invoking {@link AbilityHandlePreProcessor} + * + * @param source source ability table + * @return result + */ + protected AbilityTable process(AbilityTable source) { + // do nothing if no processor + if (CollectionUtils.isEmpty(abilityHandlePreProcessors)) { + return source; + } + // copy to advoid error process + AbilityTable abilityTable = source; + AbilityTable copy = new AbilityTable(source.getConnectionId(), new HashMap<>(source.getAbility()), source.isServer(), source.getVersion()); + for (AbilityHandlePreProcessor handler : abilityHandlePreProcessors) { + try { + abilityTable = handler.handle(abilityTable); + } catch (Throwable t) { + LOGGER.warn("[AbilityHandlePostProcessor] Failed to invoke {} :{}", + handler.getClass().getSimpleName(), t.getLocalizedMessage()); + // ensure normal operation + abilityTable = copy; + } + } + return abilityTable; + } + + /**. + * They will be invoked before updating ability table, but the order in which + * they are called cannot be guaranteed + * + * @param postProcessor PostProcessor instance + */ + @Override + public void addPostProcessor(AbilityHandlePreProcessor postProcessor) { + lockForProcessors.lock(); + try { + abilityHandlePreProcessors.add(postProcessor); + } finally { + lockForProcessors.unlock(); + LOGGER.info("[AbilityHandlePostProcessor] registry handler: {}", + postProcessor.getClass().getSimpleName()); + } + } + + /** + * Initialize the manager + */ + @Override + public void init() { + // default init + // nothing to do + } + + /** + * It should be invoked before destroy + */ + @Override + public void destroy() { + // default destroy + // nothing to do + } + + /** + * Return ability table of current node + * + * @return ability table + */ + @Override + public Map getCurrentRunningAbility() { + return new HashMap<>(this.currentRunningAbility); + } + + /** + * base class for ability + */ + public abstract class AbilityEvent extends Event { + + private static final long serialVersionUID = -123241121302761L; + + protected AbilityEvent(){} + + /** + * connection id. + */ + private String connectionId; + + /** + * ability table + */ + private AbilityTable table; + + + public String getConnectionId() { + return connectionId; + } + + public void setConnectionId(String connectionId) { + this.connectionId = connectionId; + } + + public AbilityTable getTable() { + return table; + } + + public void setTable(AbilityTable table) { + this.table = table; + } + } + + /** + * when a connection connected. + */ + public class AbilityComeEvent extends AbilityEvent { + + private static final long serialVersionUID = -123241121302761L; + + private AbilityComeEvent(){} + } + + /** + * when a connection disconnected. + */ + public class AbilityExpiredEvent extends AbilityEvent { + + private static final long serialVersionUID = -123241121212127619L; + + private AbilityExpiredEvent(){} + + } +} diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/DefaultAbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/DefaultAbilityControlManager.java new file mode 100644 index 000000000..b3012392e --- /dev/null +++ b/common/src/main/java/com/alibaba/nacos/common/ability/DefaultAbilityControlManager.java @@ -0,0 +1,343 @@ +/* + * Copyright 1999-2022 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.nacos.common.ability; + +import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.entity.AbilityTable; +import com.alibaba.nacos.common.JustForTest; +import com.alibaba.nacos.common.ability.handler.HandlerMapping; +import com.alibaba.nacos.common.ability.inter.AbilityHandlerRegistry; +import com.alibaba.nacos.common.executor.ExecutorFactory; +import com.alibaba.nacos.common.notify.NotifyCenter; +import com.alibaba.nacos.common.utils.CollectionUtils; +import com.alibaba.nacos.common.utils.MapUtil; +import com.alibaba.nacos.common.utils.ThreadUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.Executor; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/**. + * @author Daydreamer + * @description It is a relatively complete capability control center implementation. + * @date 2022/7/12 19:18 + **/ +public abstract class DefaultAbilityControlManager extends AbstractAbilityControlManager + implements AbilityHandlerRegistry { + + private static final Logger LOGGER = LoggerFactory.getLogger(DefaultAbilityControlManager.class); + + /** + * . These handlers will be invoked when the flag of ability change key: ability key from {@link AbilityKey} value: + * componments who want to be invoked if its interested ability turn on/off + */ + private final Map> handlerMappings = new ConcurrentHashMap<>(); + + /**. + * run for HandlerMapping + */ + private final Executor simpleThreadPool = ExecutorFactory.newSingleExecutorService(); + + private final ReentrantLock lockForHandlerMappings = new ReentrantLock(); + + protected DefaultAbilityControlManager() { + ThreadUtils.addShutdownHook(this::destroy); + NotifyCenter.registerToPublisher(AbilityUpdateEvent.class, 16384); + } + + /** + * . Turn on the ability whose key is

abilityKey

+ * + * @param abilityKey ability key + * @return if turn success + */ + @Override + public boolean enableCurrentNodeAbility(String abilityKey) { + return doTurn(true, abilityKey); + } + + /** + * . Turn off the ability whose key is

abilityKey

+ * + * @param abilityKey ability key + * @return if turn success + */ + @Override + public boolean disableCurrentNodeAbility(String abilityKey) { + return doTurn(false, abilityKey); + } + + /** + * . Turn on/off the ability of current node + * + * @param isOn is on + * @param abilityKey ability key from {@link AbilityKey} + * @return if turn success + */ + private boolean doTurn(boolean isOn, String abilityKey) { + Boolean isEnabled = currentRunningAbility.get(abilityKey); + // if not supporting this key + if (isEnabled == null) { + LOGGER.warn("[AbilityControlManager] Attempt to turn on/off a not existed ability!"); + return false; + } else if (isOn == isEnabled) { + // if already turn on/off + return true; + } + // turn on/off + currentRunningAbility.put(abilityKey, isOn); + // handler mappings + triggerHandlerMappingAsyn(abilityKey, isOn, this.handlerMappings); + // notify event + AbilityUpdateEvent abilityUpdateEvent = new AbilityUpdateEvent(); + abilityUpdateEvent.setTable(new AbilityTable().setAbility(Collections.unmodifiableMap(currentRunningAbility))); + abilityUpdateEvent.isOn = isOn; + abilityUpdateEvent.abilityKey = abilityKey; + NotifyCenter.publishEvent(abilityUpdateEvent); + return true; + } + + /** + * Register the component which is managed by {@link AbstractAbilityControlManager}. if you are hoping that a + * component will be invoked when turn on/off the ability whose key is

abilityKey

. + * + * @param abilityKey component key. + * @param priority the higher the priority is, the faster it will be called. + * @param handlerMapping component instance. + */ + @Override + public void registerComponent(String abilityKey, HandlerMapping handlerMapping, int priority) { + doRegisterComponent(abilityKey, handlerMapping, this.handlerMappings, lockForHandlerMappings, priority, currentRunningAbility); + } + + @Override + public int removeComponent(String abilityKey, Class handlerMappingClazz) { + return doRemove(abilityKey, handlerMappingClazz, lockForHandlerMappings, handlerMappings); + } + + @Override + public final void destroy() { + LOGGER.warn("[DefaultAbilityControlManager] - Start destroying..."); + ((ThreadPoolExecutor) simpleThreadPool).shutdown(); + if (MapUtil.isNotEmpty(handlerMappings)) { + handlerMappings.keySet().forEach(key -> doTriggerSyn(key, false, handlerMappings)); + } + // hook + doDestroy(); + LOGGER.warn("[DefaultAbilityControlManager] - Destruction of the end"); + } + + /**. + * hook for subclass + */ + protected void doDestroy() { + // for server ability manager + } + + /** + * Remove the component instance of

handlerMappingClazz

. + * + * @param abilityKey ability key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey} + * @param handlerMappingClazz implement of {@link HandlerMapping} + * @param lock lock for operation + * @param handlerMappingsMap handler collection map + * @return the count of components have removed + */ + protected int doRemove(String abilityKey, Class handlerMappingClazz, Lock lock, + Map> handlerMappingsMap) { + List handlerMappings = handlerMappingsMap.get(abilityKey); + if (CollectionUtils.isEmpty(handlerMappings)) { + return 0; + } + lock.lock(); + try { + AtomicInteger count = new AtomicInteger(); + handlerMappings.removeIf(item -> { + if (item.handlerMapping.getClass().equals(handlerMappingClazz)) { + count.getAndIncrement(); + return true; + } + return false; + }); + return count.get(); + } finally { + lock.unlock(); + } + } + + @Override + public int removeAll(String abilityKey) { + List remove = this.handlerMappings.remove(abilityKey); + return Optional.ofNullable(remove).orElse(Collections.emptyList()).size(); + } + + /**. + * Register the component into handlerMappings locking by lockForHandlerMappings to ensure concurrency security. + * + * @param abilityKey ability key + * @param handlerMapping component instance. + * @param handlerMappings container + * @param lockForHandlerMappings lock to ensure concurrency + * @param abilityTable behavioral basis of handler + */ + protected void doRegisterComponent(String abilityKey, HandlerMapping handlerMapping, + Map> handlerMappings, Lock lockForHandlerMappings, + int priority, Map abilityTable) { + if (!currentRunningAbility.containsKey(abilityKey)) { + LOGGER.warn("[AbilityHandlePostProcessor] Failed to register processor: {}, because illegal key!", + handlerMapping.getClass().getSimpleName()); + } + + // legal key + lockForHandlerMappings.lock(); + try { + List handlers = handlerMappings.getOrDefault(abilityKey, new CopyOnWriteArrayList<>()); + HandlerWithPriority handlerWithPriority = new HandlerWithPriority(handlerMapping, priority); + handlers.add(handlerWithPriority); + handlerMappings.put(abilityKey, handlers); + // choose behavior + // enable default + if (abilityTable.getOrDefault(abilityKey, false)) { + handlerMapping.enable(); + } else { + handlerMapping.disable(); + } + } catch (Exception e) { + e.printStackTrace(); + LOGGER.error("[DefaultAbilityControlManager] Fail to register handler: {}", handlerMapping.getClass().getSimpleName()); + } finally { + lockForHandlerMappings.unlock(); + LOGGER.info("[DefaultAbilityControlManager] Successfully registered processor: {}", + handlerMapping.getClass().getSimpleName()); + } + } + + /** + * Invoke componments which linked to ability key asyn. + * + * @param key ability key from {@link AbilityKey} + * @param isEnabled turn on/off + * @param handlerMappingsMap handler collection + */ + protected void triggerHandlerMappingAsyn(String key, boolean isEnabled, + Map> handlerMappingsMap) { + simpleThreadPool.execute(() -> doTriggerSyn(key, isEnabled, handlerMappingsMap)); + } + + /** + * Invoke componments which linked to ability key syn. + * + * @param key ability key from {@link AbilityKey} + * @param isEnabled turn on/off + * @param handlerMappingsMap handler collection + */ + protected void doTriggerSyn(String key, boolean isEnabled, + Map> handlerMappingsMap) { + List handlerWithPriorities = handlerMappingsMap.get(key); + // return if empty + if (CollectionUtils.isEmpty(handlerWithPriorities)) { + return; + } + Collections.sort(handlerWithPriorities); + // invoked all + handlerWithPriorities.forEach(handlerMappingWithPriorities -> { + // any error from current handler does not affect other handler + HandlerMapping handlerMapping = handlerMappingWithPriorities.handlerMapping; + try { + if (isEnabled) { + handlerMapping.enable(); + } else { + handlerMapping.disable(); + } + } catch (Throwable t) { + LOGGER.warn("[HandlerMapping] Failed to invoke {} :{}", handlerMapping.getClass().getSimpleName(), + t.getLocalizedMessage()); + } + }); + } + + @JustForTest + protected Map> handlerMapping() { + return this.handlerMappings; + } + + /** + * Support priority handler. + */ + protected class HandlerWithPriority implements Comparable { + + /**. + * Decorated + */ + public HandlerMapping handlerMapping; + + /**. + * the higher the priority, the faster it will be called + */ + public int priority; + + public HandlerWithPriority(HandlerMapping handlerMapping, int priority) { + this.handlerMapping = handlerMapping; + this.priority = priority; + } + + @Override + public int compareTo(HandlerWithPriority o) { + return o.priority - this.priority; + } + } + + /**. + * notify when current node ability changing + */ + public class AbilityUpdateEvent extends AbilityEvent { + + private static final long serialVersionUID = -1232411212311111L; + + private String abilityKey; + + private boolean isOn; + + private AbilityUpdateEvent(){} + + public String getAbilityKey() { + return abilityKey; + } + + public void setAbilityKey(String abilityKey) { + this.abilityKey = abilityKey; + } + + public boolean isOn() { + return isOn; + } + + public void setOn(boolean on) { + isOn = on; + } + } +} diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/discover/AbilityHandleLoader.java b/common/src/main/java/com/alibaba/nacos/common/ability/discover/AbilityHandleLoader.java new file mode 100644 index 000000000..feb07436a --- /dev/null +++ b/common/src/main/java/com/alibaba/nacos/common/ability/discover/AbilityHandleLoader.java @@ -0,0 +1,49 @@ +/* + * Copyright 1999-2022 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.nacos.common.ability.discover; + +import com.alibaba.nacos.common.ability.handler.AbilityHandlePreProcessor; +import com.alibaba.nacos.common.spi.NacosServiceLoader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collection; +import java.util.HashSet; + +/**. + * @author Daydreamer + * @description It is spi loader to load {@link AbilityHandlePreProcessor} + * @date 2022/8/25 18:24 + **/ +public class AbilityHandleLoader { + + private final Collection initializers; + + private static final Logger LOGGER = LoggerFactory.getLogger(AbilityHandleLoader.class); + + public AbilityHandleLoader() { + initializers = new HashSet<>(); + for (AbilityHandlePreProcessor preProcessor : NacosServiceLoader.load(AbilityHandlePreProcessor.class)) { + initializers.add(preProcessor); + LOGGER.info("Load {} for AbilityHandlePreProcessor", preProcessor.getClass().getCanonicalName()); + } + } + + public Collection getInitializers() { + return initializers; + } +} diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/discover/NacosAbilityManagerHolder.java b/common/src/main/java/com/alibaba/nacos/common/ability/discover/NacosAbilityManagerHolder.java new file mode 100644 index 000000000..fe7a0c760 --- /dev/null +++ b/common/src/main/java/com/alibaba/nacos/common/ability/discover/NacosAbilityManagerHolder.java @@ -0,0 +1,92 @@ +/* + * Copyright 1999-2022 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.nacos.common.ability.discover; + +import com.alibaba.nacos.common.ability.AbstractAbilityControlManager; +import com.alibaba.nacos.common.ability.DefaultAbilityControlManager; +import com.alibaba.nacos.common.ability.inter.AbilityControlManager; +import com.alibaba.nacos.common.spi.NacosServiceLoader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collection; +import java.util.ServiceConfigurationError; + +/** + * This class is used to discover {@link AbstractAbilityControlManager} implements. All the + * ability operation will be finish in this singleton. + * + * @author Daydreamer + * @date 2022/7/14 19:58 + **/ +public class NacosAbilityManagerHolder { + + /**. + * private constructor + */ + private NacosAbilityManagerHolder() { + } + + private static final Logger LOGGER = LoggerFactory.getLogger(NacosAbilityManagerHolder.class); + + /**. + * singleton + */ + private static DefaultAbilityControlManager abstractAbilityControlManager; + + static { + // spi discover implement + Collection load = null; + try { + // if server + load = NacosServiceLoader.load(DefaultAbilityControlManager.class); + } catch (ServiceConfigurationError e) { + // if client or not ability control manager + load = NacosServiceLoader.load(DefaultAbilityControlManager.class); + } + // the priority of the server is higher + if (load.size() > 0) { + load.forEach(clazz -> { + abstractAbilityControlManager = clazz; + }); + LOGGER.info("[AbilityControlManager] Successfully initialize AbilityControlManager"); + // init pre processor + AbilityHandleLoader loader = new AbilityHandleLoader(); + loader.getInitializers().forEach(processor -> abstractAbilityControlManager.addPostProcessor(processor)); + } + } + + /**. + * get nacos ability control manager + * + * @return BaseAbilityControlManager + */ + public static DefaultAbilityControlManager getInstance() { + return abstractAbilityControlManager; + } + + /**. + * Return the target type of ability manager + * + * @param clazz clazz + * @param target type + * @return AbilityControlManager + */ + public static T getInstance(Class clazz) { + return clazz.cast(abstractAbilityControlManager); + } +} From 427535897594f6b0effa04f2216a4cac430c5375 Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Sun, 28 Aug 2022 17:40:08 +0800 Subject: [PATCH 03/55] Add the default implements for client and server. --- .../ability/ClientAbilityControlManager.java | 72 +++++ ...ommon.ability.DefaultAbilityControlManager | 19 ++ .../control/ServerAbilityControlManager.java | 268 ++++++++++++++++++ .../inte/ClusterAbilityControlSupport.java | 80 ++++++ 4 files changed, 439 insertions(+) create mode 100644 client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java create mode 100644 common/src/main/resources/META-INF/services/com.alibaba.nacos.common.ability.DefaultAbilityControlManager create mode 100644 core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java create mode 100644 core/src/main/java/com/alibaba/nacos/core/ability/inte/ClusterAbilityControlSupport.java diff --git a/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java b/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java new file mode 100644 index 000000000..0f3a6fcbe --- /dev/null +++ b/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java @@ -0,0 +1,72 @@ +/* + * Copyright 1999-2022 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.nacos.client.ability; + +import com.alibaba.nacos.api.ability.constant.AbilityStatus; +import com.alibaba.nacos.api.ability.entity.AbilityTable; +import com.alibaba.nacos.common.ability.AbstractAbilityControlManager; +import com.alibaba.nacos.common.ability.DefaultAbilityControlManager; + +import java.util.Collections; +import java.util.Optional; + +/**. + * @author Daydreamer + * @description {@link AbstractAbilityControlManager} for nacos-client. + * @date 2022/7/13 13:38 + **/ +public class ClientAbilityControlManager extends DefaultAbilityControlManager { + + public ClientAbilityControlManager() { + } + + @Override + public boolean isSupport(String connectionId, String abilityKey) { + Boolean isRunning = currentRunningAbility.getOrDefault(abilityKey, false); + if (!isRunning) { + return false; + } + AbilityTable abilityTable = nodeAbilityTable.get(connectionId); + // it is null, check if initialing + if (abilityTable == null && AbilityStatus.INITIALIZING.equals(trace(connectionId))) { + // wait for ready + boolean finish = traceReadySyn(connectionId); + // if expired + if (!finish) { + return false; + } else { + abilityTable = nodeAbilityTable.get(connectionId); + } + } + // false if null + return abilityTable != null + && Optional.ofNullable(abilityTable.getAbility()) + .orElse(Collections.emptyMap()) + .getOrDefault(abilityKey, false); + } + + @Override + protected void add(AbilityTable table) { + // nothing to do + } + + @Override + protected void remove(String connectionId) { + // nothing to do + } + +} diff --git a/common/src/main/resources/META-INF/services/com.alibaba.nacos.common.ability.DefaultAbilityControlManager b/common/src/main/resources/META-INF/services/com.alibaba.nacos.common.ability.DefaultAbilityControlManager new file mode 100644 index 000000000..c5e3caeac --- /dev/null +++ b/common/src/main/resources/META-INF/services/com.alibaba.nacos.common.ability.DefaultAbilityControlManager @@ -0,0 +1,19 @@ +# +# Copyright 1999-2022 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. +# +# + +com.alibaba.nacos.client.ability.ClientAbilityControlManager +com.alibaba.nacos.core.ability.control.ServerAbilityControlManager \ No newline at end of file diff --git a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java new file mode 100644 index 000000000..09faa79a4 --- /dev/null +++ b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java @@ -0,0 +1,268 @@ +/* + * Copyright 1999-2022 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.nacos.core.ability.control; + +import com.alibaba.nacos.api.ability.constant.AbilityStatus; +import com.alibaba.nacos.api.ability.entity.AbilityTable; +import com.alibaba.nacos.common.JustForTest; +import com.alibaba.nacos.common.ability.AbstractAbilityControlManager; +import com.alibaba.nacos.common.ability.DefaultAbilityControlManager; +import com.alibaba.nacos.common.ability.handler.HandlerMapping; +import com.alibaba.nacos.common.notify.NotifyCenter; +import com.alibaba.nacos.common.utils.MapUtil; +import com.alibaba.nacos.core.ability.inte.ClusterAbilityControlSupport; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/**. + * @author Daydreamer + * @description {@link AbstractAbilityControlManager} for nacos-server. + * @date 2022/7/13 21:14 + **/ +public class ServerAbilityControlManager extends DefaultAbilityControlManager implements ClusterAbilityControlSupport { + + private static final Logger LOGGER = LoggerFactory.getLogger(ServerAbilityControlManager.class); + + /**. + * ability for cluster + */ + private final Map clusterAbilityTable = new ConcurrentHashMap<>(); + + /**. + * ability for server + */ + private final Map serversAbilityTable = new ConcurrentHashMap<>(); + + /** + * components for cluster. these will be invoked if cluster ability table changes. + */ + private final Map> clusterHandlerMapping = new ConcurrentHashMap<>(); + + private Lock lockForClusterComponents = new ReentrantLock(); + + public ServerAbilityControlManager() { + // add current node into + AbilityTable currentNodeAbility = new AbilityTable(); + currentNodeAbility.setAbility(super.currentRunningAbility); + currentNodeAbility.setConnectionId("current-node"); + serversAbilityTable.put(currentNodeAbility.getConnectionId(), currentNodeAbility); + clusterAbilityTable.putAll(currentNodeAbility.getAbility()); + NotifyCenter.registerToPublisher(ClusterAbilityUpdateEvent.class, 16384); + } + + @Override + public boolean isSupport(String connectionId, String abilityKey) { + Boolean isRunning = currentRunningAbility.getOrDefault(abilityKey, false); + if (!isRunning) { + return false; + } + AbilityTable abilityTable = nodeAbilityTable.get(connectionId); + // it is null, check if initialing + if (abilityTable == null && AbilityStatus.INITIALIZING.equals(trace(connectionId))) { + // wait for ready + boolean finish = traceReadySyn(connectionId); + // if expired + if (!finish) { + return false; + } else { + abilityTable = nodeAbilityTable.get(connectionId); + } + } + // false if null + return abilityTable != null + && Optional.ofNullable(abilityTable.getAbility()) + .orElse(Collections.emptyMap()) + .getOrDefault(abilityKey, false); + } + + /**. + * Whether current cluster supports ability + * + * @param abilityKey ability key + * @return whether it is turn on + */ + @Override + public boolean isClusterEnableAbility(String abilityKey) { + return clusterAbilityTable.getOrDefault(abilityKey, Boolean.FALSE); + } + + @Override + public Map getClusterAbility() { + return Collections.unmodifiableMap(clusterAbilityTable); + } + + /**. + * Register components for cluster. These will be trigger when its interested ability changes + * + * @param abilityKey ability key + * @param priority the higher the priority, the faster it will be called + * @param handlerMapping component + */ + @Override + public void registerComponentForCluster(String abilityKey, HandlerMapping handlerMapping, int priority) { + doRegisterComponent(abilityKey, handlerMapping, this.clusterHandlerMapping, lockForClusterComponents, priority, clusterAbilityTable); + } + + @Override + public int removeClusterComponent(String abilityKey, Class handlerMappingClazz) { + return doRemove(abilityKey, handlerMappingClazz, lockForClusterComponents, clusterHandlerMapping); + } + + @Override + public int removeAllForCluster(String abilityKey) { + List remove = this.clusterHandlerMapping.remove(abilityKey); + return Optional.ofNullable(remove).orElse(Collections.emptyList()).size(); + } + + @Override + protected void add(AbilityTable table) { + // from which env + boolean isServer = table.isServer(); + // if not null + if (table.getConnectionId() != null && table.getAbility() != null) { + if (isServer) { + serversAbilityTable.put(table.getConnectionId(), table); + // enter cluster + Map nodeAbility = table.getAbility(); + Set keySet = clusterAbilityTable.keySet(); + keySet.forEach(abilityKey -> { + Boolean isEnabled = clusterAbilityTable.get(abilityKey); + Boolean val = nodeAbility.getOrDefault(abilityKey, Boolean.FALSE); + // new res + Boolean newRes = val && isEnabled; + // if ability changes + if (!newRes.equals(isEnabled)) { + triggerHandlerMappingAsyn(abilityKey, false, this.clusterHandlerMapping); + clusterAbilityTable.replace(abilityKey, false); + // notify + NotifyCenter.publishEvent(buildClusterEvent(abilityKey, false)); + } + }); + } + } + } + + private ClusterAbilityUpdateEvent buildClusterEvent(String abilityKey, boolean isOn) { + // notify + ClusterAbilityUpdateEvent event = new ClusterAbilityUpdateEvent(); + event.setAbilityKey(abilityKey); + event.setOn(isOn); + event.setTable(new AbilityTable().setAbility(Collections.unmodifiableMap(clusterAbilityTable))); + return event; + } + + @Override + protected void remove(String connectionId) { + // from which + AbilityTable abilityTable = nodeAbilityTable.get(connectionId); + // return if null + if (abilityTable == null) { + return; + } + // from which env + if (abilityTable.isServer()) { + // remove from server ability collection + serversAbilityTable.remove(connectionId); + // remove from cluster + if (MapUtil.isNotEmpty(serversAbilityTable)) { + Set keySet = clusterAbilityTable.keySet(); + keySet.forEach(abilityKey -> { + Boolean isEnabled = clusterAbilityTable.getOrDefault(abilityKey, Boolean.FALSE); + // nothing to do if enabled + if (isEnabled) { + return; + } + // recalculate + Boolean newVal = serversAbilityTable.values() + .stream() + .map(AbilityTable::getAbility) + .map((map) -> map.getOrDefault(abilityKey, Boolean.FALSE)) + .reduce((a, b) -> a && b) + .orElse(Boolean.FALSE); + clusterAbilityTable.replace(abilityKey, newVal); + // if change + if (!isEnabled.equals(newVal)) { + triggerHandlerMappingAsyn(abilityKey, newVal, this.clusterHandlerMapping); + // notify + NotifyCenter.publishEvent(buildClusterEvent(abilityKey, newVal)); + } + }); + } + } + } + + @Override + protected void doDestroy() { + if (MapUtil.isNotEmpty(clusterHandlerMapping)) { + if (MapUtil.isNotEmpty(clusterHandlerMapping)) { + clusterHandlerMapping.keySet().forEach(key -> doTriggerSyn(key, false, clusterHandlerMapping)); + } + } + LOGGER.warn("[ServerAbilityControlManager] - Destruction of the end"); + } + + /**. + * notify when current node ability changing + */ + public class ClusterAbilityUpdateEvent extends AbilityEvent { + + private static final long serialVersionUID = -122222411212200111L; + + private String abilityKey; + + private boolean isOn; + + private ClusterAbilityUpdateEvent(){} + + public String getAbilityKey() { + return abilityKey; + } + + public void setAbilityKey(String abilityKey) { + this.abilityKey = abilityKey; + } + + public boolean isOn() { + return isOn; + } + + public void setOn(boolean on) { + isOn = on; + } + + } + + @JustForTest + protected void setClusterAbilityTable(Map map) { + clusterAbilityTable.putAll(map); + } + + @JustForTest + protected Map> clusterHandlerMapping() { + return this.clusterHandlerMapping; + } + +} diff --git a/core/src/main/java/com/alibaba/nacos/core/ability/inte/ClusterAbilityControlSupport.java b/core/src/main/java/com/alibaba/nacos/core/ability/inte/ClusterAbilityControlSupport.java new file mode 100644 index 000000000..1150b2005 --- /dev/null +++ b/core/src/main/java/com/alibaba/nacos/core/ability/inte/ClusterAbilityControlSupport.java @@ -0,0 +1,80 @@ +/* + * Copyright 1999-2022 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.nacos.core.ability.inte; + +import com.alibaba.nacos.common.ability.handler.HandlerMapping; +import com.alibaba.nacos.common.ability.inter.AbilityControlManager; + +import java.util.Map; + +/**. + * @author Daydreamer + * @description It provides the capability to manage the AbilityTable in cluster for the {@link AbilityControlManager} + * @date 2022/8/10 23:18 + **/ +public interface ClusterAbilityControlSupport { + + /**. + * Return the cluster abilities. + * + * @return the cluster abilities. + */ + Map getClusterAbility(); + + /**. + * Register components for cluster. These will be trigger when its interested ability changes + * + * @param abilityKey ability key + * @param priority a positive number, the higher the priority, the faster it will be called + * @param handlerMapping component + */ + void registerComponentForCluster(String abilityKey, HandlerMapping handlerMapping, int priority); + + /**. + * Default method to register component + * + * @param abilityKey component key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey}. + * @param handlerMapping component instance. + */ + default void registerComponentForCluster(String abilityKey, HandlerMapping handlerMapping) { + registerComponentForCluster(abilityKey, handlerMapping, 1); + } + + /** + * Remove the component instance of

handlerMappingClazz

. + * + * @param abilityKey ability key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey} + * @param handlerMappingClazz implement of {@link HandlerMapping} + * @return the count of components have removed + */ + int removeClusterComponent(String abilityKey, Class handlerMappingClazz); + + /** + * Remove all {@link HandlerMapping} interested in the special ability. + * @param abilityKey abnility key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey} + * @return the count of components have removed + */ + int removeAllForCluster(String abilityKey); + + /**. + * Whether current cluster supports ability + * + * @param abilityKey ability key + * @return whether it is turn on + */ + boolean isClusterEnableAbility(String abilityKey); +} From 613335e763d78f572602f7be791600929b744b2e Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Sun, 28 Aug 2022 17:42:45 +0800 Subject: [PATCH 04/55] Add the junit test for AbilityControlManager. --- .../api/utils/AbilityTableUtilsTest.java | 56 +++ .../ability/AbilityControlManagerTest.java | 380 ++++++++++++++++++ .../TestClientAbilityControlManager.java | 30 ++ .../TestServerAbilityControlManager.java | 78 ++++ 4 files changed, 544 insertions(+) create mode 100644 api/src/test/java/com/alibaba/nacos/api/utils/AbilityTableUtilsTest.java create mode 100644 test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityControlManagerTest.java create mode 100644 test/core-test/src/test/java/com/alibaba/nacos/test/ability/TestClientAbilityControlManager.java create mode 100644 test/core-test/src/test/java/com/alibaba/nacos/test/ability/TestServerAbilityControlManager.java diff --git a/api/src/test/java/com/alibaba/nacos/api/utils/AbilityTableUtilsTest.java b/api/src/test/java/com/alibaba/nacos/api/utils/AbilityTableUtilsTest.java new file mode 100644 index 000000000..c2fea2c40 --- /dev/null +++ b/api/src/test/java/com/alibaba/nacos/api/utils/AbilityTableUtilsTest.java @@ -0,0 +1,56 @@ +/* + * Copyright 1999-2022 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.nacos.api.utils; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +public class AbilityTableUtilsTest { + + @Test + public void testGetByteArray() { + Map offset = new HashMap<>(); + offset.put("a", 1); + offset.put("b", 2); + offset.put("c", 10); + offset.put("d", 127); + byte[] abilityBitBy = AbilityTableUtils.getAbilityBitBy(offset.values()); + Assert.assertEquals(16, abilityBitBy.length); + Assert.assertEquals((byte) (3 << 6), abilityBitBy[0]); + Assert.assertEquals((byte) (1 << 6), abilityBitBy[1]); + } + + @Test + public void testGetAbilityTable() { + Map offset = new HashMap<>(); + offset.put("a", 1); + offset.put("b", 2); + offset.put("c", 10); + offset.put("d", 127); + byte[] abilityBitBy = AbilityTableUtils.getAbilityBitBy(offset.values()); + Map abilityTableBy = AbilityTableUtils.getAbilityTableBy(abilityBitBy, offset); + Assert.assertEquals(4, abilityTableBy.size()); + Assert.assertEquals(Boolean.TRUE, abilityTableBy.get("a")); + Assert.assertEquals(Boolean.TRUE, abilityTableBy.get("b")); + Assert.assertEquals(Boolean.TRUE, abilityTableBy.get("c")); + Assert.assertEquals(Boolean.TRUE, abilityTableBy.get("d")); + Assert.assertEquals(Boolean.FALSE, abilityTableBy.getOrDefault("asdasd", false)); + } +} diff --git a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityControlManagerTest.java b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityControlManagerTest.java new file mode 100644 index 000000000..e27009abe --- /dev/null +++ b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityControlManagerTest.java @@ -0,0 +1,380 @@ +/* + * Copyright 1999-2022 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.nacos.test.ability; + +import com.alibaba.nacos.api.ability.constant.AbilityStatus; +import com.alibaba.nacos.api.ability.entity.AbilityTable; +import com.alibaba.nacos.common.ability.handler.AbilityHandlePreProcessor; +import com.alibaba.nacos.common.ability.handler.HandlerMapping; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.springframework.boot.test.context.SpringBootTest; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; +import java.util.Set; + +@SpringBootTest +public class AbilityControlManagerTest { + + private TestClientAbilityControlManager clientAbilityControlManager = new TestClientAbilityControlManager(); + + private TestServerAbilityControlManager serverAbilityControlManager = new TestServerAbilityControlManager(); + + private volatile int clusterEnabled = 0; + + private volatile int enabled = 0; + + private volatile LinkedList testPriority = new LinkedList<>(); + + @Before + public void inject() { + Map newTable = new HashMap<>(); + newTable.put("stop-raft", true); + clientAbilityControlManager.setCurrentSupportingAbility(newTable); + + Map table = new HashMap<>(); + table.put("stop-raft", true); + serverAbilityControlManager.setCurrentSupportingAbility(table); + + Map cluster = new HashMap<>(); + cluster.put("stop-raft", true); + serverAbilityControlManager.setClusterAbility(cluster); + serverAbilityControlManager.setCurrentSupportingAbility(newTable); + } + + @Test + public void testClientAdd() { + Map newTable = new HashMap<>(); + newTable.put("test-no-existed", true); + newTable.put("stop-raft", true); + AbilityTable table = new AbilityTable(); + table.setConnectionId("test-00001"); + table.setAbility(newTable); + table.setServer(true); + clientAbilityControlManager.addNewTable(table); + Assert.assertFalse(clientAbilityControlManager.isSupport("test-00001", "test-no-existed")); + Assert.assertTrue(clientAbilityControlManager.isSupport("test-00001", "stop-raft")); + } + + @Test + public void testServerAdd() { + Map newTable = new HashMap<>(); + newTable.put("test-no-existed", true); + newTable.put("stop-raft", true); + AbilityTable table = new AbilityTable(); + table.setConnectionId("test-00001"); + table.setAbility(newTable); + table.setServer(true); + serverAbilityControlManager.addNewTable(table); + Assert.assertFalse(serverAbilityControlManager.isSupport("test-00001", "test-no-existed")); + Assert.assertTrue(serverAbilityControlManager.isSupport("test-00001", "stop-raft")); + Assert.assertTrue(serverAbilityControlManager.isClusterEnableAbility("stop-raft")); + + Map otherServer = new HashMap<>(); + otherServer.put("test-no-existed", true); + otherServer.put("stop-raft", false); + AbilityTable otherServerTable = new AbilityTable(); + otherServerTable.setConnectionId("test-00000"); + otherServerTable.setAbility(otherServer); + otherServerTable.setServer(true); + serverAbilityControlManager.addNewTable(otherServerTable); + Assert.assertFalse(serverAbilityControlManager.isClusterEnableAbility("stop-raft")); + + Map clientTa = new HashMap<>(); + clientTa.put("test-no-existed", true); + clientTa.put("stop-raft", false); + AbilityTable clientTable = new AbilityTable(); + clientTable.setConnectionId("test-00002"); + clientTable.setAbility(clientTa); + clientTable.setServer(false); + serverAbilityControlManager.addNewTable(clientTable); + Assert.assertFalse(serverAbilityControlManager.isClusterEnableAbility("stop-raft")); + } + + @Test + public void testClientRemove() { + Map clientTa = new HashMap<>(); + clientTa.put("test-no-existed", true); + clientTa.put("stop-raft", false); + AbilityTable clientTable = new AbilityTable(); + clientTable.setConnectionId("test-01111"); + clientTable.setAbility(clientTa); + clientTable.setServer(true); + clientAbilityControlManager.addNewTable(clientTable); + Assert.assertEquals(AbilityStatus.READY, clientAbilityControlManager.trace("test-01111")); + clientAbilityControlManager.removeTable("test-01111"); + Assert.assertEquals(AbilityStatus.NOT_EXIST, clientAbilityControlManager.trace("test-01111")); + } + + @Test + public void testComponent() throws InterruptedException { + enabled = 0; + // invoke enable() or disable() when registering + serverAbilityControlManager.registerComponent("stop-raft", new TestHandlerMapping(), -1); + Assert.assertEquals(1, serverAbilityControlManager.handlerMappingCount()); + + serverAbilityControlManager.enableCurrentNodeAbility("stop-raft"); + // wait for invoking handler asyn + Thread.sleep(200L); + // nothing happens if it has enabled + Assert.assertEquals(enabled, 1); + Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning("stop-raft")); + + // invoke disable() + serverAbilityControlManager.disableCurrentNodeAbility("stop-raft"); + // wait for invoking handler asyn + Thread.sleep(200L); + // disable will invoke handler + Assert.assertEquals(enabled, 0); + Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning("stop-raft")); + + serverAbilityControlManager.disableCurrentNodeAbility("stop-raft"); + // wait for invoking handler asyn + Thread.sleep(200L); + // nothing to do because it has disable + Assert.assertEquals(enabled, 0); + Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning("stop-raft")); + + serverAbilityControlManager.enableCurrentNodeAbility("stop-raft"); + // wait for invoking handler asyn + Thread.sleep(200L); + Assert.assertEquals(enabled, 1); + Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning("stop-raft")); + + serverAbilityControlManager.enableCurrentNodeAbility("stop-raft"); + // wait for invoking handler asyn + Thread.sleep(200L); + Assert.assertEquals(enabled, 1); + Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning("stop-raft")); + } + + @Test + public void testClusterComponent() throws InterruptedException { + clusterEnabled = 0; + // invoke enable() because it turn on + serverAbilityControlManager.registerComponentForCluster("stop-raft", new ClusterHandlerMapping(), -1); + Assert.assertEquals(1, serverAbilityControlManager.clusterHandlerMappingCount()); + Assert.assertTrue(serverAbilityControlManager.isClusterEnableAbility("stop-raft")); + Assert.assertEquals(clusterEnabled, 1); + + Map serverAbility = new HashMap<>(); + serverAbility.put("test-no-existed", true); + serverAbility.put("stop-raft", false); + AbilityTable serverTable = new AbilityTable(); + serverTable.setConnectionId("test-01111"); + serverTable.setAbility(serverAbility); + serverTable.setServer(true); + serverAbilityControlManager.addNewTable(serverTable); + // wait for invoking handler asyn + Thread.sleep(200L); + + // disabled + Assert.assertFalse(serverAbilityControlManager.isClusterEnableAbility("stop-raft")); + Assert.assertEquals(clusterEnabled, 0); + + // remove this table to enabled + serverAbilityControlManager.removeTable("test-01111"); + // wait for invoking handler asyn + Thread.sleep(200L); + Assert.assertTrue(serverAbilityControlManager.isClusterEnableAbility("stop-raft")); + Assert.assertEquals(clusterEnabled, 1); + } + + @Test + public void testCurrentNodeAbility() { + Set keySet = serverAbilityControlManager.getCurrentRunningAbility().keySet(); + // diable all + keySet.forEach(key -> serverAbilityControlManager.disableCurrentNodeAbility(key)); + // get all + keySet.forEach(key -> { + Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning(key)); + }); + // enable all + keySet.forEach(key -> serverAbilityControlManager.enableCurrentNodeAbility(key)); + // get all + keySet.forEach(key -> { + Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(key)); + }); + } + + @Test + public void testPre() { + clientAbilityControlManager.addPostProcessor(new TestPreHandler()); + clientAbilityControlManager.enableCurrentNodeAbility("stop-raft"); + AbilityTable abilityTable = new AbilityTable(); + abilityTable.setConnectionId("1111"); + HashMap table = new HashMap<>(); + table.put("stop-raft", false); + abilityTable.setAbility(table); + clientAbilityControlManager.addNewTable(abilityTable); + Assert.assertFalse(clientAbilityControlManager.isSupport("1111", "stop-raft")); + } + + @Test + public void testStateSyn() { + // register a processing long time handler + AbilityTable abilityTable = new AbilityTable(); + abilityTable.setConnectionId("1111"); + HashMap table = new HashMap<>(); + table.put("stop-raft", false); + abilityTable.setAbility(table); + clientAbilityControlManager.addPostProcessor(new TestStatusPreHandler()); + // 追踪状态 + long begin = System.currentTimeMillis(); + clientAbilityControlManager.addNewTable(abilityTable); + Assert.assertTrue(clientAbilityControlManager.traceReadySyn("1111")); + long end = System.currentTimeMillis(); + Assert.assertTrue(end - begin > 5000); + } + + @Test + public void testPriority() throws InterruptedException { + TestServerAbilityControlManager testServerAbilityControlManager = new TestServerAbilityControlManager(); + String key = "key"; + TestPriority clusterHandlerMapping1 = new TestPriority("1"); + TestPriority clusterHandlerMapping2 = new TestPriority("2"); + TestPriority clusterHandlerMapping3 = new TestPriority("3"); + // first one, invoke enable() + testServerAbilityControlManager.registerComponentForCluster(key, clusterHandlerMapping2, 128); + // last one, invoke enable() + testServerAbilityControlManager.registerComponentForCluster(key, clusterHandlerMapping3); + // second one, invoke enable() + testServerAbilityControlManager.registerComponentForCluster(key, clusterHandlerMapping1, 12); + // trigger cluster + testServerAbilityControlManager.triggerCluster(key); + Assert.assertEquals(3, testServerAbilityControlManager.getClusterHandlerMapping(key).size()); + // wait for invoking + Thread.sleep(200L); + Assert.assertEquals("2", testPriority.poll()); + Assert.assertEquals("3", testPriority.poll()); + Assert.assertEquals("1", testPriority.poll()); + // here are priority + Assert.assertEquals("2", testPriority.poll()); + Assert.assertEquals("1", testPriority.poll()); + Assert.assertEquals("3", testPriority.poll()); + // remove + testServerAbilityControlManager.registerClusterHandlerMapping(key, new ClusterHandlerMapping(), -1); + Assert.assertEquals(4, testServerAbilityControlManager.getClusterHandlerMapping(key).size()); + Assert.assertEquals(1, testServerAbilityControlManager.removeClusterComponent(key, ClusterHandlerMapping.class)); + Assert.assertEquals(3, testServerAbilityControlManager.getClusterHandlerMapping(key).size()); + testServerAbilityControlManager.removeAllForCluster(key); + Assert.assertNull(testServerAbilityControlManager.getClusterHandlerMapping(key)); + + // first one + testServerAbilityControlManager.registerComponent(key, clusterHandlerMapping2, 128); + // last one + testServerAbilityControlManager.registerComponent(key, clusterHandlerMapping3); + // second one + testServerAbilityControlManager.registerComponent(key, clusterHandlerMapping1, 12); + Assert.assertEquals(3, testServerAbilityControlManager.getHandlerMapping(key).size()); + // wait for invoking + Thread.sleep(200L); + // trigger + testServerAbilityControlManager.trigger(key); + // wait for invoking + Thread.sleep(200L); + Assert.assertEquals("2", testPriority.poll()); + Assert.assertEquals("3", testPriority.poll()); + Assert.assertEquals("1", testPriority.poll()); + // here are priority + Assert.assertEquals("2", testPriority.poll()); + Assert.assertEquals("1", testPriority.poll()); + Assert.assertEquals("3", testPriority.poll()); + // remove + testServerAbilityControlManager.registerComponent(key, new ClusterHandlerMapping(), -1); + Assert.assertEquals(4, testServerAbilityControlManager.getHandlerMapping(key).size()); + Assert.assertEquals(1, testServerAbilityControlManager.removeComponent(key, ClusterHandlerMapping.class)); + Assert.assertEquals(3, testServerAbilityControlManager.getHandlerMapping(key).size()); + testServerAbilityControlManager.removeAll(key); + Assert.assertNull(testServerAbilityControlManager.getClusterHandlerMapping(key)); + } + + class TestPriority implements HandlerMapping { + + String mark; + + public TestPriority(String mark) { + // unique one + this.mark = mark.intern(); + } + + @Override + public void enable() { + testPriority.offer(mark); + } + + @Override + public void disable() { + testPriority.offer(mark); + } + } + + class ClusterHandlerMapping implements HandlerMapping { + + @Override + public void enable() { + clusterEnabled++; + } + + @Override + public void disable() { + clusterEnabled--; + } + } + + class TestHandlerMapping implements HandlerMapping { + + @Override + public void enable() { + enabled++; + } + + @Override + public void disable() { + enabled--; + } + + } + + class TestPreHandler implements AbilityHandlePreProcessor { + + @Override + public AbilityTable handle(AbilityTable source) { + source.setConnectionId("pre-handle"); + return source; + } + } + + class TestStatusPreHandler implements AbilityHandlePreProcessor { + + @Override + public AbilityTable handle(AbilityTable source) { + try { + // block + Thread.sleep(5000); + } catch (Exception e) { + e.printStackTrace(); + } + return source; + } + } +} + + diff --git a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/TestClientAbilityControlManager.java b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/TestClientAbilityControlManager.java new file mode 100644 index 000000000..5e9fc0899 --- /dev/null +++ b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/TestClientAbilityControlManager.java @@ -0,0 +1,30 @@ +/* + * Copyright 1999-2022 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.nacos.test.ability; + +import com.alibaba.nacos.client.ability.ClientAbilityControlManager; +import com.alibaba.nacos.common.JustForTest; + +import java.util.Map; + +public class TestClientAbilityControlManager extends ClientAbilityControlManager { + + @JustForTest + public void setCurrentSupportingAbility(Map ability) { + currentRunningAbility.putAll(ability); + } +} diff --git a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/TestServerAbilityControlManager.java b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/TestServerAbilityControlManager.java new file mode 100644 index 000000000..2c48bc821 --- /dev/null +++ b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/TestServerAbilityControlManager.java @@ -0,0 +1,78 @@ +/* + * Copyright 1999-2022 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.nacos.test.ability; + +import com.alibaba.nacos.common.JustForTest; +import com.alibaba.nacos.common.ability.handler.HandlerMapping; +import com.alibaba.nacos.core.ability.control.ServerAbilityControlManager; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class TestServerAbilityControlManager extends ServerAbilityControlManager { + + @JustForTest + public void setCurrentSupportingAbility(Map ability) { + currentRunningAbility.putAll(ability); + } + + @JustForTest + public void setClusterAbility(Map ability) { + super.setClusterAbilityTable(ability); + } + + @JustForTest + public int handlerMappingCount() { + return super.handlerMapping().size(); + } + + @JustForTest + public List getHandlerMapping(String abilityKey) { + return super.handlerMapping().get(abilityKey); + } + + @JustForTest + public int clusterHandlerMappingCount() { + return super.clusterHandlerMapping().size(); + } + + @JustForTest + public List getClusterHandlerMapping(String abilityKey) { + return super.clusterHandlerMapping().get(abilityKey); + } + + /** + * Just a test method. + */ + @JustForTest + public void registerClusterHandlerMapping(String key, HandlerMapping handlerMapping, int priority) { + List orDefault = super.clusterHandlerMapping().getOrDefault(key, new ArrayList<>()); + orDefault.add(new HandlerWithPriority(handlerMapping, priority)); + clusterHandlerMapping().put(key, orDefault); + } + + @JustForTest + public void triggerCluster(String abilityKey) { + triggerHandlerMappingAsyn(abilityKey, true, clusterHandlerMapping()); + } + + @JustForTest + public void trigger(String abilityKey) { + triggerHandlerMappingAsyn(abilityKey, true, handlerMapping()); + } +} From ce4fb189b87ef46d6b1d72a92492240c87445a9b Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Sun, 28 Aug 2022 18:08:29 +0800 Subject: [PATCH 05/55] Fix the bug that cannot load AbilityControlManager. --- common/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/common/pom.xml b/common/pom.xml index b1c91f19d..bda1fd571 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -84,6 +84,7 @@ true nacos-version.txt + META-INF/services/com.alibaba.nacos.common.ability.DefaultAbilityControlManager From 838c3d0ded82f16e3969a256e14b9425a3f87265 Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Sun, 28 Aug 2022 18:20:35 +0800 Subject: [PATCH 06/55] Adapt the support of new ability control. --- .../request/ConnectionSetupRequest.java | 13 +-- .../remote/response/ServerCheckResponse.java | 13 ++- .../client/config/impl/ClientWorker.java | 10 +- .../AbstractAbilityControlManager.java | 2 +- .../nacos/common/remote/client/RpcClient.java | 103 +++++++++++++++++- .../remote/client/RpcClientFactory.java | 2 + .../common/remote/client/grpc/GrpcClient.java | 15 ++- .../alibaba/nacos/core/remote/Connection.java | 12 +- .../grpc/GrpcBiStreamRequestAcceptor.java | 6 +- .../core/remote/grpc/GrpcRequestAcceptor.java | 6 +- .../ServerAbilityConnectionListener.java | 45 ++++++++ 11 files changed, 202 insertions(+), 25 deletions(-) create mode 100644 core/src/main/java/com/alibaba/nacos/core/remote/listener/ServerAbilityConnectionListener.java diff --git a/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequest.java b/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequest.java index 56e94dad2..67e246ad6 100644 --- a/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequest.java +++ b/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequest.java @@ -16,7 +16,6 @@ package com.alibaba.nacos.api.remote.request; -import com.alibaba.nacos.api.ability.ClientAbilities; import java.util.HashMap; import java.util.Map; @@ -31,12 +30,12 @@ public class ConnectionSetupRequest extends InternalRequest { private String clientVersion; - private ClientAbilities abilities; - private String tenant; private Map labels = new HashMap<>(); + private byte[] abilityTable; + public ConnectionSetupRequest() { } @@ -64,11 +63,11 @@ public class ConnectionSetupRequest extends InternalRequest { this.tenant = tenant; } - public ClientAbilities getAbilities() { - return abilities; + public byte[] getAbilityTable() { + return abilityTable; } - public void setAbilities(ClientAbilities abilities) { - this.abilities = abilities; + public void setAbilityTable(byte[] abilityTable) { + this.abilityTable = abilityTable; } } diff --git a/api/src/main/java/com/alibaba/nacos/api/remote/response/ServerCheckResponse.java b/api/src/main/java/com/alibaba/nacos/api/remote/response/ServerCheckResponse.java index fd3981cd1..4f5092fc0 100644 --- a/api/src/main/java/com/alibaba/nacos/api/remote/response/ServerCheckResponse.java +++ b/api/src/main/java/com/alibaba/nacos/api/remote/response/ServerCheckResponse.java @@ -26,12 +26,15 @@ public class ServerCheckResponse extends Response { private String connectionId; + private byte[] abilities; + public ServerCheckResponse() { } - public ServerCheckResponse(String connectionId) { + public ServerCheckResponse(String connectionId, byte[] abilities) { this.connectionId = connectionId; + this.abilities = abilities; } public String getConnectionId() { @@ -41,4 +44,12 @@ public class ServerCheckResponse extends Response { public void setConnectionId(String connectionId) { this.connectionId = connectionId; } + + public byte[] getAbilities() { + return abilities; + } + + public void setAbilities(byte[] abilities) { + this.abilities = abilities; + } } diff --git a/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java b/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java index 7cb69a8f1..2d83a5a52 100644 --- a/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java +++ b/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java @@ -18,6 +18,7 @@ package com.alibaba.nacos.client.config.impl; import com.alibaba.nacos.api.PropertyKeyConst; import com.alibaba.nacos.api.ability.ClientAbilities; +import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.common.Constants; import com.alibaba.nacos.api.config.ConfigType; import com.alibaba.nacos.api.config.listener.Listener; @@ -892,12 +893,9 @@ public class ClientWorker implements Closeable { } } - - private ClientAbilities initAbilities() { - ClientAbilities clientAbilities = new ClientAbilities(); - clientAbilities.getRemoteAbility().setSupportRemoteConnection(true); - clientAbilities.getConfigAbility().setSupportRemoteMetrics(true); - return clientAbilities; + + private byte[] initAbilities() { + return AbilityKey.getAbilityBitFlags(); } /** diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java index f78fd0a20..5b616a588 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java @@ -180,7 +180,7 @@ public abstract class AbstractAbilityControlManager implements TraceableAbilityC // hook method remove(connectionId); // remove - nodeAbilityTable.remove(connectionId); + removingTable = nodeAbilityTable.remove(connectionId); } finally { lockForAbilityTable.unlock(); } diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java index 8edb11100..3a5d1bff9 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java @@ -17,6 +17,8 @@ package com.alibaba.nacos.common.remote.client; import com.alibaba.nacos.api.ability.ClientAbilities; +import com.alibaba.nacos.api.ability.constant.AbilityStatus; +import com.alibaba.nacos.api.ability.entity.AbilityTable; import com.alibaba.nacos.api.common.Constants; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.remote.RequestCallBack; @@ -29,6 +31,8 @@ import com.alibaba.nacos.api.remote.response.ClientDetectionResponse; import com.alibaba.nacos.api.remote.response.ConnectResetResponse; import com.alibaba.nacos.api.remote.response.ErrorResponse; import com.alibaba.nacos.api.remote.response.Response; +import com.alibaba.nacos.common.ability.DefaultAbilityControlManager; +import com.alibaba.nacos.common.ability.discover.NacosAbilityManagerHolder; import com.alibaba.nacos.common.lifecycle.Closeable; import com.alibaba.nacos.common.remote.ConnectionType; import com.alibaba.nacos.common.remote.PayloadRegistry; @@ -50,6 +54,7 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.locks.LockSupport; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -77,6 +82,8 @@ public abstract class RpcClient implements Closeable { private final BlockingQueue reconnectionSignal = new ArrayBlockingQueue<>(1); + protected final BlockingQueue recServerAbilitySignal = new LinkedBlockingQueue<>(); + protected volatile Connection currentConnection; protected Map labels = new HashMap<>(); @@ -89,7 +96,7 @@ public abstract class RpcClient implements Closeable { private static final long DEFAULT_TIMEOUT_MILLS = 3000L; - protected ClientAbilities clientAbilities; + protected byte[] clientAbilities; /** * default keep alive time 5s. @@ -137,7 +144,7 @@ public abstract class RpcClient implements Closeable { * * @param clientAbilities clientAbilities. */ - public RpcClient clientAbilities(ClientAbilities clientAbilities) { + public RpcClient clientAbilities(byte[] clientAbilities) { this.clientAbilities = clientAbilities; return this; } @@ -279,7 +286,7 @@ public abstract class RpcClient implements Closeable { return; } - clientEventExecutor = new ScheduledThreadPoolExecutor(2, r -> { + clientEventExecutor = new ScheduledThreadPoolExecutor(3, r -> { Thread t = new Thread(r); t.setName("com.alibaba.nacos.client.remote.worker"); t.setDaemon(true); @@ -302,6 +309,32 @@ public abstract class RpcClient implements Closeable { } } }); + + // receive ability table + clientEventExecutor.submit(() -> { + // save server ability table or remove + while (!clientEventExecutor.isTerminated() && !clientEventExecutor.isShutdown()) { + try { + RecServerAbilityContext take = recServerAbilitySignal.take(); + // avoid interrupted should not null + if (take != null) { + DefaultAbilityControlManager manager = NacosAbilityManagerHolder.getInstance(); + // remove + manager.removeTable(take.oldConnectionId); + // and add + manager.addNewTable( + new AbilityTable() + .setAbility(take.abilityTable) + .setConnectionId(take.connectionId) + .setVersion(take.version) + .setServer(true) + ); + } + } catch (InterruptedException e) { + // do nothing + } + } + }); clientEventExecutor.submit(() -> { while (true) { @@ -395,6 +428,24 @@ public abstract class RpcClient implements Closeable { } + // try to wait for the ability table to be added, but it will check three time at most + AbilityStatus status = AbilityStatus.NOT_EXIST; + int reCheckTimes = RETRY_TIMES; + while (!isShutdown() && connectToServer != null && status.equals(AbilityStatus.NOT_EXIST) && reCheckTimes > 0) { + LockSupport.parkNanos(100L); + status = NacosAbilityManagerHolder.getInstance().trace(connectToServer.getConnectionId()); + reCheckTimes--; + } + + // judge whether support ability table + // wait to get ability table if initializing, it will pass if server doesn't support ability table or table ready + boolean connected = true; + while (!isShutdown() && connectToServer != null && AbilityStatus.INITIALIZING.equals(status) && connected) { + // wait for complete + // return false if disconnect + connected = NacosAbilityManagerHolder.getInstance().traceReadySyn(connectToServer.getConnectionId()); + } + if (connectToServer != null) { LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Success to connect to server [{}] on start up, connectionId = {}", name, connectToServer.serverInfo.getAddress(), connectToServer.getConnectionId()); @@ -453,6 +504,9 @@ public abstract class RpcClient implements Closeable { LOGGER.info("Shutdown rpc client, set status to shutdown"); rpcClientStatus.set(RpcClientStatus.SHUTDOWN); LOGGER.info("Shutdown client event executor " + clientEventExecutor); + if (currentConnection != null) { + NacosAbilityManagerHolder.getInstance().removeTable(currentConnection.getConnectionId()); + } if (clientEventExecutor != null) { clientEventExecutor.shutdownNow(); } @@ -522,7 +576,30 @@ public abstract class RpcClient implements Closeable { if (connectionNew != null) { LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Success to connect a server [{}], connectionId = {}", name, serverInfo.getAddress(), connectionNew.getConnectionId()); - // successfully create a new connect. + + // try to wait for the ability table to be added, but it will check three time at most + AbilityStatus status = AbilityStatus.NOT_EXIST; + int reCheckTimes = RETRY_TIMES; + while (status.equals(AbilityStatus.NOT_EXIST) && reCheckTimes > 0) { + LockSupport.parkNanos(100L); + status = NacosAbilityManagerHolder.getInstance().trace(connectionNew.getConnectionId()); + reCheckTimes--; + } + + // judge whether support ability table + // wait to get ability table if initializing, it will pass if server doesn't support ability table or table ready + boolean connected = true; + while (!isShutdown() && AbilityStatus.INITIALIZING.equals(status) && connected) { + // wait for complete + // return false if disconnect + connected = NacosAbilityManagerHolder.getInstance() + .traceReadySyn(connectionNew.getConnectionId()); + } + + LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Success to get server ability table, connectionId = {}", + name, connectionNew.getConnectionId()); + + // successfully create a new connect if (currentConnection != null) { LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Abandon prev connection, server is {}, connectionId is {}", name, @@ -1034,6 +1111,24 @@ public abstract class RpcClient implements Closeable { ServerInfo serverInfo; } + protected class RecServerAbilityContext { + + public RecServerAbilityContext(String connectionId, Map abilityTable, String version, String oldConnectionId) { + this.connectionId = connectionId; + this.abilityTable = abilityTable; + this.version = version; + this.oldConnectionId = oldConnectionId; + } + + String connectionId; + + Map abilityTable; + + String version; + + String oldConnectionId; + } + public String getTenant() { return tenant; } diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClientFactory.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClientFactory.java index 2d71b9e46..8b40c9cfb 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClientFactory.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClientFactory.java @@ -16,6 +16,7 @@ package com.alibaba.nacos.common.remote.client; +import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.common.remote.ConnectionType; import com.alibaba.nacos.common.remote.client.grpc.GrpcClient; @@ -139,6 +140,7 @@ public class RpcClientFactory { client.setThreadPoolCoreSize(threadPoolCoreSize); client.setThreadPoolMaxSize(threadPoolMaxSize); client.labels(labels); + client.clientAbilities(AbilityKey.getAbilityBitFlags()); return client; }); } diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java index d285583fb..0c81caf97 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java @@ -16,6 +16,7 @@ package com.alibaba.nacos.common.remote.client.grpc; +import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.grpc.auto.BiRequestStreamGrpc; import com.alibaba.nacos.api.grpc.auto.Payload; @@ -26,6 +27,7 @@ import com.alibaba.nacos.api.remote.request.ServerCheckRequest; import com.alibaba.nacos.api.remote.response.ErrorResponse; import com.alibaba.nacos.api.remote.response.Response; import com.alibaba.nacos.api.remote.response.ServerCheckResponse; +import com.alibaba.nacos.api.utils.AbilityTableUtils; import com.alibaba.nacos.common.remote.ConnectionType; import com.alibaba.nacos.common.remote.client.Connection; import com.alibaba.nacos.common.remote.client.RpcClient; @@ -43,6 +45,7 @@ import io.grpc.stub.StreamObserver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Map; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -308,6 +311,16 @@ public abstract class GrpcClient extends RpcClient { shuntDownChannel(managedChannel); return null; } + + // submit ability table as soon as possible + // ability table will be null if server doesn't support ability table + ServerCheckResponse serverCheckResponse = (ServerCheckResponse) response; + Map abilityTable = AbilityTableUtils + .getAbilityTableBy(serverCheckResponse.getAbilities(), AbilityKey.offset()); + String oldConnId = currentConnection == null ? null : currentConnection.getConnectionId(); + RecServerAbilityContext recServerAbilityContext = new RecServerAbilityContext(serverCheckResponse.getConnectionId(), + abilityTable, null, oldConnId); + recServerAbilitySignal.offer(recServerAbilityContext); BiRequestStreamGrpc.BiRequestStreamStub biRequestStreamStub = BiRequestStreamGrpc .newStub(newChannelStubTemp.getChannel()); @@ -325,7 +338,7 @@ public abstract class GrpcClient extends RpcClient { ConnectionSetupRequest conSetupRequest = new ConnectionSetupRequest(); conSetupRequest.setClientVersion(VersionUtils.getFullClientVersion()); conSetupRequest.setLabels(super.getLabels()); - conSetupRequest.setAbilities(super.clientAbilities); + conSetupRequest.setAbilityTable(super.clientAbilities == null ? AbilityKey.getAbilityBitFlags() : clientAbilities); conSetupRequest.setTenant(super.getTenant()); grpcConn.sendRequest(conSetupRequest); //wait to register connection setup diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java b/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java index 96eace5e0..2553d24a7 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java @@ -32,6 +32,8 @@ public abstract class Connection implements Requester { private boolean traced = false; + private Map abilityTable; + private ClientAbilities abilities; private final ConnectionMeta metaInfo; @@ -52,6 +54,14 @@ public abstract class Connection implements Requester { this.traced = traced; } + public Map getAbilityTable() { + return abilityTable; + } + + public void setAbilityTable(Map abilityTable) { + this.abilityTable = abilityTable; + } + /** * get abilities. * @@ -95,7 +105,7 @@ public abstract class Connection implements Requester { @Override public String toString() { - return "Connection{" + "traced=" + traced + ", abilities=" + abilities + ", metaInfo=" + metaInfo + '}'; + return "Connection{" + "traced=" + traced + ", abilities=" + abilityTable + ", metaInfo=" + metaInfo + '}'; } } diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java index 15432c91e..6f2c32b7f 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java @@ -16,12 +16,14 @@ package com.alibaba.nacos.core.remote.grpc; +import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.common.Constants; import com.alibaba.nacos.api.grpc.auto.BiRequestStreamGrpc; import com.alibaba.nacos.api.grpc.auto.Payload; import com.alibaba.nacos.api.remote.request.ConnectResetRequest; import com.alibaba.nacos.api.remote.request.ConnectionSetupRequest; import com.alibaba.nacos.api.remote.response.Response; +import com.alibaba.nacos.api.utils.AbilityTableUtils; import com.alibaba.nacos.common.remote.ConnectionType; import com.alibaba.nacos.common.remote.client.grpc.GrpcUtils; import com.alibaba.nacos.core.remote.Connection; @@ -114,13 +116,13 @@ public class GrpcBiStreamRequestAcceptor extends BiRequestStreamGrpc.BiRequestSt if (labels != null && labels.containsKey(Constants.APPNAME)) { appName = labels.get(Constants.APPNAME); } - + ConnectionMeta metaInfo = new ConnectionMeta(connectionId, payload.getMetadata().getClientIp(), remoteIp, remotePort, localPort, ConnectionType.GRPC.getType(), setUpRequest.getClientVersion(), appName, setUpRequest.getLabels()); metaInfo.setTenant(setUpRequest.getTenant()); Connection connection = new GrpcConnection(metaInfo, responseObserver, CONTEXT_KEY_CHANNEL.get()); - connection.setAbilities(setUpRequest.getAbilities()); + connection.setAbilityTable(AbilityTableUtils.getAbilityTableBy(setUpRequest.getAbilityTable(), AbilityKey.offset())); boolean rejectSdkOnStarting = metaInfo.isSdkSource() && !ApplicationUtils.isStarted(); if (rejectSdkOnStarting || !connectionManager.register(connectionId, connection)) { diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java index 801d3d84a..d16ce16ab 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java @@ -16,6 +16,7 @@ package com.alibaba.nacos.core.remote.grpc; +import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.grpc.auto.Payload; import com.alibaba.nacos.api.grpc.auto.RequestGrpc; @@ -85,10 +86,11 @@ public class GrpcRequestAcceptor extends RequestGrpc.RequestImplBase { responseObserver.onCompleted(); return; } - + // server check. if (ServerCheckRequest.class.getSimpleName().equals(type)) { - Payload serverCheckResponseP = GrpcUtils.convert(new ServerCheckResponse(CONTEXT_KEY_CONN_ID.get())); + Payload serverCheckResponseP = GrpcUtils.convert(new ServerCheckResponse(CONTEXT_KEY_CONN_ID.get(), + AbilityKey.getAbilityBitFlags())); traceIfNecessary(serverCheckResponseP, false); responseObserver.onNext(serverCheckResponseP); responseObserver.onCompleted(); diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/listener/ServerAbilityConnectionListener.java b/core/src/main/java/com/alibaba/nacos/core/remote/listener/ServerAbilityConnectionListener.java new file mode 100644 index 000000000..7b5810592 --- /dev/null +++ b/core/src/main/java/com/alibaba/nacos/core/remote/listener/ServerAbilityConnectionListener.java @@ -0,0 +1,45 @@ +/* + * Copyright 1999-2022 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.nacos.core.remote.listener; + +import com.alibaba.nacos.api.ability.entity.AbilityTable; +import com.alibaba.nacos.common.ability.discover.NacosAbilityManagerHolder; +import com.alibaba.nacos.core.remote.ClientConnectionEventListener; +import com.alibaba.nacos.core.remote.Connection; +import org.springframework.stereotype.Component; + +/**. + * @author Daydreamer + * @description This listener is used to register or remove ability table. + * @date 2022/7/17 19:18 + **/ +@Component +public class ServerAbilityConnectionListener extends ClientConnectionEventListener { + + @Override + public void clientConnected(Connection connect) { + // it will be thought from client all + AbilityTable abilityTable = new AbilityTable(connect.getMetaInfo().getConnectionId(), connect.getAbilityTable(), + false, connect.getMetaInfo().getVersion()); + NacosAbilityManagerHolder.getInstance().addNewTable(abilityTable); + } + + @Override + public void clientDisConnected(Connection connect) { + NacosAbilityManagerHolder.getInstance().removeTable(connect.getMetaInfo().getConnectionId()); + } +} From 26bbc5780b8891f907936723dcaf77bb186c1029 Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Sun, 28 Aug 2022 18:45:56 +0800 Subject: [PATCH 07/55] Adapt and replace old version ability api. --- .../nacos/api/ability/ClientAbilities.java | 1 + .../nacos/api/ability/ServerAbilities.java | 1 + .../com/alibaba/nacos/core/cluster/Member.java | 13 +++++++++++++ .../alibaba/nacos/core/cluster/MemberUtil.java | 10 +++++++--- .../nacos/core/cluster/ServerMemberManager.java | 17 ++++++++++++++--- .../listener/StartingApplicationListener.java | 2 ++ 6 files changed, 38 insertions(+), 6 deletions(-) diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/ClientAbilities.java b/api/src/main/java/com/alibaba/nacos/api/ability/ClientAbilities.java index ea4dd9aa7..fe9c80e95 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/ClientAbilities.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/ClientAbilities.java @@ -28,6 +28,7 @@ import java.io.Serializable; * @author liuzunfei * @version $Id: ClientAbilities.java, v 0.1 2021年01月24日 00:09 AM liuzunfei Exp $ */ +@Deprecated public class ClientAbilities implements Serializable { private static final long serialVersionUID = -3590789441404549261L; diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/ServerAbilities.java b/api/src/main/java/com/alibaba/nacos/api/ability/ServerAbilities.java index f6b8b5591..80d3f772d 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/ServerAbilities.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/ServerAbilities.java @@ -29,6 +29,7 @@ import java.util.Objects; * @author liuzunfei * @version $Id: ServerAbilities.java, v 0.1 2021年01月24日 00:09 AM liuzunfei Exp $ */ +@Deprecated public class ServerAbilities implements Serializable { private static final long serialVersionUID = -2120543002911304171L; diff --git a/core/src/main/java/com/alibaba/nacos/core/cluster/Member.java b/core/src/main/java/com/alibaba/nacos/core/cluster/Member.java index 090cf9f41..69b0cafd6 100644 --- a/core/src/main/java/com/alibaba/nacos/core/cluster/Member.java +++ b/core/src/main/java/com/alibaba/nacos/core/cluster/Member.java @@ -53,8 +53,11 @@ public class Member implements Comparable, Cloneable, Serializable { private transient int failAccessCnt = 0; + @Deprecated private ServerAbilities abilities = new ServerAbilities(); + private boolean supportRemoteConnection; + public Member() { String prefix = "nacos.core.member.meta."; extendInfo.put(MemberMetaDataConstants.SITE_KEY, @@ -65,10 +68,20 @@ public class Member implements Comparable, Cloneable, Serializable { .put(MemberMetaDataConstants.WEIGHT, EnvUtil.getProperty(prefix + MemberMetaDataConstants.WEIGHT, "1")); } + public boolean isSupportRemoteConnection() { + return supportRemoteConnection; + } + + public void setSupportRemoteConnection(boolean supportRemoteConnection) { + this.supportRemoteConnection = supportRemoteConnection; + } + + @Deprecated public ServerAbilities getAbilities() { return abilities; } + @Deprecated public void setAbilities(ServerAbilities abilities) { this.abilities = abilities; } diff --git a/core/src/main/java/com/alibaba/nacos/core/cluster/MemberUtil.java b/core/src/main/java/com/alibaba/nacos/core/cluster/MemberUtil.java index 3a81aeb08..07cf27b8a 100644 --- a/core/src/main/java/com/alibaba/nacos/core/cluster/MemberUtil.java +++ b/core/src/main/java/com/alibaba/nacos/core/cluster/MemberUtil.java @@ -67,6 +67,7 @@ public class MemberUtil { oldMember.setExtendInfo(newMember.getExtendInfo()); oldMember.setAddress(newMember.getAddress()); oldMember.setAbilities(newMember.getAbilities()); + oldMember.setSupportRemoteConnection(newMember.isSupportRemoteConnection()); } /** @@ -108,7 +109,10 @@ public class MemberUtil { if (member.getAbilities() == null || member.getAbilities().getRemoteAbility() == null) { return false; } - return member.getAbilities().getRemoteAbility().isSupportRemoteConnection(); + + boolean oldVerJudge = member.getAbilities().getRemoteAbility().isSupportRemoteConnection(); + + return member.isSupportRemoteConnection() || oldVerJudge; } public static int calculateRaftPort(Member member) { @@ -279,8 +283,8 @@ public class MemberUtil { if (!expected.getState().equals(actual.getState())) { return true; } - - if (!expected.getAbilities().equals(actual.getAbilities())) { + + if (!(expected.isSupportRemoteConnection() && actual.isSupportRemoteConnection())) { return true; } diff --git a/core/src/main/java/com/alibaba/nacos/core/cluster/ServerMemberManager.java b/core/src/main/java/com/alibaba/nacos/core/cluster/ServerMemberManager.java index 16c6824a5..d90653996 100644 --- a/core/src/main/java/com/alibaba/nacos/core/cluster/ServerMemberManager.java +++ b/core/src/main/java/com/alibaba/nacos/core/cluster/ServerMemberManager.java @@ -152,6 +152,7 @@ public class ServerMemberManager implements ApplicationListener Date: Sun, 28 Aug 2022 18:48:48 +0800 Subject: [PATCH 08/55] Example for new ability. --- .../java/com/alibaba/nacos/api/ability/constant/AbilityKey.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java index 0971ca7af..cf194ccca 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java @@ -51,7 +51,7 @@ public class AbilityKey { * This field can be used outside. * * And then you need to declare the offset of the flag bit of this ability in the ability table, you can: - * CURRENT_NODE_ABILITY_TABLE.put("compression", 1); means that is the first bit from left to right in the table. + * CURRENT_SERVER_ABILITY_OFFSET.put("compression", 1); means that is the first bit from left to right in the table. * */ From de9e113e24571aa6f9f6b8b905dc01759dff1829 Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Sun, 28 Aug 2022 19:10:55 +0800 Subject: [PATCH 09/55] Fix checkstyle --- .../nacos/api/remote/request/ConnectionSetupRequest.java | 1 - .../com/alibaba/nacos/client/config/impl/ClientWorker.java | 1 - .../java/com/alibaba/nacos/common/remote/client/RpcClient.java | 1 - .../com/alibaba/nacos/core/cluster/ServerMemberManager.java | 3 ++- 4 files changed, 2 insertions(+), 4 deletions(-) diff --git a/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequest.java b/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequest.java index 67e246ad6..046a897a4 100644 --- a/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequest.java +++ b/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequest.java @@ -16,7 +16,6 @@ package com.alibaba.nacos.api.remote.request; - import java.util.HashMap; import java.util.Map; diff --git a/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java b/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java index 2d83a5a52..fad43fc4c 100644 --- a/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java +++ b/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java @@ -17,7 +17,6 @@ package com.alibaba.nacos.client.config.impl; import com.alibaba.nacos.api.PropertyKeyConst; -import com.alibaba.nacos.api.ability.ClientAbilities; import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.common.Constants; import com.alibaba.nacos.api.config.ConfigType; diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java index 3a5d1bff9..c4107c480 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java @@ -16,7 +16,6 @@ package com.alibaba.nacos.common.remote.client; -import com.alibaba.nacos.api.ability.ClientAbilities; import com.alibaba.nacos.api.ability.constant.AbilityStatus; import com.alibaba.nacos.api.ability.entity.AbilityTable; import com.alibaba.nacos.api.common.Constants; diff --git a/core/src/main/java/com/alibaba/nacos/core/cluster/ServerMemberManager.java b/core/src/main/java/com/alibaba/nacos/core/cluster/ServerMemberManager.java index d90653996..3c4e28b19 100644 --- a/core/src/main/java/com/alibaba/nacos/core/cluster/ServerMemberManager.java +++ b/core/src/main/java/com/alibaba/nacos/core/cluster/ServerMemberManager.java @@ -60,6 +60,7 @@ import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.concurrent.ConcurrentSkipListMap; +import com.alibaba.nacos.core.ability.control.ServerAbilityControlManager; /** * Cluster node management in Nacos. @@ -176,7 +177,7 @@ public class ServerMemberManager implements ApplicationListener Date: Tue, 30 Aug 2022 21:36:24 +0800 Subject: [PATCH 10/55] Remove the AbilityHandlePreProcessor and AbilityStatus. Change the way to get or remove AbilityTable for RpcClient. --- .../api/ability/constant/AbilityStatus.java | 46 ------ .../ability/ClientAbilityControlManager.java | 12 -- .../client/config/impl/ClientWorker.java | 5 +- .../gprc/redo/NamingGrpcRedoService.java | 5 +- .../client/naming/remote/TestConnection.java | 36 +++++ .../gprc/redo/NamingGrpcRedoServiceTest.java | 8 +- .../AbstractAbilityControlManager.java | 149 +----------------- .../ability/discover/AbilityHandleLoader.java | 49 ------ .../discover/NacosAbilityManagerHolder.java | 3 - .../handler/AbilityHandlePreProcessor.java | 36 ----- .../ability/inter/AbilityControlManager.java | 9 -- .../inter/TraceableAbilityControlManager.java | 44 ------ .../listener/ClientAbilityEventListener.java | 24 +++ .../client/ConnectionEventListener.java | 8 +- .../nacos/common/remote/client/RpcClient.java | 105 +++--------- .../common/remote/client/grpc/GrpcClient.java | 11 +- .../control/ServerAbilityControlManager.java | 12 -- .../ability/AbilityControlManagerTest.java | 58 +------ 18 files changed, 116 insertions(+), 504 deletions(-) delete mode 100644 api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityStatus.java create mode 100644 client/src/test/java/com/alibaba/nacos/client/naming/remote/TestConnection.java delete mode 100644 common/src/main/java/com/alibaba/nacos/common/ability/discover/AbilityHandleLoader.java delete mode 100644 common/src/main/java/com/alibaba/nacos/common/ability/handler/AbilityHandlePreProcessor.java delete mode 100644 common/src/main/java/com/alibaba/nacos/common/ability/inter/TraceableAbilityControlManager.java create mode 100644 common/src/main/java/com/alibaba/nacos/common/ability/listener/ClientAbilityEventListener.java diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityStatus.java b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityStatus.java deleted file mode 100644 index 825e99a0a..000000000 --- a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityStatus.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 1999-2022 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.nacos.api.ability.constant; - -/**. - * @author Daydreamer - * @description This enum is used to track the status of the ability table. - * @date 2022/7/13 14:11 - **/ -public enum AbilityStatus { - - /** - * It means that the ability table does not exist in the current node. - */ - NOT_EXIST, - - /** - * It means that current node has received the ability table and the table is initializing by AbilityPostProcessor. - */ - INITIALIZING, - - /** - * It means that the ability table is ready. - */ - READY, - - /** - * It means that the ability table will be removed soon. - */ - EXPIRED - -} diff --git a/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java b/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java index 0f3a6fcbe..9d39574f8 100644 --- a/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java +++ b/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java @@ -16,7 +16,6 @@ package com.alibaba.nacos.client.ability; -import com.alibaba.nacos.api.ability.constant.AbilityStatus; import com.alibaba.nacos.api.ability.entity.AbilityTable; import com.alibaba.nacos.common.ability.AbstractAbilityControlManager; import com.alibaba.nacos.common.ability.DefaultAbilityControlManager; @@ -41,17 +40,6 @@ public class ClientAbilityControlManager extends DefaultAbilityControlManager { return false; } AbilityTable abilityTable = nodeAbilityTable.get(connectionId); - // it is null, check if initialing - if (abilityTable == null && AbilityStatus.INITIALIZING.equals(trace(connectionId))) { - // wait for ready - boolean finish = traceReadySyn(connectionId); - // if expired - if (!finish) { - return false; - } else { - abilityTable = nodeAbilityTable.get(connectionId); - } - } // false if null return abilityTable != null && Optional.ofNullable(abilityTable.getAbility()) diff --git a/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java b/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java index fad43fc4c..fc450b990 100644 --- a/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java +++ b/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java @@ -37,6 +37,7 @@ import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.remote.RemoteConstants; import com.alibaba.nacos.api.remote.request.Request; import com.alibaba.nacos.api.remote.response.Response; +import com.alibaba.nacos.common.remote.client.Connection; import com.alibaba.nacos.plugin.auth.api.RequestResource; import com.alibaba.nacos.client.config.common.GroupKey; import com.alibaba.nacos.client.config.filter.impl.ConfigFilterChainManager; @@ -629,13 +630,13 @@ public class ClientWorker implements Closeable { rpcClientInner.registerConnectionListener(new ConnectionEventListener() { @Override - public void onConnected() { + public void onConnected(Connection connection) { LOGGER.info("[{}] Connected,notify listen context...", rpcClientInner.getName()); notifyListenConfig(); } @Override - public void onDisConnect() { + public void onDisConnect(Connection connection) { String taskId = rpcClientInner.getLabels().get("taskId"); LOGGER.info("[{}] DisConnected,clear listen context...", rpcClientInner.getName()); Collection values = cacheMap.get().values(); diff --git a/client/src/main/java/com/alibaba/nacos/client/naming/remote/gprc/redo/NamingGrpcRedoService.java b/client/src/main/java/com/alibaba/nacos/client/naming/remote/gprc/redo/NamingGrpcRedoService.java index 4b68b6e3b..d715a3578 100644 --- a/client/src/main/java/com/alibaba/nacos/client/naming/remote/gprc/redo/NamingGrpcRedoService.java +++ b/client/src/main/java/com/alibaba/nacos/client/naming/remote/gprc/redo/NamingGrpcRedoService.java @@ -25,6 +25,7 @@ import com.alibaba.nacos.client.naming.remote.gprc.redo.data.InstanceRedoData; import com.alibaba.nacos.client.naming.remote.gprc.redo.data.SubscriberRedoData; import com.alibaba.nacos.client.utils.LogUtils; import com.alibaba.nacos.common.executor.NameThreadFactory; +import com.alibaba.nacos.common.remote.client.Connection; import com.alibaba.nacos.common.remote.client.ConnectionEventListener; import java.util.HashSet; @@ -73,13 +74,13 @@ public class NamingGrpcRedoService implements ConnectionEventListener { } @Override - public void onConnected() { + public void onConnected(Connection connection) { connected = true; LogUtils.NAMING_LOGGER.info("Grpc connection connect"); } @Override - public void onDisConnect() { + public void onDisConnect(Connection connection) { connected = false; LogUtils.NAMING_LOGGER.warn("Grpc connection disconnect, mark to redo"); synchronized (registeredInstances) { diff --git a/client/src/test/java/com/alibaba/nacos/client/naming/remote/TestConnection.java b/client/src/test/java/com/alibaba/nacos/client/naming/remote/TestConnection.java new file mode 100644 index 000000000..6d02c962d --- /dev/null +++ b/client/src/test/java/com/alibaba/nacos/client/naming/remote/TestConnection.java @@ -0,0 +1,36 @@ +package com.alibaba.nacos.client.naming.remote; + +import com.alibaba.nacos.api.exception.NacosException; +import com.alibaba.nacos.api.remote.RequestCallBack; +import com.alibaba.nacos.api.remote.RequestFuture; +import com.alibaba.nacos.api.remote.request.Request; +import com.alibaba.nacos.api.remote.response.Response; +import com.alibaba.nacos.common.remote.client.Connection; +import com.alibaba.nacos.common.remote.client.RpcClient; + +public class TestConnection extends Connection { + + public TestConnection(RpcClient.ServerInfo serverInfo) { + super(serverInfo); + } + + @Override + public Response request(Request request, long timeoutMills) throws NacosException { + return null; + } + + @Override + public RequestFuture requestFuture(Request request) throws NacosException { + return null; + } + + @Override + public void asyncRequest(Request request, RequestCallBack requestCallBack) throws NacosException { + + } + + @Override + public void close() { + + } +} diff --git a/client/src/test/java/com/alibaba/nacos/client/naming/remote/gprc/redo/NamingGrpcRedoServiceTest.java b/client/src/test/java/com/alibaba/nacos/client/naming/remote/gprc/redo/NamingGrpcRedoServiceTest.java index 150ff5d87..cc204b401 100644 --- a/client/src/test/java/com/alibaba/nacos/client/naming/remote/gprc/redo/NamingGrpcRedoServiceTest.java +++ b/client/src/test/java/com/alibaba/nacos/client/naming/remote/gprc/redo/NamingGrpcRedoServiceTest.java @@ -17,10 +17,12 @@ package com.alibaba.nacos.client.naming.remote.gprc.redo; import com.alibaba.nacos.api.naming.pojo.Instance; +import com.alibaba.nacos.client.naming.remote.TestConnection; import com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy; import com.alibaba.nacos.client.naming.remote.gprc.redo.data.BatchInstanceRedoData; import com.alibaba.nacos.client.naming.remote.gprc.redo.data.InstanceRedoData; import com.alibaba.nacos.client.naming.remote.gprc.redo.data.SubscriberRedoData; +import com.alibaba.nacos.common.remote.client.RpcClient; import com.alibaba.nacos.common.utils.ReflectUtils; import org.junit.After; import org.junit.Before; @@ -68,13 +70,13 @@ public class NamingGrpcRedoServiceTest { @Test public void testOnConnected() { assertFalse(redoService.isConnected()); - redoService.onConnected(); + redoService.onConnected(new TestConnection(new RpcClient.ServerInfo())); assertTrue(redoService.isConnected()); } @Test public void testOnDisConnect() { - redoService.onConnected(); + redoService.onConnected(new TestConnection(new RpcClient.ServerInfo())); redoService.cacheInstanceForRedo(SERVICE, GROUP, new Instance()); redoService.instanceRegistered(SERVICE, GROUP); redoService.cacheSubscriberForRedo(SERVICE, GROUP, CLUSTER); @@ -82,7 +84,7 @@ public class NamingGrpcRedoServiceTest { assertTrue(redoService.isConnected()); assertTrue(redoService.findInstanceRedoData().isEmpty()); assertTrue(redoService.findSubscriberRedoData().isEmpty()); - redoService.onDisConnect(); + redoService.onDisConnect(new TestConnection(new RpcClient.ServerInfo())); assertFalse(redoService.isConnected()); assertFalse(redoService.findInstanceRedoData().isEmpty()); assertFalse(redoService.findSubscriberRedoData().isEmpty()); diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java index 5b616a588..e1723a9e2 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java @@ -17,23 +17,16 @@ package com.alibaba.nacos.common.ability; import com.alibaba.nacos.api.ability.constant.AbilityKey; -import com.alibaba.nacos.api.ability.constant.AbilityStatus; import com.alibaba.nacos.api.ability.entity.AbilityTable; -import com.alibaba.nacos.common.ability.handler.AbilityHandlePreProcessor; -import com.alibaba.nacos.common.ability.inter.TraceableAbilityControlManager; +import com.alibaba.nacos.common.ability.inter.AbilityControlManager; import com.alibaba.nacos.common.notify.Event; import com.alibaba.nacos.common.notify.NotifyCenter; -import com.alibaba.nacos.common.utils.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicReference; -import java.util.concurrent.locks.LockSupport; import java.util.concurrent.locks.ReentrantLock; /**. @@ -42,7 +35,7 @@ import java.util.concurrent.locks.ReentrantLock; * @date 2022/7/12 19:18 **/ @SuppressWarnings("all") -public abstract class AbstractAbilityControlManager implements TraceableAbilityControlManager { +public abstract class AbstractAbilityControlManager implements AbilityControlManager { private static final Logger LOGGER = LoggerFactory.getLogger(AbstractAbilityControlManager.class); @@ -63,17 +56,6 @@ public abstract class AbstractAbilityControlManager implements TraceableAbilityC */ protected final Map nodeAbilityTable = new ConcurrentHashMap<>(); - /**. - * These handlers will be invoke before combine the ability table - */ - private final List abilityHandlePreProcessors = new ArrayList<>(); - - /** - * This map is used to trace the status of ability table. - * Its status should be update after {@link #addNewTable(AbilityTable)} and {@link #removeTable(String)} - */ - protected final Map> abilityStatus = new ConcurrentHashMap<>(); - private final ReentrantLock lockForProcessors = new ReentrantLock(); private final ReentrantLock lockForAbilityTable = new ReentrantLock(); @@ -124,33 +106,18 @@ public abstract class AbstractAbilityControlManager implements TraceableAbilityC if (contains(connectionId)) { return; } - // update status - abilityStatus.put(connectionId, new AtomicReference<>(AbilityStatus.INITIALIZING)); - // handle ability table before joining current node - AbilityTable processed = process(table); // hook method - add(processed); + add(table); // add to node nodeAbilityTable.put(connectionId, table); } finally { lockForAbilityTable.unlock(); } - // update status - AtomicReference abilityStatusAtomicReference = abilityStatus.get(table.getConnectionId()); - if (abilityStatusAtomicReference != null) { - // try one time - // do nothing if AbilityStatus == Expired - // if ready - if(abilityStatusAtomicReference.compareAndSet(AbilityStatus.INITIALIZING, AbilityStatus.READY)) { - // publish event to subscriber - AbilityComeEvent updateEvent = new AbilityComeEvent(); - updateEvent.setConnectionId(table.getConnectionId()); - updateEvent.setTable(table); - NotifyCenter.publishEvent(updateEvent); - } - } else { - LOGGER.warn("[AbiityControlManager] Cannot get connection status after processing ability table, possible reason is that the network is unstable"); - } + // publish event to subscriber + AbilityComeEvent updateEvent = new AbilityComeEvent(); + updateEvent.setConnectionId(table.getConnectionId()); + updateEvent.setTable(table); + NotifyCenter.publishEvent(updateEvent); } /** @@ -171,12 +138,6 @@ public abstract class AbstractAbilityControlManager implements TraceableAbilityC if (!nodeAbilityTable.containsKey(connectionId)) { return; } - nodeAbilityTable.get(connectionId); - // update status - abilityStatus.computeIfPresent(connectionId, (k, v) -> { - v.set(AbilityStatus.EXPIRED); - return v; - }); // hook method remove(connectionId); // remove @@ -184,8 +145,6 @@ public abstract class AbstractAbilityControlManager implements TraceableAbilityC } finally { lockForAbilityTable.unlock(); } - // remove status - abilityStatus.remove(connectionId); // publish event if (removingTable != null) { AbilityExpiredEvent expiredEvent = new AbilityExpiredEvent(); @@ -195,7 +154,6 @@ public abstract class AbstractAbilityControlManager implements TraceableAbilityC } } - /** * Register a new ability table. This is a ThreadSafe method for {@link AbstractAbilityControlManager#remove(String)}. * @@ -221,97 +179,6 @@ public abstract class AbstractAbilityControlManager implements TraceableAbilityC public boolean contains(String connectionId) { return nodeAbilityTable.containsKey(connectionId); } - - - /** - * Get the status of the ability table. - * - * @param connectionId connection id - * @return status of ability table {@link AbilityStatus} - */ - @Override - public AbilityStatus trace(String connectionId) { - if (connectionId == null) { - return AbilityStatus.NOT_EXIST; - } - return abilityStatus.getOrDefault(connectionId, new AtomicReference<>(AbilityStatus.NOT_EXIST)).get(); - } - - /** - * Trace the status of connection if

{@link AbilityStatus#INITIALIZING}

, wake up if

{@link AbilityStatus#READY}

- * It will return if status is

{@link AbilityStatus#EXPIRED}

or

{@link AbilityStatus#NOT_EXIST}

- * - * @param connectionId connection id - * @param source source status - * @param target target status - * @return if success - */ - @Override - public boolean traceReadySyn(String connectionId) { - AbilityStatus source = AbilityStatus.INITIALIZING; - AbilityStatus target = AbilityStatus.READY; - AtomicReference atomicReference = abilityStatus.get(connectionId); - // return if null - if (atomicReference == null || atomicReference.get().equals(AbilityStatus.EXPIRED)) { - return false; - } else if (target == atomicReference.get()) { - return true; - } - // try if status legal - while (!atomicReference.get().equals(target) && atomicReference.get().equals(source)) { - LockSupport.parkNanos(100L); - // if expired - if (atomicReference.get().equals(AbilityStatus.EXPIRED)) { - return false; - } - } - return atomicReference.get().equals(target); - } - - /**. - * Invoking {@link AbilityHandlePreProcessor} - * - * @param source source ability table - * @return result - */ - protected AbilityTable process(AbilityTable source) { - // do nothing if no processor - if (CollectionUtils.isEmpty(abilityHandlePreProcessors)) { - return source; - } - // copy to advoid error process - AbilityTable abilityTable = source; - AbilityTable copy = new AbilityTable(source.getConnectionId(), new HashMap<>(source.getAbility()), source.isServer(), source.getVersion()); - for (AbilityHandlePreProcessor handler : abilityHandlePreProcessors) { - try { - abilityTable = handler.handle(abilityTable); - } catch (Throwable t) { - LOGGER.warn("[AbilityHandlePostProcessor] Failed to invoke {} :{}", - handler.getClass().getSimpleName(), t.getLocalizedMessage()); - // ensure normal operation - abilityTable = copy; - } - } - return abilityTable; - } - - /**. - * They will be invoked before updating ability table, but the order in which - * they are called cannot be guaranteed - * - * @param postProcessor PostProcessor instance - */ - @Override - public void addPostProcessor(AbilityHandlePreProcessor postProcessor) { - lockForProcessors.lock(); - try { - abilityHandlePreProcessors.add(postProcessor); - } finally { - lockForProcessors.unlock(); - LOGGER.info("[AbilityHandlePostProcessor] registry handler: {}", - postProcessor.getClass().getSimpleName()); - } - } /** * Initialize the manager diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/discover/AbilityHandleLoader.java b/common/src/main/java/com/alibaba/nacos/common/ability/discover/AbilityHandleLoader.java deleted file mode 100644 index feb07436a..000000000 --- a/common/src/main/java/com/alibaba/nacos/common/ability/discover/AbilityHandleLoader.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 1999-2022 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.nacos.common.ability.discover; - -import com.alibaba.nacos.common.ability.handler.AbilityHandlePreProcessor; -import com.alibaba.nacos.common.spi.NacosServiceLoader; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Collection; -import java.util.HashSet; - -/**. - * @author Daydreamer - * @description It is spi loader to load {@link AbilityHandlePreProcessor} - * @date 2022/8/25 18:24 - **/ -public class AbilityHandleLoader { - - private final Collection initializers; - - private static final Logger LOGGER = LoggerFactory.getLogger(AbilityHandleLoader.class); - - public AbilityHandleLoader() { - initializers = new HashSet<>(); - for (AbilityHandlePreProcessor preProcessor : NacosServiceLoader.load(AbilityHandlePreProcessor.class)) { - initializers.add(preProcessor); - LOGGER.info("Load {} for AbilityHandlePreProcessor", preProcessor.getClass().getCanonicalName()); - } - } - - public Collection getInitializers() { - return initializers; - } -} diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/discover/NacosAbilityManagerHolder.java b/common/src/main/java/com/alibaba/nacos/common/ability/discover/NacosAbilityManagerHolder.java index fe7a0c760..dc3fe479d 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/discover/NacosAbilityManagerHolder.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/discover/NacosAbilityManagerHolder.java @@ -64,9 +64,6 @@ public class NacosAbilityManagerHolder { abstractAbilityControlManager = clazz; }); LOGGER.info("[AbilityControlManager] Successfully initialize AbilityControlManager"); - // init pre processor - AbilityHandleLoader loader = new AbilityHandleLoader(); - loader.getInitializers().forEach(processor -> abstractAbilityControlManager.addPostProcessor(processor)); } } diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/handler/AbilityHandlePreProcessor.java b/common/src/main/java/com/alibaba/nacos/common/ability/handler/AbilityHandlePreProcessor.java deleted file mode 100644 index 252f81123..000000000 --- a/common/src/main/java/com/alibaba/nacos/common/ability/handler/AbilityHandlePreProcessor.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 1999-2022 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.nacos.common.ability.handler; - -import com.alibaba.nacos.api.ability.entity.AbilityTable; - -/**. - * @author Daydreamer - * @description This handler will should be invoked before ability table joining current node. - * @date 2022/7/12 19:24 - **/ -public interface AbilityHandlePreProcessor { - - /** - * Handling before joining current node. - * - * @param source source ability handler - * @return result table - */ - AbilityTable handle(AbilityTable source); - -} diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityControlManager.java index 15adf7fc9..75aac8893 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityControlManager.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityControlManager.java @@ -18,7 +18,6 @@ package com.alibaba.nacos.common.ability.inter; import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.ability.entity.AbilityTable; -import com.alibaba.nacos.common.ability.handler.AbilityHandlePreProcessor; import java.util.Map; @@ -75,14 +74,6 @@ public interface AbilityControlManager { */ Map getCurrentRunningAbility(); - /**. - * They will be invoked before updating ability table, but the order in which - * they are called cannot be guaranteed - * - * @param postProcessor PostProcessor instance - */ - void addPostProcessor(AbilityHandlePreProcessor postProcessor); - /**. * Initialize the manager */ diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/inter/TraceableAbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/inter/TraceableAbilityControlManager.java deleted file mode 100644 index 6b87b9b38..000000000 --- a/common/src/main/java/com/alibaba/nacos/common/ability/inter/TraceableAbilityControlManager.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 1999-2022 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.nacos.common.ability.inter; - -import com.alibaba.nacos.api.ability.constant.AbilityStatus; - -/**. - * @author Daydreamer - * @description It provides the capability to trace the state of AbilityTable for the {@link AbilityControlManager} - * @date 2022/8/10 23:30 - **/ -public interface TraceableAbilityControlManager extends AbilityControlManager { - - /** - * Get the status of the ability table. - * - * @param connectionId connection id - * @return status of ability table {@link AbilityStatus} - */ - AbilityStatus trace(String connectionId); - - /**. - * Trace the status of connection if {@link AbilityStatus#INITIALIZING}, wake up if {@link AbilityStatus#READY} - * It will return if status is {@link AbilityStatus#EXPIRED} or {@link AbilityStatus#NOT_EXIST} - * - * @param connectionId connection id - * @return if success to {@link AbilityStatus#READY} - */ - boolean traceReadySyn(String connectionId); -} diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/listener/ClientAbilityEventListener.java b/common/src/main/java/com/alibaba/nacos/common/ability/listener/ClientAbilityEventListener.java new file mode 100644 index 000000000..0c2004365 --- /dev/null +++ b/common/src/main/java/com/alibaba/nacos/common/ability/listener/ClientAbilityEventListener.java @@ -0,0 +1,24 @@ +package com.alibaba.nacos.common.ability.listener; + + +import com.alibaba.nacos.common.ability.discover.NacosAbilityManagerHolder; +import com.alibaba.nacos.common.remote.client.Connection; +import com.alibaba.nacos.common.remote.client.ConnectionEventListener; + +/**. + * @author Daydreamer + * @description This listener is used for remove ability table if disconnected. + * @date 2022/8/30 22:00 + **/ +public class ClientAbilityEventListener implements ConnectionEventListener { + + @Override + public void onConnected(Connection connection) { + // nothing to do + } + + @Override + public void onDisConnect(Connection connection) { + NacosAbilityManagerHolder.getInstance().removeTable(connection.getConnectionId()); + } +} diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/ConnectionEventListener.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/ConnectionEventListener.java index f3f15bf24..d411a62a9 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/ConnectionEventListener.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/ConnectionEventListener.java @@ -25,11 +25,15 @@ public interface ConnectionEventListener { /** * notify when connected to server. + * + * @param connection connection has connected */ - public void onConnected(); + public void onConnected(Connection connection); /** * notify when disconnected to server. + * + * @param connection connection has disconnected */ - public void onDisConnect(); + public void onDisConnect(Connection connection); } diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java index c4107c480..9db2e1e84 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java @@ -16,8 +16,6 @@ package com.alibaba.nacos.common.remote.client; -import com.alibaba.nacos.api.ability.constant.AbilityStatus; -import com.alibaba.nacos.api.ability.entity.AbilityTable; import com.alibaba.nacos.api.common.Constants; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.remote.RequestCallBack; @@ -30,8 +28,8 @@ import com.alibaba.nacos.api.remote.response.ClientDetectionResponse; import com.alibaba.nacos.api.remote.response.ConnectResetResponse; import com.alibaba.nacos.api.remote.response.ErrorResponse; import com.alibaba.nacos.api.remote.response.Response; -import com.alibaba.nacos.common.ability.DefaultAbilityControlManager; import com.alibaba.nacos.common.ability.discover.NacosAbilityManagerHolder; +import com.alibaba.nacos.common.ability.listener.ClientAbilityEventListener; import com.alibaba.nacos.common.lifecycle.Closeable; import com.alibaba.nacos.common.remote.ConnectionType; import com.alibaba.nacos.common.remote.PayloadRegistry; @@ -53,7 +51,6 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; -import java.util.concurrent.locks.LockSupport; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -81,8 +78,6 @@ public abstract class RpcClient implements Closeable { private final BlockingQueue reconnectionSignal = new ArrayBlockingQueue<>(1); - protected final BlockingQueue recServerAbilitySignal = new LinkedBlockingQueue<>(); - protected volatile Connection currentConnection; protected Map labels = new HashMap<>(); @@ -191,15 +186,17 @@ public abstract class RpcClient implements Closeable { /** * Notify when client disconnected. + * + * @param connection connection has disconnected */ - protected void notifyDisConnected() { + protected void notifyDisConnected(Connection connection) { if (connectionEventListeners.isEmpty()) { return; } LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Notify disconnected event to listeners", name); for (ConnectionEventListener connectionEventListener : connectionEventListeners) { try { - connectionEventListener.onDisConnect(); + connectionEventListener.onDisConnect(connection); } catch (Throwable throwable) { LoggerUtils.printIfErrorEnabled(LOGGER, "[{}] Notify disconnect listener error, listener = {}", name, connectionEventListener.getClass().getName()); @@ -209,15 +206,17 @@ public abstract class RpcClient implements Closeable { /** * Notify when client new connected. + * + * @param connection connection has connected */ - protected void notifyConnected() { + protected void notifyConnected(Connection connection) { if (connectionEventListeners.isEmpty()) { return; } LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Notify connected event to listeners.", name); for (ConnectionEventListener connectionEventListener : connectionEventListeners) { try { - connectionEventListener.onConnected(); + connectionEventListener.onConnected(connection); } catch (Throwable throwable) { LoggerUtils.printIfErrorEnabled(LOGGER, "[{}] Notify connect listener error, listener = {}", name, connectionEventListener.getClass().getName()); @@ -285,7 +284,10 @@ public abstract class RpcClient implements Closeable { return; } - clientEventExecutor = new ScheduledThreadPoolExecutor(3, r -> { + // add listener to remove expired ability table + registerConnectionListener(new ClientAbilityEventListener()); + + clientEventExecutor = new ScheduledThreadPoolExecutor(2, r -> { Thread t = new Thread(r); t.setName("com.alibaba.nacos.client.remote.worker"); t.setDaemon(true); @@ -299,41 +301,15 @@ public abstract class RpcClient implements Closeable { try { take = eventLinkedBlockingQueue.take(); if (take.isConnected()) { - notifyConnected(); + notifyConnected(take.connection); } else if (take.isDisConnected()) { - notifyDisConnected(); + notifyDisConnected(take.connection); } } catch (Throwable e) { // Do nothing } } }); - - // receive ability table - clientEventExecutor.submit(() -> { - // save server ability table or remove - while (!clientEventExecutor.isTerminated() && !clientEventExecutor.isShutdown()) { - try { - RecServerAbilityContext take = recServerAbilitySignal.take(); - // avoid interrupted should not null - if (take != null) { - DefaultAbilityControlManager manager = NacosAbilityManagerHolder.getInstance(); - // remove - manager.removeTable(take.oldConnectionId); - // and add - manager.addNewTable( - new AbilityTable() - .setAbility(take.abilityTable) - .setConnectionId(take.connectionId) - .setVersion(take.version) - .setServer(true) - ); - } - } catch (InterruptedException e) { - // do nothing - } - } - }); clientEventExecutor.submit(() -> { while (true) { @@ -427,30 +403,12 @@ public abstract class RpcClient implements Closeable { } - // try to wait for the ability table to be added, but it will check three time at most - AbilityStatus status = AbilityStatus.NOT_EXIST; - int reCheckTimes = RETRY_TIMES; - while (!isShutdown() && connectToServer != null && status.equals(AbilityStatus.NOT_EXIST) && reCheckTimes > 0) { - LockSupport.parkNanos(100L); - status = NacosAbilityManagerHolder.getInstance().trace(connectToServer.getConnectionId()); - reCheckTimes--; - } - - // judge whether support ability table - // wait to get ability table if initializing, it will pass if server doesn't support ability table or table ready - boolean connected = true; - while (!isShutdown() && connectToServer != null && AbilityStatus.INITIALIZING.equals(status) && connected) { - // wait for complete - // return false if disconnect - connected = NacosAbilityManagerHolder.getInstance().traceReadySyn(connectToServer.getConnectionId()); - } - if (connectToServer != null) { LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Success to connect to server [{}] on start up, connectionId = {}", name, connectToServer.serverInfo.getAddress(), connectToServer.getConnectionId()); this.currentConnection = connectToServer; rpcClientStatus.set(RpcClientStatus.RUNNING); - eventLinkedBlockingQueue.offer(new ConnectionEvent(ConnectionEvent.CONNECTED)); + eventLinkedBlockingQueue.offer(new ConnectionEvent(ConnectionEvent.CONNECTED, currentConnection)); } else { switchServerAsync(); } @@ -576,28 +534,6 @@ public abstract class RpcClient implements Closeable { LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Success to connect a server [{}], connectionId = {}", name, serverInfo.getAddress(), connectionNew.getConnectionId()); - // try to wait for the ability table to be added, but it will check three time at most - AbilityStatus status = AbilityStatus.NOT_EXIST; - int reCheckTimes = RETRY_TIMES; - while (status.equals(AbilityStatus.NOT_EXIST) && reCheckTimes > 0) { - LockSupport.parkNanos(100L); - status = NacosAbilityManagerHolder.getInstance().trace(connectionNew.getConnectionId()); - reCheckTimes--; - } - - // judge whether support ability table - // wait to get ability table if initializing, it will pass if server doesn't support ability table or table ready - boolean connected = true; - while (!isShutdown() && AbilityStatus.INITIALIZING.equals(status) && connected) { - // wait for complete - // return false if disconnect - connected = NacosAbilityManagerHolder.getInstance() - .traceReadySyn(connectionNew.getConnectionId()); - } - - LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Success to get server ability table, connectionId = {}", - name, connectionNew.getConnectionId()); - // successfully create a new connect if (currentConnection != null) { LoggerUtils.printIfInfoEnabled(LOGGER, @@ -610,7 +546,7 @@ public abstract class RpcClient implements Closeable { currentConnection = connectionNew; rpcClientStatus.set(RpcClientStatus.RUNNING); switchSuccess = true; - eventLinkedBlockingQueue.add(new ConnectionEvent(ConnectionEvent.CONNECTED)); + eventLinkedBlockingQueue.add(new ConnectionEvent(ConnectionEvent.CONNECTED, currentConnection)); return; } @@ -671,7 +607,7 @@ public abstract class RpcClient implements Closeable { if (connection != null) { LOGGER.info("Close current connection " + connection.getConnectionId()); connection.close(); - eventLinkedBlockingQueue.add(new ConnectionEvent(ConnectionEvent.DISCONNECTED)); + eventLinkedBlockingQueue.add(new ConnectionEvent(ConnectionEvent.DISCONNECTED, connection)); } } @@ -1076,8 +1012,11 @@ public abstract class RpcClient implements Closeable { int eventType; - public ConnectionEvent(int eventType) { + Connection connection; + + public ConnectionEvent(int eventType, Connection connection) { this.eventType = eventType; + this.connection = connection; } public boolean isConnected() { diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java index 0c81caf97..a68c81e58 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java @@ -17,6 +17,7 @@ package com.alibaba.nacos.common.remote.client.grpc; import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.entity.AbilityTable; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.grpc.auto.BiRequestStreamGrpc; import com.alibaba.nacos.api.grpc.auto.Payload; @@ -28,6 +29,7 @@ import com.alibaba.nacos.api.remote.response.ErrorResponse; import com.alibaba.nacos.api.remote.response.Response; import com.alibaba.nacos.api.remote.response.ServerCheckResponse; import com.alibaba.nacos.api.utils.AbilityTableUtils; +import com.alibaba.nacos.common.ability.discover.NacosAbilityManagerHolder; import com.alibaba.nacos.common.remote.ConnectionType; import com.alibaba.nacos.common.remote.client.Connection; import com.alibaba.nacos.common.remote.client.RpcClient; @@ -317,10 +319,11 @@ public abstract class GrpcClient extends RpcClient { ServerCheckResponse serverCheckResponse = (ServerCheckResponse) response; Map abilityTable = AbilityTableUtils .getAbilityTableBy(serverCheckResponse.getAbilities(), AbilityKey.offset()); - String oldConnId = currentConnection == null ? null : currentConnection.getConnectionId(); - RecServerAbilityContext recServerAbilityContext = new RecServerAbilityContext(serverCheckResponse.getConnectionId(), - abilityTable, null, oldConnId); - recServerAbilitySignal.offer(recServerAbilityContext); + AbilityTable table = new AbilityTable(); + table.setServer(true) + .setConnectionId(serverCheckResponse.getConnectionId()) + .setAbility(abilityTable); + NacosAbilityManagerHolder.getInstance().addNewTable(table); BiRequestStreamGrpc.BiRequestStreamStub biRequestStreamStub = BiRequestStreamGrpc .newStub(newChannelStubTemp.getChannel()); diff --git a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java index 09faa79a4..44a01258f 100644 --- a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java +++ b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java @@ -16,7 +16,6 @@ package com.alibaba.nacos.core.ability.control; -import com.alibaba.nacos.api.ability.constant.AbilityStatus; import com.alibaba.nacos.api.ability.entity.AbilityTable; import com.alibaba.nacos.common.JustForTest; import com.alibaba.nacos.common.ability.AbstractAbilityControlManager; @@ -80,17 +79,6 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im return false; } AbilityTable abilityTable = nodeAbilityTable.get(connectionId); - // it is null, check if initialing - if (abilityTable == null && AbilityStatus.INITIALIZING.equals(trace(connectionId))) { - // wait for ready - boolean finish = traceReadySyn(connectionId); - // if expired - if (!finish) { - return false; - } else { - abilityTable = nodeAbilityTable.get(connectionId); - } - } // false if null return abilityTable != null && Optional.ofNullable(abilityTable.getAbility()) diff --git a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityControlManagerTest.java b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityControlManagerTest.java index e27009abe..99d7cced7 100644 --- a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityControlManagerTest.java +++ b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityControlManagerTest.java @@ -16,9 +16,7 @@ package com.alibaba.nacos.test.ability; -import com.alibaba.nacos.api.ability.constant.AbilityStatus; import com.alibaba.nacos.api.ability.entity.AbilityTable; -import com.alibaba.nacos.common.ability.handler.AbilityHandlePreProcessor; import com.alibaba.nacos.common.ability.handler.HandlerMapping; import org.junit.Assert; import org.junit.Before; @@ -118,9 +116,9 @@ public class AbilityControlManagerTest { clientTable.setAbility(clientTa); clientTable.setServer(true); clientAbilityControlManager.addNewTable(clientTable); - Assert.assertEquals(AbilityStatus.READY, clientAbilityControlManager.trace("test-01111")); + Assert.assertTrue(clientAbilityControlManager.contains(clientTable.getConnectionId())); clientAbilityControlManager.removeTable("test-01111"); - Assert.assertEquals(AbilityStatus.NOT_EXIST, clientAbilityControlManager.trace("test-01111")); + Assert.assertFalse(clientAbilityControlManager.contains(clientTable.getConnectionId())); } @Test @@ -214,36 +212,6 @@ public class AbilityControlManagerTest { }); } - @Test - public void testPre() { - clientAbilityControlManager.addPostProcessor(new TestPreHandler()); - clientAbilityControlManager.enableCurrentNodeAbility("stop-raft"); - AbilityTable abilityTable = new AbilityTable(); - abilityTable.setConnectionId("1111"); - HashMap table = new HashMap<>(); - table.put("stop-raft", false); - abilityTable.setAbility(table); - clientAbilityControlManager.addNewTable(abilityTable); - Assert.assertFalse(clientAbilityControlManager.isSupport("1111", "stop-raft")); - } - - @Test - public void testStateSyn() { - // register a processing long time handler - AbilityTable abilityTable = new AbilityTable(); - abilityTable.setConnectionId("1111"); - HashMap table = new HashMap<>(); - table.put("stop-raft", false); - abilityTable.setAbility(table); - clientAbilityControlManager.addPostProcessor(new TestStatusPreHandler()); - // 追踪状态 - long begin = System.currentTimeMillis(); - clientAbilityControlManager.addNewTable(abilityTable); - Assert.assertTrue(clientAbilityControlManager.traceReadySyn("1111")); - long end = System.currentTimeMillis(); - Assert.assertTrue(end - begin > 5000); - } - @Test public void testPriority() throws InterruptedException { TestServerAbilityControlManager testServerAbilityControlManager = new TestServerAbilityControlManager(); @@ -352,29 +320,7 @@ public class AbilityControlManagerTest { } } - - class TestPreHandler implements AbilityHandlePreProcessor { - - @Override - public AbilityTable handle(AbilityTable source) { - source.setConnectionId("pre-handle"); - return source; - } - } - class TestStatusPreHandler implements AbilityHandlePreProcessor { - - @Override - public AbilityTable handle(AbilityTable source) { - try { - // block - Thread.sleep(5000); - } catch (Exception e) { - e.printStackTrace(); - } - return source; - } - } } From 92add6e833d38bac1b0453b081b8f90230911866 Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Wed, 31 Aug 2022 16:59:43 +0800 Subject: [PATCH 11/55] Separate client capability and server capability: ClientAbilities and ServerAbilities. --- .../api/ability/constant/AbilityKey.java | 94 ++---------------- .../api/ability/entity/AbilityTable.java | 11 ++- .../ability/register/AbilityBitOperate.java | 61 ++++++++++++ .../register/impl/ClientAbilities.java | 72 ++++++++++++++ .../register/impl/ServerAbilities.java | 73 ++++++++++++++ .../request/ConnectionSetupRequest.java | 13 +++ .../nacos/api/utils/AbilityTableUtils.java | 13 +-- .../api/utils/AbilityTableUtilsTest.java | 56 ----------- .../ability/ClientAbilityControlManager.java | 11 ++- .../client/config/impl/ClientWorker.java | 7 +- .../AbstractAbilityControlManager.java | 18 +++- .../ability/DefaultAbilityControlManager.java | 51 +++++----- .../ability/inter/AbilityControlManager.java | 9 +- .../ability/inter/AbilityHandlerRegistry.java | 22 +++-- .../nacos/common/remote/client/RpcClient.java | 12 --- .../remote/client/RpcClientFactory.java | 3 +- .../common/remote/client/grpc/GrpcClient.java | 24 ++++- .../remote/client/grpc/GrpcClusterClient.java | 11 +++ .../remote/client/grpc/GrpcSdkClient.java | 11 +++ .../remote/client/grpc/GrpcClientTest.java | 10 ++ .../control/ServerAbilityControlManager.java | 42 ++++---- .../inte/ClusterAbilityControlSupport.java | 18 ++-- .../alibaba/nacos/core/remote/Connection.java | 7 +- .../grpc/GrpcBiStreamRequestAcceptor.java | 14 ++- .../core/remote/grpc/GrpcRequestAcceptor.java | 4 +- .../ability/AbilityControlManagerTest.java | 97 ++++++++++--------- .../TestClientAbilityControlManager.java | 3 +- .../TestServerAbilityControlManager.java | 15 +-- 28 files changed, 472 insertions(+), 310 deletions(-) create mode 100644 api/src/main/java/com/alibaba/nacos/api/ability/register/AbilityBitOperate.java create mode 100644 api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java create mode 100644 api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java delete mode 100644 api/src/test/java/com/alibaba/nacos/api/utils/AbilityTableUtilsTest.java diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java index cf194ccca..71e1e1435 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java @@ -16,96 +16,16 @@ package com.alibaba.nacos.api.ability.constant; -import com.alibaba.nacos.api.utils.AbilityTableUtils; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - /**. * @author Daydreamer - * @description Ability table key. It can be a replacement of {@link com.alibaba.nacos.api.ability.ServerAbilities} - * and {@link com.alibaba.nacos.api.ability.ClientAbilities}. - * @date 2022/7/12 19:23 + * @description Ability key constant. + * @date 2022/8/31 12:27 **/ -@SuppressWarnings("unchecked") -public class AbilityKey { - - private static final HashMap CURRENT_SERVER_SUPPORT_ABILITY = new HashMap<>(); - - private static final HashMap CURRENT_SERVER_ABILITY_OFFSET = new HashMap<>(); - - private static final byte[] ABILITY_BIT_FLAGS; - - private AbilityKey() { - } +public enum AbilityKey { - static { - /* - * example: - * There is a function named "compression". - * The key is "compression", the value is the offset of the flag bit of this ability in the ability table. The value should be unique. - * - * You can add a new public static field like: - * public static final String COMPRESSION = "compression"; - * This field can be used outside. - * - * And then you need to declare the offset of the flag bit of this ability in the ability table, you can: - * CURRENT_SERVER_ABILITY_OFFSET.put("compression", 1); means that is the first bit from left to right in the table. - * - */ - - // put ability here, which you want current server supports - - } + /** + * just for junit test + */ + TEST_1, TEST_2, - /**. - * Return ability table of current node - * But this ability is static which means that this ability table is all function this node supports if no one to ask it to close some functions. - * If you want to get what function current node is supporting, you should call AbilityControlManager#getCurrentAbility - * By the way, AbilityControlManager is singleton, you can get it by static method - * - * @return ability table - */ - public static Map getCurrentNodeSupportAbility() { - return Collections.unmodifiableMap(CURRENT_SERVER_SUPPORT_ABILITY); - } - - /**. - * Return the static ability bit table - * - * @return ability bit table - */ - public static byte[] getAbilityBitFlags() { - return ABILITY_BIT_FLAGS.clone(); - } - - /**. - * Is it a legal key - * - * @param key input - * @return whether a legal key - */ - public static boolean isLegal(String key) { - return CURRENT_SERVER_SUPPORT_ABILITY.containsKey(key); - } - - static { - // init the bits table - ABILITY_BIT_FLAGS = AbilityTableUtils.getAbilityBitBy(CURRENT_SERVER_ABILITY_OFFSET.values()); - // init the ability table, default all true - CURRENT_SERVER_ABILITY_OFFSET.forEach((k, v) -> { - CURRENT_SERVER_SUPPORT_ABILITY.put(k, Boolean.TRUE); - }); - } - - /**. - * Return the ability bit offsets - * - * @return bit offset - */ - public static Map offset() { - return CURRENT_SERVER_ABILITY_OFFSET; - } - } diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/entity/AbilityTable.java b/api/src/main/java/com/alibaba/nacos/api/ability/entity/AbilityTable.java index 921a092a7..67eb663dd 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/entity/AbilityTable.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/entity/AbilityTable.java @@ -17,6 +17,7 @@ package com.alibaba.nacos.api.ability.entity; import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.register.AbilityBitOperate; import java.util.Map; @@ -34,10 +35,10 @@ public class AbilityTable implements Cloneable { /**. * ability table - * key: name from {@link AbilityKey} + * key: name from {@link com.alibaba.nacos.api.ability.constant.AbilityKey} * value: whether to turn on */ - private Map ability; + private Map ability; /**. * whether it from a server node @@ -70,7 +71,7 @@ public class AbilityTable implements Cloneable { return this; } - public AbilityTable(String connectionId, Map ability, boolean isServer, String version) { + public AbilityTable(String connectionId, Map ability, boolean isServer, String version) { this.connectionId = connectionId; this.ability = ability; this.isServer = isServer; @@ -86,11 +87,11 @@ public class AbilityTable implements Cloneable { return this; } - public Map getAbility() { + public Map getAbility() { return ability; } - public AbilityTable setAbility(Map ability) { + public AbilityTable setAbility(Map ability) { this.ability = ability; return this; } diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/register/AbilityBitOperate.java b/api/src/main/java/com/alibaba/nacos/api/ability/register/AbilityBitOperate.java new file mode 100644 index 000000000..e16165e74 --- /dev/null +++ b/api/src/main/java/com/alibaba/nacos/api/ability/register/AbilityBitOperate.java @@ -0,0 +1,61 @@ +/* + * Copyright 1999-2022 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.nacos.api.ability.register; + +import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.utils.AbilityTableUtils; + +import java.util.HashMap; +import java.util.Map; + +/**. + * @author Daydreamer + * @description Operation for bit table. + * @date 2022/7/12 19:23 + **/ +public abstract class AbilityBitOperate { + + protected final HashMap abilityOffset = new HashMap<>(); + + private byte[] abilityBitFlag; + + /**. + * Return the static ability bit table + * + * @return ability bit table + */ + public byte[] getAbilityBitFlags() { + return abilityBitFlag.clone(); + } + + /**. + * Return the ability bit offsets + * + * @return bit offset + */ + public Map offset() { + return abilityOffset; + } + + /** + * put the bit offset to {@link AbilityBitOperate#abilityBitFlag} + */ + protected void init() { + // init the bits table + abilityBitFlag = AbilityTableUtils.getAbilityBitBy(abilityOffset.values()); + } +} diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java new file mode 100644 index 000000000..ba1a7496d --- /dev/null +++ b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java @@ -0,0 +1,72 @@ +/* + * Copyright 1999-2022 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.nacos.api.ability.register.impl; + +import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.register.AbilityBitOperate; + +import java.util.Map; + +/**. + * @author Daydreamer + * @description It is used to register client abilities. + * @date 2022/8/31 12:32 + **/ +public class ClientAbilities extends AbilityBitOperate { + + private static final ClientAbilities INSTANCE = new ClientAbilities(); + + { + /* + * example: + * There is a function named "compression". + * The key is "compression", the value is the offset of the flag bit of this ability in the ability table. The value should be unique. + * + * You can add a new public static field in

AbilityKeyConstant

like: + * public static final String COMPRESSION = "compression"; + * This field can be used outside. + * + * And then you need to declare the offset of the flag bit of this ability in the ability table, you can: + * abilityOffset.put("compression", 1); means that is the first bit from left to right in the table. + * + */ + // put ability here, which you want current server supports + } + + private ClientAbilities() { + // put key to bit offset + init(); + } + + /** + * get the ability offset for server + * + * @return ability offset + */ + public static byte[] getBitFlags() { + return INSTANCE.getAbilityBitFlags(); + } + + /** + * get the ability offset for server + * + * @return ability offset + */ + public static Map getOffset() { + return INSTANCE.offset(); + } +} diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java new file mode 100644 index 000000000..842591587 --- /dev/null +++ b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java @@ -0,0 +1,73 @@ +/* + * Copyright 1999-2022 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.nacos.api.ability.register.impl; + +import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.register.AbilityBitOperate; + +import java.util.Map; + +/**. + * @author Daydreamer + * @description It is used to register server abilities. + * @date 2022/8/31 12:32 + **/ +public class ServerAbilities extends AbilityBitOperate { + + private static final ServerAbilities INSTANCE = new ServerAbilities(); + + { + /* + * example: + * There is a function named "compression". + * The key is "compression", the value is the offset of the flag bit of this ability in the ability table. The value should be unique. + * + * You can add a new public static field like: + * public static final String COMPRESSION = "compression"; + * This field can be used outside. + * + * And then you need to declare the offset of the flag bit of this ability in the ability table, you can: + * CURRENT_SERVER_ABILITY_OFFSET.put("compression", 1); means that is the first bit from left to right in the table. + * + */ + // put ability here, which you want current server supports + } + + private ServerAbilities() { + // put key to bit offset + init(); + } + + /** + * get bit table + * + * @return ability offset + */ + public static byte[] getBitFlags() { + return INSTANCE.getAbilityBitFlags(); + } + + /** + * get the ability offset for server + * + * @return ability offset + */ + public static Map getOffset() { + return INSTANCE.offset(); + } + +} diff --git a/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequest.java b/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequest.java index 046a897a4..d2fbd704a 100644 --- a/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequest.java +++ b/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequest.java @@ -35,6 +35,19 @@ public class ConnectionSetupRequest extends InternalRequest { private byte[] abilityTable; + /** + * server will resolve {@link ConnectionSetupRequest#abilityTable} to server abilities, or to client abilities + */ + private boolean isServer; + + public boolean isServer() { + return isServer; + } + + public void setServer(boolean server) { + isServer = server; + } + public ConnectionSetupRequest() { } diff --git a/api/src/main/java/com/alibaba/nacos/api/utils/AbilityTableUtils.java b/api/src/main/java/com/alibaba/nacos/api/utils/AbilityTableUtils.java index 11ad28cc0..aa74be70d 100644 --- a/api/src/main/java/com/alibaba/nacos/api/utils/AbilityTableUtils.java +++ b/api/src/main/java/com/alibaba/nacos/api/utils/AbilityTableUtils.java @@ -17,6 +17,7 @@ package com.alibaba.nacos.api.utils; import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.register.AbilityBitOperate; import java.util.Collection; import java.util.Collections; @@ -67,18 +68,18 @@ public class AbilityTableUtils { * get ability table by bits * * @param bits bit flag - * @param offsetMap offset from {@link AbilityKey} + * @param offsetMap offset from {@link AbilityBitOperate} * @return Return the Map containing AbilityTableKey and isRunning. */ - public static Map getAbilityTableBy(byte[] bits, Map offsetMap) { + public static Map getAbilityTableBy(byte[] bits, Map offsetMap) { if (bits == null || offsetMap.size() == 0) { return Collections.emptyMap(); } int length = bits.length; - Set> entries = offsetMap.entrySet(); - Map res = new HashMap<>(offsetMap.size()); - for (Map.Entry entry : entries) { - String abilityKey = entry.getKey(); + Set> entries = offsetMap.entrySet(); + Map res = new HashMap<>(offsetMap.size()); + for (Map.Entry entry : entries) { + AbilityKey abilityKey = entry.getKey(); Integer offset = entry.getValue(); // if not exists int index = offset / 8 + (offset % 8 == 0 ? -1 : 0); diff --git a/api/src/test/java/com/alibaba/nacos/api/utils/AbilityTableUtilsTest.java b/api/src/test/java/com/alibaba/nacos/api/utils/AbilityTableUtilsTest.java deleted file mode 100644 index c2fea2c40..000000000 --- a/api/src/test/java/com/alibaba/nacos/api/utils/AbilityTableUtilsTest.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 1999-2022 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.nacos.api.utils; - -import org.junit.Assert; -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - -public class AbilityTableUtilsTest { - - @Test - public void testGetByteArray() { - Map offset = new HashMap<>(); - offset.put("a", 1); - offset.put("b", 2); - offset.put("c", 10); - offset.put("d", 127); - byte[] abilityBitBy = AbilityTableUtils.getAbilityBitBy(offset.values()); - Assert.assertEquals(16, abilityBitBy.length); - Assert.assertEquals((byte) (3 << 6), abilityBitBy[0]); - Assert.assertEquals((byte) (1 << 6), abilityBitBy[1]); - } - - @Test - public void testGetAbilityTable() { - Map offset = new HashMap<>(); - offset.put("a", 1); - offset.put("b", 2); - offset.put("c", 10); - offset.put("d", 127); - byte[] abilityBitBy = AbilityTableUtils.getAbilityBitBy(offset.values()); - Map abilityTableBy = AbilityTableUtils.getAbilityTableBy(abilityBitBy, offset); - Assert.assertEquals(4, abilityTableBy.size()); - Assert.assertEquals(Boolean.TRUE, abilityTableBy.get("a")); - Assert.assertEquals(Boolean.TRUE, abilityTableBy.get("b")); - Assert.assertEquals(Boolean.TRUE, abilityTableBy.get("c")); - Assert.assertEquals(Boolean.TRUE, abilityTableBy.get("d")); - Assert.assertEquals(Boolean.FALSE, abilityTableBy.getOrDefault("asdasd", false)); - } -} diff --git a/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java b/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java index 9d39574f8..9e859b3b2 100644 --- a/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java +++ b/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java @@ -16,11 +16,15 @@ package com.alibaba.nacos.client.ability; +import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.ability.entity.AbilityTable; +import com.alibaba.nacos.api.ability.register.impl.ClientAbilities; +import com.alibaba.nacos.api.utils.AbilityTableUtils; import com.alibaba.nacos.common.ability.AbstractAbilityControlManager; import com.alibaba.nacos.common.ability.DefaultAbilityControlManager; import java.util.Collections; +import java.util.Map; import java.util.Optional; /**. @@ -34,7 +38,12 @@ public class ClientAbilityControlManager extends DefaultAbilityControlManager { } @Override - public boolean isSupport(String connectionId, String abilityKey) { + protected Map getCurrentNodeSupportAbility() { + return AbilityTableUtils.getAbilityTableBy(ClientAbilities.getBitFlags(), ClientAbilities.getOffset()); + } + + @Override + public boolean isSupport(String connectionId, AbilityKey abilityKey) { Boolean isRunning = currentRunningAbility.getOrDefault(abilityKey, false); if (!isRunning) { return false; diff --git a/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java b/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java index fc450b990..d56b23a7c 100644 --- a/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java +++ b/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java @@ -17,7 +17,7 @@ package com.alibaba.nacos.client.config.impl; import com.alibaba.nacos.api.PropertyKeyConst; -import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.register.AbilityBitOperate; import com.alibaba.nacos.api.common.Constants; import com.alibaba.nacos.api.config.ConfigType; import com.alibaba.nacos.api.config.listener.Listener; @@ -885,7 +885,6 @@ public class ClientWorker implements Closeable { if (rpcClient.isWaitInitiated()) { initRpcClientHandler(rpcClient); rpcClient.setTenant(getTenant()); - rpcClient.clientAbilities(initAbilities()); rpcClient.start(); } @@ -893,10 +892,6 @@ public class ClientWorker implements Closeable { } } - - private byte[] initAbilities() { - return AbilityKey.getAbilityBitFlags(); - } /** * build config string. diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java index e1723a9e2..c72e6a9e2 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java @@ -17,6 +17,7 @@ package com.alibaba.nacos.common.ability; import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.register.AbilityBitOperate; import com.alibaba.nacos.api.ability.entity.AbilityTable; import com.alibaba.nacos.common.ability.inter.AbilityControlManager; import com.alibaba.nacos.common.notify.Event; @@ -43,10 +44,10 @@ public abstract class AbstractAbilityControlManager implements AbilityControlMan /** * Abilities current supporting *

- * key: ability key from {@link AbilityKey} + * key: ability key from {@link AbilityBitOperate} * value: whether to turn on */ - protected final Map currentRunningAbility = new ConcurrentHashMap<>(); + protected final Map currentRunningAbility = new ConcurrentHashMap<>(); /** * Ability table collections @@ -64,10 +65,17 @@ public abstract class AbstractAbilityControlManager implements AbilityControlMan // register events registerAbilityEvent(); // put abilities - currentRunningAbility.putAll(AbilityKey.getCurrentNodeSupportAbility()); + currentRunningAbility.putAll(getCurrentNodeSupportAbility()); // initialize init(); } + + /** + * This is a hook for subclass to init current node ability + * + * @return current node ability + */ + protected abstract Map getCurrentNodeSupportAbility(); private void registerAbilityEvent(){ @@ -83,7 +91,7 @@ public abstract class AbstractAbilityControlManager implements AbilityControlMan * @return is running */ @Override - public boolean isCurrentNodeAbilityRunning(String abilityKey) { + public boolean isCurrentNodeAbilityRunning(AbilityKey abilityKey) { return currentRunningAbility.getOrDefault(abilityKey, false); } @@ -204,7 +212,7 @@ public abstract class AbstractAbilityControlManager implements AbilityControlMan * @return ability table */ @Override - public Map getCurrentRunningAbility() { + public Map getCurrentRunningAbility() { return new HashMap<>(this.currentRunningAbility); } diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/DefaultAbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/DefaultAbilityControlManager.java index b3012392e..9d7dbfe36 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/DefaultAbilityControlManager.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/DefaultAbilityControlManager.java @@ -17,6 +17,7 @@ package com.alibaba.nacos.common.ability; import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.register.AbilityBitOperate; import com.alibaba.nacos.api.ability.entity.AbilityTable; import com.alibaba.nacos.common.JustForTest; import com.alibaba.nacos.common.ability.handler.HandlerMapping; @@ -52,10 +53,10 @@ public abstract class DefaultAbilityControlManager extends AbstractAbilityContro private static final Logger LOGGER = LoggerFactory.getLogger(DefaultAbilityControlManager.class); /** - * . These handlers will be invoked when the flag of ability change key: ability key from {@link AbilityKey} value: - * componments who want to be invoked if its interested ability turn on/off + * These handlers will be invoked when the flag of ability change key: ability key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey} value: + * components who want to be invoked if its interested ability turn on/off */ - private final Map> handlerMappings = new ConcurrentHashMap<>(); + private final Map> handlerMappings = new ConcurrentHashMap<>(); /**. * run for HandlerMapping @@ -76,7 +77,7 @@ public abstract class DefaultAbilityControlManager extends AbstractAbilityContro * @return if turn success */ @Override - public boolean enableCurrentNodeAbility(String abilityKey) { + public boolean enableCurrentNodeAbility(AbilityKey abilityKey) { return doTurn(true, abilityKey); } @@ -87,7 +88,7 @@ public abstract class DefaultAbilityControlManager extends AbstractAbilityContro * @return if turn success */ @Override - public boolean disableCurrentNodeAbility(String abilityKey) { + public boolean disableCurrentNodeAbility(AbilityKey abilityKey) { return doTurn(false, abilityKey); } @@ -98,7 +99,7 @@ public abstract class DefaultAbilityControlManager extends AbstractAbilityContro * @param abilityKey ability key from {@link AbilityKey} * @return if turn success */ - private boolean doTurn(boolean isOn, String abilityKey) { + private boolean doTurn(boolean isOn, AbilityKey abilityKey) { Boolean isEnabled = currentRunningAbility.get(abilityKey); // if not supporting this key if (isEnabled == null) { @@ -130,12 +131,12 @@ public abstract class DefaultAbilityControlManager extends AbstractAbilityContro * @param handlerMapping component instance. */ @Override - public void registerComponent(String abilityKey, HandlerMapping handlerMapping, int priority) { + public void registerComponent(AbilityKey abilityKey, HandlerMapping handlerMapping, int priority) { doRegisterComponent(abilityKey, handlerMapping, this.handlerMappings, lockForHandlerMappings, priority, currentRunningAbility); } @Override - public int removeComponent(String abilityKey, Class handlerMappingClazz) { + public int removeComponent(AbilityKey abilityKey, Class handlerMappingClazz) { return doRemove(abilityKey, handlerMappingClazz, lockForHandlerMappings, handlerMappings); } @@ -161,14 +162,14 @@ public abstract class DefaultAbilityControlManager extends AbstractAbilityContro /** * Remove the component instance of

handlerMappingClazz

. * - * @param abilityKey ability key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey} + * @param abilityKey ability key from {@link AbilityBitOperate} * @param handlerMappingClazz implement of {@link HandlerMapping} * @param lock lock for operation * @param handlerMappingsMap handler collection map * @return the count of components have removed */ - protected int doRemove(String abilityKey, Class handlerMappingClazz, Lock lock, - Map> handlerMappingsMap) { + protected int doRemove(AbilityKey abilityKey, Class handlerMappingClazz, Lock lock, + Map> handlerMappingsMap) { List handlerMappings = handlerMappingsMap.get(abilityKey); if (CollectionUtils.isEmpty(handlerMappings)) { return 0; @@ -190,7 +191,7 @@ public abstract class DefaultAbilityControlManager extends AbstractAbilityContro } @Override - public int removeAll(String abilityKey) { + public int removeAll(AbilityKey abilityKey) { List remove = this.handlerMappings.remove(abilityKey); return Optional.ofNullable(remove).orElse(Collections.emptyList()).size(); } @@ -204,9 +205,9 @@ public abstract class DefaultAbilityControlManager extends AbstractAbilityContro * @param lockForHandlerMappings lock to ensure concurrency * @param abilityTable behavioral basis of handler */ - protected void doRegisterComponent(String abilityKey, HandlerMapping handlerMapping, - Map> handlerMappings, Lock lockForHandlerMappings, - int priority, Map abilityTable) { + protected void doRegisterComponent(AbilityKey abilityKey, HandlerMapping handlerMapping, + Map> handlerMappings, Lock lockForHandlerMappings, + int priority, Map abilityTable) { if (!currentRunningAbility.containsKey(abilityKey)) { LOGGER.warn("[AbilityHandlePostProcessor] Failed to register processor: {}, because illegal key!", handlerMapping.getClass().getSimpleName()); @@ -239,24 +240,24 @@ public abstract class DefaultAbilityControlManager extends AbstractAbilityContro /** * Invoke componments which linked to ability key asyn. * - * @param key ability key from {@link AbilityKey} + * @param key ability key from {@link AbilityBitOperate} * @param isEnabled turn on/off * @param handlerMappingsMap handler collection */ - protected void triggerHandlerMappingAsyn(String key, boolean isEnabled, - Map> handlerMappingsMap) { + protected void triggerHandlerMappingAsyn(AbilityKey key, boolean isEnabled, + Map> handlerMappingsMap) { simpleThreadPool.execute(() -> doTriggerSyn(key, isEnabled, handlerMappingsMap)); } /** * Invoke componments which linked to ability key syn. * - * @param key ability key from {@link AbilityKey} + * @param key ability key from {@link AbilityBitOperate} * @param isEnabled turn on/off * @param handlerMappingsMap handler collection */ - protected void doTriggerSyn(String key, boolean isEnabled, - Map> handlerMappingsMap) { + protected void doTriggerSyn(AbilityKey key, boolean isEnabled, + Map> handlerMappingsMap) { List handlerWithPriorities = handlerMappingsMap.get(key); // return if empty if (CollectionUtils.isEmpty(handlerWithPriorities)) { @@ -281,7 +282,7 @@ public abstract class DefaultAbilityControlManager extends AbstractAbilityContro } @JustForTest - protected Map> handlerMapping() { + protected Map> handlerMapping() { return this.handlerMappings; } @@ -318,17 +319,17 @@ public abstract class DefaultAbilityControlManager extends AbstractAbilityContro private static final long serialVersionUID = -1232411212311111L; - private String abilityKey; + private AbilityKey abilityKey; private boolean isOn; private AbilityUpdateEvent(){} - public String getAbilityKey() { + public AbilityKey getAbilityKey() { return abilityKey; } - public void setAbilityKey(String abilityKey) { + public void setAbilityKey(AbilityKey abilityKey) { this.abilityKey = abilityKey; } diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityControlManager.java index 75aac8893..22bbfd85a 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityControlManager.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityControlManager.java @@ -17,6 +17,7 @@ package com.alibaba.nacos.common.ability.inter; import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.register.AbilityBitOperate; import com.alibaba.nacos.api.ability.entity.AbilityTable; import java.util.Map; @@ -32,10 +33,10 @@ public interface AbilityControlManager { * Whether the ability is supported for Connection. If the ability of current node is closed, it will return false. * * @param connectionId the connection range of ability table. - * @param abilityKey key name which comes from {@link AbilityKey}. + * @param abilityKey key name which comes from {@link AbilityBitOperate}. * @return whether the ability is supported in certain connection. */ - boolean isSupport(String connectionId, String abilityKey); + boolean isSupport(String connectionId, AbilityKey abilityKey); /** * Whether the ability current node supporting is running. Return false if current node doesn't support. @@ -43,7 +44,7 @@ public interface AbilityControlManager { * @param abilityKey ability key * @return is running */ - boolean isCurrentNodeAbilityRunning(String abilityKey); + boolean isCurrentNodeAbilityRunning(AbilityKey abilityKey); /** * Register a new ability table. @@ -72,7 +73,7 @@ public interface AbilityControlManager { * * @return ability table */ - Map getCurrentRunningAbility(); + Map getCurrentRunningAbility(); /**. * Initialize the manager diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityHandlerRegistry.java b/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityHandlerRegistry.java index c27254784..77d2e847c 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityHandlerRegistry.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityHandlerRegistry.java @@ -16,6 +16,8 @@ package com.alibaba.nacos.common.ability.inter; +import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.register.AbilityBitOperate; import com.alibaba.nacos.common.ability.AbstractAbilityControlManager; import com.alibaba.nacos.common.ability.handler.HandlerMapping; @@ -32,7 +34,7 @@ public interface AbilityHandlerRegistry { * @param abilityKey ability key * @return if turn success */ - boolean enableCurrentNodeAbility(String abilityKey); + boolean enableCurrentNodeAbility(AbilityKey abilityKey); /**. * Turn off the ability whose key is

abilityKey

@@ -40,42 +42,42 @@ public interface AbilityHandlerRegistry { * @param abilityKey ability key * @return if turn success */ - boolean disableCurrentNodeAbility(String abilityKey); + boolean disableCurrentNodeAbility(AbilityKey abilityKey); /**. * Register the component which is managed by {@link AbstractAbilityControlManager}. * if you are hoping that a component will be invoked when turn on/off the ability whose key is

abilityKey

. * - * @param abilityKey component key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey} + * @param abilityKey component key from {@link AbilityBitOperate} * @param priority a positive number, the higher the priority is, the faster it will be called. `1` is the lowest priority. * @param handlerMapping component instance. */ - void registerComponent(String abilityKey, HandlerMapping handlerMapping, int priority); + void registerComponent(AbilityKey abilityKey, HandlerMapping handlerMapping, int priority); /**. * Default method to register component with the lowest priority. * - * @param abilityKey component key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey} + * @param abilityKey component key from {@link AbilityBitOperate} * @param handlerMapping component instance. */ - default void registerComponent(String abilityKey, HandlerMapping handlerMapping) { + default void registerComponent(AbilityKey abilityKey, HandlerMapping handlerMapping) { registerComponent(abilityKey, handlerMapping, 1); } /** * Remove the component instance of

handlerMappingClazz

. * - * @param abilityKey ability key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey} + * @param abilityKey ability key from {@link AbilityBitOperate} * @param handlerMappingClazz implement of {@link HandlerMapping} * @return the count of components have removed */ - int removeComponent(String abilityKey, Class handlerMappingClazz); + int removeComponent(AbilityKey abilityKey, Class handlerMappingClazz); /** * Remove all {@link HandlerMapping} interested in the special ability. - * @param abilityKey abnility key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey} + * @param abilityKey abnility key from {@link AbilityBitOperate} * @return the count of components have removed */ - int removeAll(String abilityKey); + int removeAll(AbilityKey abilityKey); } diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java index 9db2e1e84..59d8134ec 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java @@ -90,8 +90,6 @@ public abstract class RpcClient implements Closeable { private static final long DEFAULT_TIMEOUT_MILLS = 3000L; - protected byte[] clientAbilities; - /** * default keep alive time 5s. */ @@ -133,16 +131,6 @@ public abstract class RpcClient implements Closeable { } } - /** - * init client abilities. - * - * @param clientAbilities clientAbilities. - */ - public RpcClient clientAbilities(byte[] clientAbilities) { - this.clientAbilities = clientAbilities; - return this; - } - /** * init server list factory. only can init once. * diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClientFactory.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClientFactory.java index 8b40c9cfb..8293f0192 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClientFactory.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClientFactory.java @@ -16,7 +16,7 @@ package com.alibaba.nacos.common.remote.client; -import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.register.impl.ServerAbilities; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.common.remote.ConnectionType; import com.alibaba.nacos.common.remote.client.grpc.GrpcClient; @@ -140,7 +140,6 @@ public class RpcClientFactory { client.setThreadPoolCoreSize(threadPoolCoreSize); client.setThreadPoolMaxSize(threadPoolMaxSize); client.labels(labels); - client.clientAbilities(AbilityKey.getAbilityBitFlags()); return client; }); } diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java index a68c81e58..d4c61452e 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java @@ -17,7 +17,9 @@ package com.alibaba.nacos.common.remote.client.grpc; import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.register.AbilityBitOperate; import com.alibaba.nacos.api.ability.entity.AbilityTable; +import com.alibaba.nacos.api.ability.register.impl.ServerAbilities; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.grpc.auto.BiRequestStreamGrpc; import com.alibaba.nacos.api.grpc.auto.Payload; @@ -317,8 +319,8 @@ public abstract class GrpcClient extends RpcClient { // submit ability table as soon as possible // ability table will be null if server doesn't support ability table ServerCheckResponse serverCheckResponse = (ServerCheckResponse) response; - Map abilityTable = AbilityTableUtils - .getAbilityTableBy(serverCheckResponse.getAbilities(), AbilityKey.offset()); + Map abilityTable = AbilityTableUtils + .getAbilityTableBy(serverCheckResponse.getAbilities(), ServerAbilities.getOffset()); AbilityTable table = new AbilityTable(); table.setServer(true) .setConnectionId(serverCheckResponse.getConnectionId()) @@ -341,7 +343,8 @@ public abstract class GrpcClient extends RpcClient { ConnectionSetupRequest conSetupRequest = new ConnectionSetupRequest(); conSetupRequest.setClientVersion(VersionUtils.getFullClientVersion()); conSetupRequest.setLabels(super.getLabels()); - conSetupRequest.setAbilityTable(super.clientAbilities == null ? AbilityKey.getAbilityBitFlags() : clientAbilities); + conSetupRequest.setAbilityTable(getAbilityBit()); + conSetupRequest.setServer(isServer()); conSetupRequest.setTenant(super.getTenant()); grpcConn.sendRequest(conSetupRequest); //wait to register connection setup @@ -355,6 +358,21 @@ public abstract class GrpcClient extends RpcClient { return null; } + /** + * get ability, server or client + * + * @return bit table + */ + protected abstract byte[] getAbilityBit(); + + /** + * Return whether server environment + * The same offset may refer to different functions in the client capability table and the server capability table. + * + * @return whether server environment + */ + protected abstract boolean isServer(); + } diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClusterClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClusterClient.java index 7b63653b6..67cd0cd7c 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClusterClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClusterClient.java @@ -16,6 +16,7 @@ package com.alibaba.nacos.common.remote.client.grpc; +import com.alibaba.nacos.api.ability.register.impl.ServerAbilities; import com.alibaba.nacos.api.common.Constants; /** @@ -35,6 +36,16 @@ public class GrpcClusterClient extends GrpcClient { super(name); } + @Override + public byte[] getAbilityBit() { + return ServerAbilities.getBitFlags(); + } + + @Override + protected boolean isServer() { + return true; + } + @Override public int rpcPortOffset() { return Integer.parseInt(System.getProperty(NACOS_SERVER_GRPC_PORT_OFFSET_KEY, diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcSdkClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcSdkClient.java index 34cf40824..8cbc9fcc3 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcSdkClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcSdkClient.java @@ -16,6 +16,7 @@ package com.alibaba.nacos.common.remote.client.grpc; +import com.alibaba.nacos.api.ability.register.impl.ClientAbilities; import com.alibaba.nacos.api.common.Constants; /** @@ -35,6 +36,16 @@ public class GrpcSdkClient extends GrpcClient { super(name); } + @Override + public byte[] getAbilityBit() { + return ClientAbilities.getBitFlags(); + } + + @Override + protected boolean isServer() { + return false; + } + @Override public int rpcPortOffset() { return Integer.parseInt(System.getProperty(NACOS_SERVER_GRPC_PORT_OFFSET_KEY, diff --git a/common/src/test/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClientTest.java b/common/src/test/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClientTest.java index 5a81ab3ed..dd6f8f965 100644 --- a/common/src/test/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClientTest.java +++ b/common/src/test/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClientTest.java @@ -47,6 +47,16 @@ public class GrpcClientTest { @Before public void setUp() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { grpcClient = spy(new GrpcClient("testClient") { + @Override + public byte[] getAbilityBit() { + return new byte[1]; + } + + @Override + protected boolean isServer() { + return false; + } + @Override public int rpcPortOffset() { return 1000; diff --git a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java index 44a01258f..6a6d5effa 100644 --- a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java +++ b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java @@ -16,7 +16,10 @@ package com.alibaba.nacos.core.ability.control; +import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.ability.entity.AbilityTable; +import com.alibaba.nacos.api.ability.register.impl.ServerAbilities; +import com.alibaba.nacos.api.utils.AbilityTableUtils; import com.alibaba.nacos.common.JustForTest; import com.alibaba.nacos.common.ability.AbstractAbilityControlManager; import com.alibaba.nacos.common.ability.DefaultAbilityControlManager; @@ -48,7 +51,7 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im /**. * ability for cluster */ - private final Map clusterAbilityTable = new ConcurrentHashMap<>(); + private final Map clusterAbilityTable = new ConcurrentHashMap<>(); /**. * ability for server @@ -58,7 +61,7 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im /** * components for cluster. these will be invoked if cluster ability table changes. */ - private final Map> clusterHandlerMapping = new ConcurrentHashMap<>(); + private final Map> clusterHandlerMapping = new ConcurrentHashMap<>(); private Lock lockForClusterComponents = new ReentrantLock(); @@ -73,7 +76,12 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im } @Override - public boolean isSupport(String connectionId, String abilityKey) { + protected Map getCurrentNodeSupportAbility() { + return AbilityTableUtils.getAbilityTableBy(ServerAbilities.getBitFlags(), ServerAbilities.getOffset()); + } + + @Override + public boolean isSupport(String connectionId, AbilityKey abilityKey) { Boolean isRunning = currentRunningAbility.getOrDefault(abilityKey, false); if (!isRunning) { return false; @@ -93,12 +101,12 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im * @return whether it is turn on */ @Override - public boolean isClusterEnableAbility(String abilityKey) { + public boolean isClusterEnableAbility(AbilityKey abilityKey) { return clusterAbilityTable.getOrDefault(abilityKey, Boolean.FALSE); } @Override - public Map getClusterAbility() { + public Map getClusterAbility() { return Collections.unmodifiableMap(clusterAbilityTable); } @@ -110,17 +118,17 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im * @param handlerMapping component */ @Override - public void registerComponentForCluster(String abilityKey, HandlerMapping handlerMapping, int priority) { + public void registerComponentForCluster(AbilityKey abilityKey, HandlerMapping handlerMapping, int priority) { doRegisterComponent(abilityKey, handlerMapping, this.clusterHandlerMapping, lockForClusterComponents, priority, clusterAbilityTable); } @Override - public int removeClusterComponent(String abilityKey, Class handlerMappingClazz) { + public int removeClusterComponent(AbilityKey abilityKey, Class handlerMappingClazz) { return doRemove(abilityKey, handlerMappingClazz, lockForClusterComponents, clusterHandlerMapping); } @Override - public int removeAllForCluster(String abilityKey) { + public int removeAllForCluster(AbilityKey abilityKey) { List remove = this.clusterHandlerMapping.remove(abilityKey); return Optional.ofNullable(remove).orElse(Collections.emptyList()).size(); } @@ -134,8 +142,8 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im if (isServer) { serversAbilityTable.put(table.getConnectionId(), table); // enter cluster - Map nodeAbility = table.getAbility(); - Set keySet = clusterAbilityTable.keySet(); + Map nodeAbility = table.getAbility(); + Set keySet = clusterAbilityTable.keySet(); keySet.forEach(abilityKey -> { Boolean isEnabled = clusterAbilityTable.get(abilityKey); Boolean val = nodeAbility.getOrDefault(abilityKey, Boolean.FALSE); @@ -153,7 +161,7 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im } } - private ClusterAbilityUpdateEvent buildClusterEvent(String abilityKey, boolean isOn) { + private ClusterAbilityUpdateEvent buildClusterEvent(AbilityKey abilityKey, boolean isOn) { // notify ClusterAbilityUpdateEvent event = new ClusterAbilityUpdateEvent(); event.setAbilityKey(abilityKey); @@ -176,7 +184,7 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im serversAbilityTable.remove(connectionId); // remove from cluster if (MapUtil.isNotEmpty(serversAbilityTable)) { - Set keySet = clusterAbilityTable.keySet(); + Set keySet = clusterAbilityTable.keySet(); keySet.forEach(abilityKey -> { Boolean isEnabled = clusterAbilityTable.getOrDefault(abilityKey, Boolean.FALSE); // nothing to do if enabled @@ -219,17 +227,17 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im private static final long serialVersionUID = -122222411212200111L; - private String abilityKey; + private AbilityKey abilityKey; private boolean isOn; private ClusterAbilityUpdateEvent(){} - public String getAbilityKey() { + public AbilityKey getAbilityKey() { return abilityKey; } - public void setAbilityKey(String abilityKey) { + public void setAbilityKey(AbilityKey abilityKey) { this.abilityKey = abilityKey; } @@ -244,12 +252,12 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im } @JustForTest - protected void setClusterAbilityTable(Map map) { + protected void setClusterAbilityTable(Map map) { clusterAbilityTable.putAll(map); } @JustForTest - protected Map> clusterHandlerMapping() { + protected Map> clusterHandlerMapping() { return this.clusterHandlerMapping; } diff --git a/core/src/main/java/com/alibaba/nacos/core/ability/inte/ClusterAbilityControlSupport.java b/core/src/main/java/com/alibaba/nacos/core/ability/inte/ClusterAbilityControlSupport.java index 1150b2005..5b79e6b6b 100644 --- a/core/src/main/java/com/alibaba/nacos/core/ability/inte/ClusterAbilityControlSupport.java +++ b/core/src/main/java/com/alibaba/nacos/core/ability/inte/ClusterAbilityControlSupport.java @@ -16,6 +16,8 @@ package com.alibaba.nacos.core.ability.inte; +import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.register.AbilityBitOperate; import com.alibaba.nacos.common.ability.handler.HandlerMapping; import com.alibaba.nacos.common.ability.inter.AbilityControlManager; @@ -33,7 +35,7 @@ public interface ClusterAbilityControlSupport { * * @return the cluster abilities. */ - Map getClusterAbility(); + Map getClusterAbility(); /**. * Register components for cluster. These will be trigger when its interested ability changes @@ -42,7 +44,7 @@ public interface ClusterAbilityControlSupport { * @param priority a positive number, the higher the priority, the faster it will be called * @param handlerMapping component */ - void registerComponentForCluster(String abilityKey, HandlerMapping handlerMapping, int priority); + void registerComponentForCluster(AbilityKey abilityKey, HandlerMapping handlerMapping, int priority); /**. * Default method to register component @@ -50,25 +52,25 @@ public interface ClusterAbilityControlSupport { * @param abilityKey component key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey}. * @param handlerMapping component instance. */ - default void registerComponentForCluster(String abilityKey, HandlerMapping handlerMapping) { + default void registerComponentForCluster(AbilityKey abilityKey, HandlerMapping handlerMapping) { registerComponentForCluster(abilityKey, handlerMapping, 1); } /** * Remove the component instance of

handlerMappingClazz

. * - * @param abilityKey ability key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey} + * @param abilityKey ability key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey}. * @param handlerMappingClazz implement of {@link HandlerMapping} * @return the count of components have removed */ - int removeClusterComponent(String abilityKey, Class handlerMappingClazz); + int removeClusterComponent(AbilityKey abilityKey, Class handlerMappingClazz); /** * Remove all {@link HandlerMapping} interested in the special ability. - * @param abilityKey abnility key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey} + * @param abilityKey abnility key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey}. * @return the count of components have removed */ - int removeAllForCluster(String abilityKey); + int removeAllForCluster(AbilityKey abilityKey); /**. * Whether current cluster supports ability @@ -76,5 +78,5 @@ public interface ClusterAbilityControlSupport { * @param abilityKey ability key * @return whether it is turn on */ - boolean isClusterEnableAbility(String abilityKey); + boolean isClusterEnableAbility(AbilityKey abilityKey); } diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java b/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java index 2553d24a7..2e159bce1 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java @@ -17,6 +17,7 @@ package com.alibaba.nacos.core.remote; import com.alibaba.nacos.api.ability.ClientAbilities; +import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.remote.Requester; import java.util.Map; @@ -32,7 +33,7 @@ public abstract class Connection implements Requester { private boolean traced = false; - private Map abilityTable; + private Map abilityTable; private ClientAbilities abilities; @@ -54,11 +55,11 @@ public abstract class Connection implements Requester { this.traced = traced; } - public Map getAbilityTable() { + public Map getAbilityTable() { return abilityTable; } - public void setAbilityTable(Map abilityTable) { + public void setAbilityTable(Map abilityTable) { this.abilityTable = abilityTable; } diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java index 6f2c32b7f..39edc93c3 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java @@ -16,7 +16,8 @@ package com.alibaba.nacos.core.remote.grpc; -import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.register.impl.ClientAbilities; +import com.alibaba.nacos.api.ability.register.impl.ServerAbilities; import com.alibaba.nacos.api.common.Constants; import com.alibaba.nacos.api.grpc.auto.BiRequestStreamGrpc; import com.alibaba.nacos.api.grpc.auto.Payload; @@ -122,7 +123,16 @@ public class GrpcBiStreamRequestAcceptor extends BiRequestStreamGrpc.BiRequestSt setUpRequest.getClientVersion(), appName, setUpRequest.getLabels()); metaInfo.setTenant(setUpRequest.getTenant()); Connection connection = new GrpcConnection(metaInfo, responseObserver, CONTEXT_KEY_CHANNEL.get()); - connection.setAbilityTable(AbilityTableUtils.getAbilityTableBy(setUpRequest.getAbilityTable(), AbilityKey.offset())); + if (setUpRequest.isServer()) { + // if from server + connection.setAbilityTable(AbilityTableUtils.getAbilityTableBy(setUpRequest.getAbilityTable(), + ServerAbilities.getOffset())); + } else { + // if from client + connection.setAbilityTable(AbilityTableUtils.getAbilityTableBy(setUpRequest.getAbilityTable(), + ClientAbilities.getOffset())); + } + System.out.println(connection.getAbilityTable()); boolean rejectSdkOnStarting = metaInfo.isSdkSource() && !ApplicationUtils.isStarted(); if (rejectSdkOnStarting || !connectionManager.register(connectionId, connection)) { diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java index d16ce16ab..a2869d6cd 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java @@ -16,7 +16,7 @@ package com.alibaba.nacos.core.remote.grpc; -import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.register.impl.ServerAbilities; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.grpc.auto.Payload; import com.alibaba.nacos.api.grpc.auto.RequestGrpc; @@ -90,7 +90,7 @@ public class GrpcRequestAcceptor extends RequestGrpc.RequestImplBase { // server check. if (ServerCheckRequest.class.getSimpleName().equals(type)) { Payload serverCheckResponseP = GrpcUtils.convert(new ServerCheckResponse(CONTEXT_KEY_CONN_ID.get(), - AbilityKey.getAbilityBitFlags())); + ServerAbilities.getBitFlags())); traceIfNecessary(serverCheckResponseP, false); responseObserver.onNext(serverCheckResponseP); responseObserver.onCompleted(); diff --git a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityControlManagerTest.java b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityControlManagerTest.java index 99d7cced7..16d753d4f 100644 --- a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityControlManagerTest.java +++ b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityControlManagerTest.java @@ -16,6 +16,7 @@ package com.alibaba.nacos.test.ability; +import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.ability.entity.AbilityTable; import com.alibaba.nacos.common.ability.handler.HandlerMapping; import org.junit.Assert; @@ -43,74 +44,74 @@ public class AbilityControlManagerTest { @Before public void inject() { - Map newTable = new HashMap<>(); - newTable.put("stop-raft", true); + Map newTable = new HashMap<>(); + newTable.put(AbilityKey.TEST_1, true); clientAbilityControlManager.setCurrentSupportingAbility(newTable); - Map table = new HashMap<>(); - table.put("stop-raft", true); + Map table = new HashMap<>(); + table.put(AbilityKey.TEST_1, true); serverAbilityControlManager.setCurrentSupportingAbility(table); - Map cluster = new HashMap<>(); - cluster.put("stop-raft", true); + Map cluster = new HashMap<>(); + cluster.put(AbilityKey.TEST_1, true); serverAbilityControlManager.setClusterAbility(cluster); serverAbilityControlManager.setCurrentSupportingAbility(newTable); } @Test public void testClientAdd() { - Map newTable = new HashMap<>(); - newTable.put("test-no-existed", true); - newTable.put("stop-raft", true); + Map newTable = new HashMap<>(); + newTable.put(AbilityKey.TEST_2, true); + newTable.put(AbilityKey.TEST_1, true); AbilityTable table = new AbilityTable(); table.setConnectionId("test-00001"); table.setAbility(newTable); table.setServer(true); clientAbilityControlManager.addNewTable(table); - Assert.assertFalse(clientAbilityControlManager.isSupport("test-00001", "test-no-existed")); - Assert.assertTrue(clientAbilityControlManager.isSupport("test-00001", "stop-raft")); + Assert.assertFalse(clientAbilityControlManager.isSupport("test-00001", AbilityKey.TEST_2)); + Assert.assertTrue(clientAbilityControlManager.isSupport("test-00001", AbilityKey.TEST_1)); } @Test public void testServerAdd() { - Map newTable = new HashMap<>(); - newTable.put("test-no-existed", true); - newTable.put("stop-raft", true); + Map newTable = new HashMap<>(); + newTable.put(AbilityKey.TEST_2, true); + newTable.put(AbilityKey.TEST_1, true); AbilityTable table = new AbilityTable(); table.setConnectionId("test-00001"); table.setAbility(newTable); table.setServer(true); serverAbilityControlManager.addNewTable(table); - Assert.assertFalse(serverAbilityControlManager.isSupport("test-00001", "test-no-existed")); - Assert.assertTrue(serverAbilityControlManager.isSupport("test-00001", "stop-raft")); - Assert.assertTrue(serverAbilityControlManager.isClusterEnableAbility("stop-raft")); + Assert.assertFalse(serverAbilityControlManager.isSupport("test-00001", AbilityKey.TEST_2)); + Assert.assertTrue(serverAbilityControlManager.isSupport("test-00001", AbilityKey.TEST_1)); + Assert.assertTrue(serverAbilityControlManager.isClusterEnableAbility(AbilityKey.TEST_1)); - Map otherServer = new HashMap<>(); - otherServer.put("test-no-existed", true); - otherServer.put("stop-raft", false); + Map otherServer = new HashMap<>(); + otherServer.put(AbilityKey.TEST_2, true); + otherServer.put(AbilityKey.TEST_1, false); AbilityTable otherServerTable = new AbilityTable(); otherServerTable.setConnectionId("test-00000"); otherServerTable.setAbility(otherServer); otherServerTable.setServer(true); serverAbilityControlManager.addNewTable(otherServerTable); - Assert.assertFalse(serverAbilityControlManager.isClusterEnableAbility("stop-raft")); + Assert.assertFalse(serverAbilityControlManager.isClusterEnableAbility(AbilityKey.TEST_1)); - Map clientTa = new HashMap<>(); - clientTa.put("test-no-existed", true); - clientTa.put("stop-raft", false); + Map clientTa = new HashMap<>(); + clientTa.put(AbilityKey.TEST_2, true); + clientTa.put(AbilityKey.TEST_1, false); AbilityTable clientTable = new AbilityTable(); clientTable.setConnectionId("test-00002"); clientTable.setAbility(clientTa); clientTable.setServer(false); serverAbilityControlManager.addNewTable(clientTable); - Assert.assertFalse(serverAbilityControlManager.isClusterEnableAbility("stop-raft")); + Assert.assertFalse(serverAbilityControlManager.isClusterEnableAbility(AbilityKey.TEST_1)); } @Test public void testClientRemove() { - Map clientTa = new HashMap<>(); - clientTa.put("test-no-existed", true); - clientTa.put("stop-raft", false); + Map clientTa = new HashMap<>(); + clientTa.put(AbilityKey.TEST_2, true); + clientTa.put(AbilityKey.TEST_1, false); AbilityTable clientTable = new AbilityTable(); clientTable.setConnectionId("test-01111"); clientTable.setAbility(clientTa); @@ -125,56 +126,56 @@ public class AbilityControlManagerTest { public void testComponent() throws InterruptedException { enabled = 0; // invoke enable() or disable() when registering - serverAbilityControlManager.registerComponent("stop-raft", new TestHandlerMapping(), -1); + serverAbilityControlManager.registerComponent(AbilityKey.TEST_1, new TestHandlerMapping(), -1); Assert.assertEquals(1, serverAbilityControlManager.handlerMappingCount()); - serverAbilityControlManager.enableCurrentNodeAbility("stop-raft"); + serverAbilityControlManager.enableCurrentNodeAbility(AbilityKey.TEST_1); // wait for invoking handler asyn Thread.sleep(200L); // nothing happens if it has enabled Assert.assertEquals(enabled, 1); - Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning("stop-raft")); + Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); // invoke disable() - serverAbilityControlManager.disableCurrentNodeAbility("stop-raft"); + serverAbilityControlManager.disableCurrentNodeAbility(AbilityKey.TEST_1); // wait for invoking handler asyn Thread.sleep(200L); // disable will invoke handler Assert.assertEquals(enabled, 0); - Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning("stop-raft")); + Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); - serverAbilityControlManager.disableCurrentNodeAbility("stop-raft"); + serverAbilityControlManager.disableCurrentNodeAbility(AbilityKey.TEST_1); // wait for invoking handler asyn Thread.sleep(200L); // nothing to do because it has disable Assert.assertEquals(enabled, 0); - Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning("stop-raft")); + Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); - serverAbilityControlManager.enableCurrentNodeAbility("stop-raft"); + serverAbilityControlManager.enableCurrentNodeAbility(AbilityKey.TEST_1); // wait for invoking handler asyn Thread.sleep(200L); Assert.assertEquals(enabled, 1); - Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning("stop-raft")); + Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); - serverAbilityControlManager.enableCurrentNodeAbility("stop-raft"); + serverAbilityControlManager.enableCurrentNodeAbility(AbilityKey.TEST_1); // wait for invoking handler asyn Thread.sleep(200L); Assert.assertEquals(enabled, 1); - Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning("stop-raft")); + Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); } @Test public void testClusterComponent() throws InterruptedException { clusterEnabled = 0; // invoke enable() because it turn on - serverAbilityControlManager.registerComponentForCluster("stop-raft", new ClusterHandlerMapping(), -1); + serverAbilityControlManager.registerComponentForCluster(AbilityKey.TEST_1, new ClusterHandlerMapping(), -1); Assert.assertEquals(1, serverAbilityControlManager.clusterHandlerMappingCount()); - Assert.assertTrue(serverAbilityControlManager.isClusterEnableAbility("stop-raft")); + Assert.assertTrue(serverAbilityControlManager.isClusterEnableAbility(AbilityKey.TEST_1)); Assert.assertEquals(clusterEnabled, 1); - Map serverAbility = new HashMap<>(); - serverAbility.put("test-no-existed", true); - serverAbility.put("stop-raft", false); + Map serverAbility = new HashMap<>(); + serverAbility.put(AbilityKey.TEST_2, true); + serverAbility.put(AbilityKey.TEST_1, false); AbilityTable serverTable = new AbilityTable(); serverTable.setConnectionId("test-01111"); serverTable.setAbility(serverAbility); @@ -184,20 +185,20 @@ public class AbilityControlManagerTest { Thread.sleep(200L); // disabled - Assert.assertFalse(serverAbilityControlManager.isClusterEnableAbility("stop-raft")); + Assert.assertFalse(serverAbilityControlManager.isClusterEnableAbility(AbilityKey.TEST_1)); Assert.assertEquals(clusterEnabled, 0); // remove this table to enabled serverAbilityControlManager.removeTable("test-01111"); // wait for invoking handler asyn Thread.sleep(200L); - Assert.assertTrue(serverAbilityControlManager.isClusterEnableAbility("stop-raft")); + Assert.assertTrue(serverAbilityControlManager.isClusterEnableAbility(AbilityKey.TEST_1)); Assert.assertEquals(clusterEnabled, 1); } @Test public void testCurrentNodeAbility() { - Set keySet = serverAbilityControlManager.getCurrentRunningAbility().keySet(); + Set keySet = serverAbilityControlManager.getCurrentRunningAbility().keySet(); // diable all keySet.forEach(key -> serverAbilityControlManager.disableCurrentNodeAbility(key)); // get all @@ -215,7 +216,7 @@ public class AbilityControlManagerTest { @Test public void testPriority() throws InterruptedException { TestServerAbilityControlManager testServerAbilityControlManager = new TestServerAbilityControlManager(); - String key = "key"; + AbilityKey key = AbilityKey.TEST_1; TestPriority clusterHandlerMapping1 = new TestPriority("1"); TestPriority clusterHandlerMapping2 = new TestPriority("2"); TestPriority clusterHandlerMapping3 = new TestPriority("3"); diff --git a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/TestClientAbilityControlManager.java b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/TestClientAbilityControlManager.java index 5e9fc0899..e506e2952 100644 --- a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/TestClientAbilityControlManager.java +++ b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/TestClientAbilityControlManager.java @@ -16,6 +16,7 @@ package com.alibaba.nacos.test.ability; +import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.client.ability.ClientAbilityControlManager; import com.alibaba.nacos.common.JustForTest; @@ -24,7 +25,7 @@ import java.util.Map; public class TestClientAbilityControlManager extends ClientAbilityControlManager { @JustForTest - public void setCurrentSupportingAbility(Map ability) { + public void setCurrentSupportingAbility(Map ability) { currentRunningAbility.putAll(ability); } } diff --git a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/TestServerAbilityControlManager.java b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/TestServerAbilityControlManager.java index 2c48bc821..3571c6060 100644 --- a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/TestServerAbilityControlManager.java +++ b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/TestServerAbilityControlManager.java @@ -16,6 +16,7 @@ package com.alibaba.nacos.test.ability; +import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.common.JustForTest; import com.alibaba.nacos.common.ability.handler.HandlerMapping; import com.alibaba.nacos.core.ability.control.ServerAbilityControlManager; @@ -27,12 +28,12 @@ import java.util.Map; public class TestServerAbilityControlManager extends ServerAbilityControlManager { @JustForTest - public void setCurrentSupportingAbility(Map ability) { + public void setCurrentSupportingAbility(Map ability) { currentRunningAbility.putAll(ability); } @JustForTest - public void setClusterAbility(Map ability) { + public void setClusterAbility(Map ability) { super.setClusterAbilityTable(ability); } @@ -42,7 +43,7 @@ public class TestServerAbilityControlManager extends ServerAbilityControlManager } @JustForTest - public List getHandlerMapping(String abilityKey) { + public List getHandlerMapping(AbilityKey abilityKey) { return super.handlerMapping().get(abilityKey); } @@ -52,7 +53,7 @@ public class TestServerAbilityControlManager extends ServerAbilityControlManager } @JustForTest - public List getClusterHandlerMapping(String abilityKey) { + public List getClusterHandlerMapping(AbilityKey abilityKey) { return super.clusterHandlerMapping().get(abilityKey); } @@ -60,19 +61,19 @@ public class TestServerAbilityControlManager extends ServerAbilityControlManager * Just a test method. */ @JustForTest - public void registerClusterHandlerMapping(String key, HandlerMapping handlerMapping, int priority) { + public void registerClusterHandlerMapping(AbilityKey key, HandlerMapping handlerMapping, int priority) { List orDefault = super.clusterHandlerMapping().getOrDefault(key, new ArrayList<>()); orDefault.add(new HandlerWithPriority(handlerMapping, priority)); clusterHandlerMapping().put(key, orDefault); } @JustForTest - public void triggerCluster(String abilityKey) { + public void triggerCluster(AbilityKey abilityKey) { triggerHandlerMappingAsyn(abilityKey, true, clusterHandlerMapping()); } @JustForTest - public void trigger(String abilityKey) { + public void trigger(AbilityKey abilityKey) { triggerHandlerMappingAsyn(abilityKey, true, handlerMapping()); } } From 4560d88327aabe7d39859fa8a47c0d801184da00 Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Wed, 31 Aug 2022 19:05:00 +0800 Subject: [PATCH 12/55] Tell unknown if it cannot find AbilityTable. --- .../api/ability/constant/AbilityStatus.java | 40 +++++++++++++++++++ .../ability/ClientAbilityControlManager.java | 17 ++++---- .../ability/inter/AbilityControlManager.java | 3 +- .../control/ServerAbilityControlManager.java | 16 ++++---- 4 files changed, 61 insertions(+), 15 deletions(-) create mode 100644 api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityStatus.java diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityStatus.java b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityStatus.java new file mode 100644 index 000000000..bf788bc8a --- /dev/null +++ b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityStatus.java @@ -0,0 +1,40 @@ +/* + * Copyright 1999-2022 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.nacos.api.ability.constant; + +/**. + * @author Daydreamer + * @description It is used to know a certain ability whether supporting. + * @date 2022/8/31 12:27 + **/ +public enum AbilityStatus { + + /** + * Support a certain ability + */ + SUPPORTED, + + /** + * Not support a certain ability + */ + NOT_SUPPORTED, + + /** + * Cannot find ability table, unknown + */ + UNKNOWN +} diff --git a/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java b/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java index 9e859b3b2..1ecdb41df 100644 --- a/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java +++ b/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java @@ -17,6 +17,7 @@ package com.alibaba.nacos.client.ability; import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.constant.AbilityStatus; import com.alibaba.nacos.api.ability.entity.AbilityTable; import com.alibaba.nacos.api.ability.register.impl.ClientAbilities; import com.alibaba.nacos.api.utils.AbilityTableUtils; @@ -43,17 +44,19 @@ public class ClientAbilityControlManager extends DefaultAbilityControlManager { } @Override - public boolean isSupport(String connectionId, AbilityKey abilityKey) { + public AbilityStatus isSupport(String connectionId, AbilityKey abilityKey) { Boolean isRunning = currentRunningAbility.getOrDefault(abilityKey, false); if (!isRunning) { - return false; + return AbilityStatus.NOT_SUPPORTED; } AbilityTable abilityTable = nodeAbilityTable.get(connectionId); - // false if null - return abilityTable != null - && Optional.ofNullable(abilityTable.getAbility()) - .orElse(Collections.emptyMap()) - .getOrDefault(abilityKey, false); + if(abilityTable == null) { + return AbilityStatus.UNKNOWN; + } + Boolean isSupport = Optional.ofNullable(abilityTable.getAbility()) + .orElse(Collections.emptyMap()) + .getOrDefault(abilityKey, false); + return isSupport ? AbilityStatus.SUPPORTED : AbilityStatus.NOT_SUPPORTED; } @Override diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityControlManager.java index 22bbfd85a..a40cfca63 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityControlManager.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityControlManager.java @@ -17,6 +17,7 @@ package com.alibaba.nacos.common.ability.inter; import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.constant.AbilityStatus; import com.alibaba.nacos.api.ability.register.AbilityBitOperate; import com.alibaba.nacos.api.ability.entity.AbilityTable; @@ -36,7 +37,7 @@ public interface AbilityControlManager { * @param abilityKey key name which comes from {@link AbilityBitOperate}. * @return whether the ability is supported in certain connection. */ - boolean isSupport(String connectionId, AbilityKey abilityKey); + AbilityStatus isSupport(String connectionId, AbilityKey abilityKey); /** * Whether the ability current node supporting is running. Return false if current node doesn't support. diff --git a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java index 6a6d5effa..16da67df9 100644 --- a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java +++ b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java @@ -17,6 +17,7 @@ package com.alibaba.nacos.core.ability.control; import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.constant.AbilityStatus; import com.alibaba.nacos.api.ability.entity.AbilityTable; import com.alibaba.nacos.api.ability.register.impl.ServerAbilities; import com.alibaba.nacos.api.utils.AbilityTableUtils; @@ -81,17 +82,18 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im } @Override - public boolean isSupport(String connectionId, AbilityKey abilityKey) { + public AbilityStatus isSupport(String connectionId, AbilityKey abilityKey) { Boolean isRunning = currentRunningAbility.getOrDefault(abilityKey, false); if (!isRunning) { - return false; + return AbilityStatus.NOT_SUPPORTED; } AbilityTable abilityTable = nodeAbilityTable.get(connectionId); - // false if null - return abilityTable != null - && Optional.ofNullable(abilityTable.getAbility()) - .orElse(Collections.emptyMap()) - .getOrDefault(abilityKey, false); + if(abilityTable == null) { + return AbilityStatus.UNKNOWN; + } + Boolean isSupport = Optional.ofNullable(abilityTable.getAbility()).orElse(Collections.emptyMap()) + .getOrDefault(abilityKey, false); + return isSupport ? AbilityStatus.SUPPORTED : AbilityStatus.NOT_SUPPORTED; } /**. From 22ace653fcdc29c7b28ed76855ab112fb90467fd Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Wed, 31 Aug 2022 21:22:24 +0800 Subject: [PATCH 13/55] The abilities of stock connection abilities remains unchanged and the abilities of incremental connection changes. --- .../nacos/api/ability/entity/AbilityTable.java | 7 ++++++- .../nacos/api/utils/AbilityTableUtils.java | 15 +++++++++++++++ .../ability/ClientAbilityControlManager.java | 4 ---- .../ability/AbstractAbilityControlManager.java | 9 +++++++++ .../remote/client/grpc/GrpcClusterClient.java | 5 ++++- .../common/remote/client/grpc/GrpcSdkClient.java | 5 ++++- .../control/ServerAbilityControlManager.java | 4 ---- 7 files changed, 38 insertions(+), 11 deletions(-) diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/entity/AbilityTable.java b/api/src/main/java/com/alibaba/nacos/api/ability/entity/AbilityTable.java index 67eb663dd..f35f30826 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/entity/AbilityTable.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/entity/AbilityTable.java @@ -95,5 +95,10 @@ public class AbilityTable implements Cloneable { this.ability = ability; return this; } - + + @Override + public String toString() { + return "AbilityTable{" + "connectionId='" + connectionId + '\'' + ", ability=" + ability + ", isServer=" + + isServer + ", version='" + version + '\'' + '}'; + } } diff --git a/api/src/main/java/com/alibaba/nacos/api/utils/AbilityTableUtils.java b/api/src/main/java/com/alibaba/nacos/api/utils/AbilityTableUtils.java index aa74be70d..e6d4c9d01 100644 --- a/api/src/main/java/com/alibaba/nacos/api/utils/AbilityTableUtils.java +++ b/api/src/main/java/com/alibaba/nacos/api/utils/AbilityTableUtils.java @@ -24,6 +24,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; /**. * @author Daydreamer @@ -98,4 +99,18 @@ public class AbilityTableUtils { } return res; } + + /**. + * get ability bit table by existed ability table and offset map + * + * @param offsetMap offset from {@link AbilityBitOperate} + * @return Return the Map containing AbilityTableKey and isRunning. + */ + public static byte[] getAbilityBiTableBy(Map offsetMap, Map abilityTable) { + // filter the element which abilityTable don't have or value is false + Map res = offsetMap.entrySet().stream() + .filter(item -> abilityTable.getOrDefault(item.getKey(), false)) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + return getAbilityBitBy(res.values()); + } } diff --git a/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java b/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java index 1ecdb41df..da37ab638 100644 --- a/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java +++ b/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java @@ -45,10 +45,6 @@ public class ClientAbilityControlManager extends DefaultAbilityControlManager { @Override public AbilityStatus isSupport(String connectionId, AbilityKey abilityKey) { - Boolean isRunning = currentRunningAbility.getOrDefault(abilityKey, false); - if (!isRunning) { - return AbilityStatus.NOT_SUPPORTED; - } AbilityTable abilityTable = nodeAbilityTable.get(connectionId); if(abilityTable == null) { return AbilityStatus.UNKNOWN; diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java index c72e6a9e2..28efd20dc 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java @@ -27,6 +27,7 @@ import org.slf4j.LoggerFactory; import java.util.HashMap; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReentrantLock; @@ -117,6 +118,14 @@ public abstract class AbstractAbilityControlManager implements AbilityControlMan // hook method add(table); // add to node + Set abilityKeys = table.getAbility().keySet(); + Map clientAbilities = table.getAbility(); + abilityKeys.forEach(abilityKey -> { + Boolean res = currentRunningAbility.getOrDefault(abilityKey, false); + Boolean coming = clientAbilities.getOrDefault(abilityKey, false); + clientAbilities.put(abilityKey, res && coming); + }); + System.out.println(table); nodeAbilityTable.put(connectionId, table); } finally { lockForAbilityTable.unlock(); diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClusterClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClusterClient.java index 67cd0cd7c..fdae2aa2f 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClusterClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClusterClient.java @@ -18,6 +18,8 @@ package com.alibaba.nacos.common.remote.client.grpc; import com.alibaba.nacos.api.ability.register.impl.ServerAbilities; import com.alibaba.nacos.api.common.Constants; +import com.alibaba.nacos.api.utils.AbilityTableUtils; +import com.alibaba.nacos.common.ability.discover.NacosAbilityManagerHolder; /** * gRPC client for cluster. @@ -38,7 +40,8 @@ public class GrpcClusterClient extends GrpcClient { @Override public byte[] getAbilityBit() { - return ServerAbilities.getBitFlags(); + // calculate the ability bit table based on ability of current client + return AbilityTableUtils.getAbilityBiTableBy(ServerAbilities.getOffset(), NacosAbilityManagerHolder.getInstance().getCurrentRunningAbility()); } @Override diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcSdkClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcSdkClient.java index 8cbc9fcc3..9c85b2b3c 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcSdkClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcSdkClient.java @@ -18,6 +18,8 @@ package com.alibaba.nacos.common.remote.client.grpc; import com.alibaba.nacos.api.ability.register.impl.ClientAbilities; import com.alibaba.nacos.api.common.Constants; +import com.alibaba.nacos.api.utils.AbilityTableUtils; +import com.alibaba.nacos.common.ability.discover.NacosAbilityManagerHolder; /** * gRPC client for sdk. @@ -38,7 +40,8 @@ public class GrpcSdkClient extends GrpcClient { @Override public byte[] getAbilityBit() { - return ClientAbilities.getBitFlags(); + // calculate the ability bit table based on ability of current client + return AbilityTableUtils.getAbilityBiTableBy(ClientAbilities.getOffset(), NacosAbilityManagerHolder.getInstance().getCurrentRunningAbility()); } @Override diff --git a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java index 16da67df9..1ee0577e3 100644 --- a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java +++ b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java @@ -83,10 +83,6 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im @Override public AbilityStatus isSupport(String connectionId, AbilityKey abilityKey) { - Boolean isRunning = currentRunningAbility.getOrDefault(abilityKey, false); - if (!isRunning) { - return AbilityStatus.NOT_SUPPORTED; - } AbilityTable abilityTable = nodeAbilityTable.get(connectionId); if(abilityTable == null) { return AbilityStatus.UNKNOWN; From dd6c565e65e8692cfd5cd063c7128d1f76d960f2 Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Wed, 31 Aug 2022 21:26:13 +0800 Subject: [PATCH 14/55] Fix note --- .../nacos/api/ability/register/impl/ClientAbilities.java | 8 ++++---- .../nacos/api/ability/register/impl/ServerAbilities.java | 6 +++--- .../core/remote/grpc/GrpcBiStreamRequestAcceptor.java | 1 - 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java index ba1a7496d..df065f653 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java @@ -36,15 +36,15 @@ public class ClientAbilities extends AbilityBitOperate { * There is a function named "compression". * The key is "compression", the value is the offset of the flag bit of this ability in the ability table. The value should be unique. * - * You can add a new public static field in

AbilityKeyConstant

like: - * public static final String COMPRESSION = "compression"; + * You can add a new public field in

AbilityKey

like: + * DATA_COMPRESSION * This field can be used outside. * * And then you need to declare the offset of the flag bit of this ability in the ability table, you can: - * abilityOffset.put("compression", 1); means that is the first bit from left to right in the table. + * abilityOffset.put(AbilityKey.DATA_COMPRESSION, 1); means that is the first bit from left to right in the table. * */ - // put ability here, which you want current server supports + // put ability here, which you want current client supports } private ClientAbilities() { diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java index 842591587..facf2525c 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java @@ -36,12 +36,12 @@ public class ServerAbilities extends AbilityBitOperate { * There is a function named "compression". * The key is "compression", the value is the offset of the flag bit of this ability in the ability table. The value should be unique. * - * You can add a new public static field like: - * public static final String COMPRESSION = "compression"; + * You can add a new public field in

AbilityKey

like: + * DATA_COMPRESSION * This field can be used outside. * * And then you need to declare the offset of the flag bit of this ability in the ability table, you can: - * CURRENT_SERVER_ABILITY_OFFSET.put("compression", 1); means that is the first bit from left to right in the table. + * abilityOffset.put(AbilityKey.DATA_COMPRESSION, 1); means that is the first bit from left to right in the table. * */ // put ability here, which you want current server supports diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java index 39edc93c3..b143834ba 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java @@ -132,7 +132,6 @@ public class GrpcBiStreamRequestAcceptor extends BiRequestStreamGrpc.BiRequestSt connection.setAbilityTable(AbilityTableUtils.getAbilityTableBy(setUpRequest.getAbilityTable(), ClientAbilities.getOffset())); } - System.out.println(connection.getAbilityTable()); boolean rejectSdkOnStarting = metaInfo.isSdkSource() && !ApplicationUtils.isStarted(); if (rejectSdkOnStarting || !connectionManager.register(connectionId, connection)) { From 37cf6c47d8b2efdeb2f162d8ecf844e3ffc021d5 Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Thu, 1 Sep 2022 12:33:34 +0800 Subject: [PATCH 15/55] Fix checkstyle. --- .../api/ability/constant/AbilityKey.java | 21 +++++++++++++++++-- .../api/ability/constant/AbilityStatus.java | 6 +++--- .../api/ability/entity/AbilityTable.java | 1 - ...te.java => AbstractAbilityBitOperate.java} | 9 ++++---- .../register/impl/ClientAbilities.java | 8 +++---- .../register/impl/ServerAbilities.java | 8 +++---- .../request/ConnectionSetupRequest.java | 2 +- .../nacos/api/utils/AbilityTableUtils.java | 6 +++--- .../ability/ClientAbilityControlManager.java | 2 +- .../client/config/impl/ClientWorker.java | 1 - .../client/naming/remote/TestConnection.java | 16 ++++++++++++++ .../AbstractAbilityControlManager.java | 5 ++--- .../ability/DefaultAbilityControlManager.java | 14 +++++++------ .../ability/inter/AbilityControlManager.java | 4 ++-- .../ability/inter/AbilityHandlerRegistry.java | 10 ++++----- .../listener/ClientAbilityEventListener.java | 17 ++++++++++++++- .../remote/client/RpcClientFactory.java | 1 - .../common/remote/client/grpc/GrpcClient.java | 3 +-- .../control/ServerAbilityControlManager.java | 2 +- .../inte/ClusterAbilityControlSupport.java | 1 - 20 files changed, 91 insertions(+), 46 deletions(-) rename api/src/main/java/com/alibaba/nacos/api/ability/register/{AbilityBitOperate.java => AbstractAbilityBitOperate.java} (87%) diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java index 71e1e1435..8a9b8f8c1 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java @@ -23,9 +23,26 @@ package com.alibaba.nacos.api.ability.constant; **/ public enum AbilityKey { - /** + /**. * just for junit test */ - TEST_1, TEST_2, + TEST_1("test_1"), + /**. + * just for junit test + */ + TEST_2("test_2"); + + + + + + + + + private final String name; + + AbilityKey(String name) { + this.name = name; + } } diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityStatus.java b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityStatus.java index bf788bc8a..a762c0373 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityStatus.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityStatus.java @@ -23,17 +23,17 @@ package com.alibaba.nacos.api.ability.constant; **/ public enum AbilityStatus { - /** + /**. * Support a certain ability */ SUPPORTED, - /** + /**. * Not support a certain ability */ NOT_SUPPORTED, - /** + /**. * Cannot find ability table, unknown */ UNKNOWN diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/entity/AbilityTable.java b/api/src/main/java/com/alibaba/nacos/api/ability/entity/AbilityTable.java index f35f30826..63fda78da 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/entity/AbilityTable.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/entity/AbilityTable.java @@ -17,7 +17,6 @@ package com.alibaba.nacos.api.ability.entity; import com.alibaba.nacos.api.ability.constant.AbilityKey; -import com.alibaba.nacos.api.ability.register.AbilityBitOperate; import java.util.Map; diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/register/AbilityBitOperate.java b/api/src/main/java/com/alibaba/nacos/api/ability/register/AbstractAbilityBitOperate.java similarity index 87% rename from api/src/main/java/com/alibaba/nacos/api/ability/register/AbilityBitOperate.java rename to api/src/main/java/com/alibaba/nacos/api/ability/register/AbstractAbilityBitOperate.java index e16165e74..321842672 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/register/AbilityBitOperate.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/register/AbstractAbilityBitOperate.java @@ -19,6 +19,7 @@ package com.alibaba.nacos.api.ability.register; import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.utils.AbilityTableUtils; +import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -27,7 +28,7 @@ import java.util.Map; * @description Operation for bit table. * @date 2022/7/12 19:23 **/ -public abstract class AbilityBitOperate { +public abstract class AbstractAbilityBitOperate { protected final HashMap abilityOffset = new HashMap<>(); @@ -48,11 +49,11 @@ public abstract class AbilityBitOperate { * @return bit offset */ public Map offset() { - return abilityOffset; + return Collections.unmodifiableMap(abilityOffset); } - /** - * put the bit offset to {@link AbilityBitOperate#abilityBitFlag} + /**. + * put the bit offset to {@link AbstractAbilityBitOperate#abilityBitFlag} */ protected void init() { // init the bits table diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java index df065f653..8df959560 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java @@ -17,7 +17,7 @@ package com.alibaba.nacos.api.ability.register.impl; import com.alibaba.nacos.api.ability.constant.AbilityKey; -import com.alibaba.nacos.api.ability.register.AbilityBitOperate; +import com.alibaba.nacos.api.ability.register.AbstractAbilityBitOperate; import java.util.Map; @@ -26,7 +26,7 @@ import java.util.Map; * @description It is used to register client abilities. * @date 2022/8/31 12:32 **/ -public class ClientAbilities extends AbilityBitOperate { +public class ClientAbilities extends AbstractAbilityBitOperate { private static final ClientAbilities INSTANCE = new ClientAbilities(); @@ -52,7 +52,7 @@ public class ClientAbilities extends AbilityBitOperate { init(); } - /** + /**. * get the ability offset for server * * @return ability offset @@ -61,7 +61,7 @@ public class ClientAbilities extends AbilityBitOperate { return INSTANCE.getAbilityBitFlags(); } - /** + /**. * get the ability offset for server * * @return ability offset diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java index facf2525c..2f959087d 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java @@ -17,7 +17,7 @@ package com.alibaba.nacos.api.ability.register.impl; import com.alibaba.nacos.api.ability.constant.AbilityKey; -import com.alibaba.nacos.api.ability.register.AbilityBitOperate; +import com.alibaba.nacos.api.ability.register.AbstractAbilityBitOperate; import java.util.Map; @@ -26,7 +26,7 @@ import java.util.Map; * @description It is used to register server abilities. * @date 2022/8/31 12:32 **/ -public class ServerAbilities extends AbilityBitOperate { +public class ServerAbilities extends AbstractAbilityBitOperate { private static final ServerAbilities INSTANCE = new ServerAbilities(); @@ -52,7 +52,7 @@ public class ServerAbilities extends AbilityBitOperate { init(); } - /** + /**. * get bit table * * @return ability offset @@ -61,7 +61,7 @@ public class ServerAbilities extends AbilityBitOperate { return INSTANCE.getAbilityBitFlags(); } - /** + /**. * get the ability offset for server * * @return ability offset diff --git a/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequest.java b/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequest.java index d2fbd704a..15b3c35d5 100644 --- a/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequest.java +++ b/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequest.java @@ -35,7 +35,7 @@ public class ConnectionSetupRequest extends InternalRequest { private byte[] abilityTable; - /** + /**. * server will resolve {@link ConnectionSetupRequest#abilityTable} to server abilities, or to client abilities */ private boolean isServer; diff --git a/api/src/main/java/com/alibaba/nacos/api/utils/AbilityTableUtils.java b/api/src/main/java/com/alibaba/nacos/api/utils/AbilityTableUtils.java index e6d4c9d01..a97d2a2c2 100644 --- a/api/src/main/java/com/alibaba/nacos/api/utils/AbilityTableUtils.java +++ b/api/src/main/java/com/alibaba/nacos/api/utils/AbilityTableUtils.java @@ -17,7 +17,7 @@ package com.alibaba.nacos.api.utils; import com.alibaba.nacos.api.ability.constant.AbilityKey; -import com.alibaba.nacos.api.ability.register.AbilityBitOperate; +import com.alibaba.nacos.api.ability.register.AbstractAbilityBitOperate; import java.util.Collection; import java.util.Collections; @@ -69,7 +69,7 @@ public class AbilityTableUtils { * get ability table by bits * * @param bits bit flag - * @param offsetMap offset from {@link AbilityBitOperate} + * @param offsetMap offset from {@link AbstractAbilityBitOperate} * @return Return the Map containing AbilityTableKey and isRunning. */ public static Map getAbilityTableBy(byte[] bits, Map offsetMap) { @@ -103,7 +103,7 @@ public class AbilityTableUtils { /**. * get ability bit table by existed ability table and offset map * - * @param offsetMap offset from {@link AbilityBitOperate} + * @param offsetMap offset from {@link AbstractAbilityBitOperate} * @return Return the Map containing AbilityTableKey and isRunning. */ public static byte[] getAbilityBiTableBy(Map offsetMap, Map abilityTable) { diff --git a/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java b/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java index da37ab638..534b3b202 100644 --- a/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java +++ b/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java @@ -46,7 +46,7 @@ public class ClientAbilityControlManager extends DefaultAbilityControlManager { @Override public AbilityStatus isSupport(String connectionId, AbilityKey abilityKey) { AbilityTable abilityTable = nodeAbilityTable.get(connectionId); - if(abilityTable == null) { + if (abilityTable == null) { return AbilityStatus.UNKNOWN; } Boolean isSupport = Optional.ofNullable(abilityTable.getAbility()) diff --git a/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java b/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java index d56b23a7c..a227d537e 100644 --- a/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java +++ b/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java @@ -17,7 +17,6 @@ package com.alibaba.nacos.client.config.impl; import com.alibaba.nacos.api.PropertyKeyConst; -import com.alibaba.nacos.api.ability.register.AbilityBitOperate; import com.alibaba.nacos.api.common.Constants; import com.alibaba.nacos.api.config.ConfigType; import com.alibaba.nacos.api.config.listener.Listener; diff --git a/client/src/test/java/com/alibaba/nacos/client/naming/remote/TestConnection.java b/client/src/test/java/com/alibaba/nacos/client/naming/remote/TestConnection.java index 6d02c962d..43fc088fd 100644 --- a/client/src/test/java/com/alibaba/nacos/client/naming/remote/TestConnection.java +++ b/client/src/test/java/com/alibaba/nacos/client/naming/remote/TestConnection.java @@ -1,3 +1,19 @@ +/* + * Copyright 1999-2022 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.nacos.client.naming.remote; import com.alibaba.nacos.api.exception.NacosException; diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java index 28efd20dc..51e77b837 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java @@ -17,7 +17,7 @@ package com.alibaba.nacos.common.ability; import com.alibaba.nacos.api.ability.constant.AbilityKey; -import com.alibaba.nacos.api.ability.register.AbilityBitOperate; +import com.alibaba.nacos.api.ability.register.AbstractAbilityBitOperate; import com.alibaba.nacos.api.ability.entity.AbilityTable; import com.alibaba.nacos.common.ability.inter.AbilityControlManager; import com.alibaba.nacos.common.notify.Event; @@ -45,7 +45,7 @@ public abstract class AbstractAbilityControlManager implements AbilityControlMan /** * Abilities current supporting *

- * key: ability key from {@link AbilityBitOperate} + * key: ability key from {@link AbstractAbilityBitOperate} * value: whether to turn on */ protected final Map currentRunningAbility = new ConcurrentHashMap<>(); @@ -125,7 +125,6 @@ public abstract class AbstractAbilityControlManager implements AbilityControlMan Boolean coming = clientAbilities.getOrDefault(abilityKey, false); clientAbilities.put(abilityKey, res && coming); }); - System.out.println(table); nodeAbilityTable.put(connectionId, table); } finally { lockForAbilityTable.unlock(); diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/DefaultAbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/DefaultAbilityControlManager.java index 9d7dbfe36..46268198f 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/DefaultAbilityControlManager.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/DefaultAbilityControlManager.java @@ -17,7 +17,7 @@ package com.alibaba.nacos.common.ability; import com.alibaba.nacos.api.ability.constant.AbilityKey; -import com.alibaba.nacos.api.ability.register.AbilityBitOperate; +import com.alibaba.nacos.api.ability.register.AbstractAbilityBitOperate; import com.alibaba.nacos.api.ability.entity.AbilityTable; import com.alibaba.nacos.common.JustForTest; import com.alibaba.nacos.common.ability.handler.HandlerMapping; @@ -47,13 +47,15 @@ import java.util.concurrent.locks.ReentrantLock; * @description It is a relatively complete capability control center implementation. * @date 2022/7/12 19:18 **/ +@SuppressWarnings("PMD.AbstractClassShouldStartWithAbstractNamingRule") public abstract class DefaultAbilityControlManager extends AbstractAbilityControlManager implements AbilityHandlerRegistry { private static final Logger LOGGER = LoggerFactory.getLogger(DefaultAbilityControlManager.class); - /** - * These handlers will be invoked when the flag of ability change key: ability key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey} value: + /**. + * These handlers will be invoked when the flag of ability change key: + * ability key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey} value: * components who want to be invoked if its interested ability turn on/off */ private final Map> handlerMappings = new ConcurrentHashMap<>(); @@ -162,7 +164,7 @@ public abstract class DefaultAbilityControlManager extends AbstractAbilityContro /** * Remove the component instance of

handlerMappingClazz

. * - * @param abilityKey ability key from {@link AbilityBitOperate} + * @param abilityKey ability key from {@link AbstractAbilityBitOperate} * @param handlerMappingClazz implement of {@link HandlerMapping} * @param lock lock for operation * @param handlerMappingsMap handler collection map @@ -240,7 +242,7 @@ public abstract class DefaultAbilityControlManager extends AbstractAbilityContro /** * Invoke componments which linked to ability key asyn. * - * @param key ability key from {@link AbilityBitOperate} + * @param key ability key from {@link AbstractAbilityBitOperate} * @param isEnabled turn on/off * @param handlerMappingsMap handler collection */ @@ -252,7 +254,7 @@ public abstract class DefaultAbilityControlManager extends AbstractAbilityContro /** * Invoke componments which linked to ability key syn. * - * @param key ability key from {@link AbilityBitOperate} + * @param key ability key from {@link AbstractAbilityBitOperate} * @param isEnabled turn on/off * @param handlerMappingsMap handler collection */ diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityControlManager.java index a40cfca63..0972ff980 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityControlManager.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityControlManager.java @@ -18,7 +18,7 @@ package com.alibaba.nacos.common.ability.inter; import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.ability.constant.AbilityStatus; -import com.alibaba.nacos.api.ability.register.AbilityBitOperate; +import com.alibaba.nacos.api.ability.register.AbstractAbilityBitOperate; import com.alibaba.nacos.api.ability.entity.AbilityTable; import java.util.Map; @@ -34,7 +34,7 @@ public interface AbilityControlManager { * Whether the ability is supported for Connection. If the ability of current node is closed, it will return false. * * @param connectionId the connection range of ability table. - * @param abilityKey key name which comes from {@link AbilityBitOperate}. + * @param abilityKey key name which comes from {@link AbstractAbilityBitOperate}. * @return whether the ability is supported in certain connection. */ AbilityStatus isSupport(String connectionId, AbilityKey abilityKey); diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityHandlerRegistry.java b/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityHandlerRegistry.java index 77d2e847c..52d1b432f 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityHandlerRegistry.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityHandlerRegistry.java @@ -17,7 +17,7 @@ package com.alibaba.nacos.common.ability.inter; import com.alibaba.nacos.api.ability.constant.AbilityKey; -import com.alibaba.nacos.api.ability.register.AbilityBitOperate; +import com.alibaba.nacos.api.ability.register.AbstractAbilityBitOperate; import com.alibaba.nacos.common.ability.AbstractAbilityControlManager; import com.alibaba.nacos.common.ability.handler.HandlerMapping; @@ -48,7 +48,7 @@ public interface AbilityHandlerRegistry { * Register the component which is managed by {@link AbstractAbilityControlManager}. * if you are hoping that a component will be invoked when turn on/off the ability whose key is

abilityKey

. * - * @param abilityKey component key from {@link AbilityBitOperate} + * @param abilityKey component key from {@link AbstractAbilityBitOperate} * @param priority a positive number, the higher the priority is, the faster it will be called. `1` is the lowest priority. * @param handlerMapping component instance. */ @@ -57,7 +57,7 @@ public interface AbilityHandlerRegistry { /**. * Default method to register component with the lowest priority. * - * @param abilityKey component key from {@link AbilityBitOperate} + * @param abilityKey component key from {@link AbstractAbilityBitOperate} * @param handlerMapping component instance. */ default void registerComponent(AbilityKey abilityKey, HandlerMapping handlerMapping) { @@ -67,7 +67,7 @@ public interface AbilityHandlerRegistry { /** * Remove the component instance of

handlerMappingClazz

. * - * @param abilityKey ability key from {@link AbilityBitOperate} + * @param abilityKey ability key from {@link AbstractAbilityBitOperate} * @param handlerMappingClazz implement of {@link HandlerMapping} * @return the count of components have removed */ @@ -75,7 +75,7 @@ public interface AbilityHandlerRegistry { /** * Remove all {@link HandlerMapping} interested in the special ability. - * @param abilityKey abnility key from {@link AbilityBitOperate} + * @param abilityKey abnility key from {@link AbstractAbilityBitOperate} * @return the count of components have removed */ int removeAll(AbilityKey abilityKey); diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/listener/ClientAbilityEventListener.java b/common/src/main/java/com/alibaba/nacos/common/ability/listener/ClientAbilityEventListener.java index 0c2004365..0093709c5 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/listener/ClientAbilityEventListener.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/listener/ClientAbilityEventListener.java @@ -1,5 +1,20 @@ -package com.alibaba.nacos.common.ability.listener; +/* + * Copyright 1999-2022 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.nacos.common.ability.listener; import com.alibaba.nacos.common.ability.discover.NacosAbilityManagerHolder; import com.alibaba.nacos.common.remote.client.Connection; diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClientFactory.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClientFactory.java index 8293f0192..2d71b9e46 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClientFactory.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClientFactory.java @@ -16,7 +16,6 @@ package com.alibaba.nacos.common.remote.client; -import com.alibaba.nacos.api.ability.register.impl.ServerAbilities; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.common.remote.ConnectionType; import com.alibaba.nacos.common.remote.client.grpc.GrpcClient; diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java index d4c61452e..c6771ab76 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java @@ -17,7 +17,6 @@ package com.alibaba.nacos.common.remote.client.grpc; import com.alibaba.nacos.api.ability.constant.AbilityKey; -import com.alibaba.nacos.api.ability.register.AbilityBitOperate; import com.alibaba.nacos.api.ability.entity.AbilityTable; import com.alibaba.nacos.api.ability.register.impl.ServerAbilities; import com.alibaba.nacos.api.exception.NacosException; @@ -358,7 +357,7 @@ public abstract class GrpcClient extends RpcClient { return null; } - /** + /**. * get ability, server or client * * @return bit table diff --git a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java index 1ee0577e3..e61d39553 100644 --- a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java +++ b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java @@ -84,7 +84,7 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im @Override public AbilityStatus isSupport(String connectionId, AbilityKey abilityKey) { AbilityTable abilityTable = nodeAbilityTable.get(connectionId); - if(abilityTable == null) { + if (abilityTable == null) { return AbilityStatus.UNKNOWN; } Boolean isSupport = Optional.ofNullable(abilityTable.getAbility()).orElse(Collections.emptyMap()) diff --git a/core/src/main/java/com/alibaba/nacos/core/ability/inte/ClusterAbilityControlSupport.java b/core/src/main/java/com/alibaba/nacos/core/ability/inte/ClusterAbilityControlSupport.java index 5b79e6b6b..9b989a078 100644 --- a/core/src/main/java/com/alibaba/nacos/core/ability/inte/ClusterAbilityControlSupport.java +++ b/core/src/main/java/com/alibaba/nacos/core/ability/inte/ClusterAbilityControlSupport.java @@ -17,7 +17,6 @@ package com.alibaba.nacos.core.ability.inte; import com.alibaba.nacos.api.ability.constant.AbilityKey; -import com.alibaba.nacos.api.ability.register.AbilityBitOperate; import com.alibaba.nacos.common.ability.handler.HandlerMapping; import com.alibaba.nacos.common.ability.inter.AbilityControlManager; From 6273cce1df1b3177903f09ab563f8621f04952d7 Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Thu, 1 Sep 2022 17:42:01 +0800 Subject: [PATCH 16/55] Separate client capability and server capability: ClientAbilities and ServerAbilities. --- .../api/ability/constant/AbilityKey.java | 46 +++++++++++++++---- ...rate.java => AbstractAbilityRegistry.java} | 26 +++++------ .../register/impl/ClientAbilities.java | 22 ++++----- .../register/impl/ServerAbilities.java | 22 ++++----- .../nacos/api/utils/AbilityTableUtils.java | 22 +++++++-- .../ability/ClientAbilityControlManager.java | 3 +- .../AbstractAbilityControlManager.java | 4 +- .../ability/DefaultAbilityControlManager.java | 8 ++-- .../ability/inter/AbilityControlManager.java | 4 +- .../ability/inter/AbilityHandlerRegistry.java | 10 ++-- .../common/remote/client/grpc/GrpcClient.java | 15 +++--- .../remote/client/grpc/GrpcClusterClient.java | 9 ---- .../remote/client/grpc/GrpcSdkClient.java | 9 ---- .../remote/client/grpc/GrpcClientTest.java | 4 -- .../control/ServerAbilityControlManager.java | 3 +- .../grpc/GrpcBiStreamRequestAcceptor.java | 14 ++---- .../ability/AbilityControlManagerTest.java | 9 ++-- 17 files changed, 119 insertions(+), 111 deletions(-) rename api/src/main/java/com/alibaba/nacos/api/ability/register/{AbstractAbilityBitOperate.java => AbstractAbilityRegistry.java} (70%) diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java index 8a9b8f8c1..11a26e54a 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java @@ -16,6 +16,11 @@ package com.alibaba.nacos.api.ability.constant; +import java.util.Arrays; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + /**. * @author Daydreamer * @description Ability key constant. @@ -26,23 +31,44 @@ public enum AbilityKey { /**. * just for junit test */ - TEST_1("test_1"), + TEST_1("test_1", 1), /**. * just for junit test */ - TEST_2("test_2"); - - - - - - - + TEST_2("test_2", 2); + /**. + * the name of a certain ability + */ private final String name; - AbilityKey(String name) { + /**. + * the offset in ability table + */ + private final int offset; + + AbilityKey(String name, int offset) { this.name = name; + this.offset = offset; + } + + public String getName() { + return name; + } + + public int getOffset() { + return offset; + } + + private static final Map OFFSET_MAP; + + public static Map offset() { + return OFFSET_MAP; + } + + static { + OFFSET_MAP = Arrays.stream(AbilityKey.values()) + .collect(Collectors.toMap(Function.identity(), AbilityKey::getOffset)); } } diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/register/AbstractAbilityBitOperate.java b/api/src/main/java/com/alibaba/nacos/api/ability/register/AbstractAbilityRegistry.java similarity index 70% rename from api/src/main/java/com/alibaba/nacos/api/ability/register/AbstractAbilityBitOperate.java rename to api/src/main/java/com/alibaba/nacos/api/ability/register/AbstractAbilityRegistry.java index 321842672..4ad0df43d 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/register/AbstractAbilityBitOperate.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/register/AbstractAbilityRegistry.java @@ -28,9 +28,9 @@ import java.util.Map; * @description Operation for bit table. * @date 2022/7/12 19:23 **/ -public abstract class AbstractAbilityBitOperate { +public abstract class AbstractAbilityRegistry { - protected final HashMap abilityOffset = new HashMap<>(); + protected final Map supportedAbilities = new HashMap<>(); private byte[] abilityBitFlag; @@ -42,21 +42,21 @@ public abstract class AbstractAbilityBitOperate { public byte[] getAbilityBitFlags() { return abilityBitFlag.clone(); } - - /**. - * Return the ability bit offsets - * - * @return bit offset - */ - public Map offset() { - return Collections.unmodifiableMap(abilityOffset); - } /**. - * put the bit offset to {@link AbstractAbilityBitOperate#abilityBitFlag} + * put the bit offset to {@link AbstractAbilityRegistry#abilityBitFlag} */ protected void init() { // init the bits table - abilityBitFlag = AbilityTableUtils.getAbilityBitBy(abilityOffset.values()); + abilityBitFlag = AbilityTableUtils.getAbilityBiTableBy(AbilityKey.values(), supportedAbilities); + } + + /** + * get static ability current server supports + * + * @return static ability + */ + public Map getSupportedAbilities() { + return Collections.unmodifiableMap(supportedAbilities); } } diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java index 8df959560..c4ec32be5 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java @@ -17,7 +17,7 @@ package com.alibaba.nacos.api.ability.register.impl; import com.alibaba.nacos.api.ability.constant.AbilityKey; -import com.alibaba.nacos.api.ability.register.AbstractAbilityBitOperate; +import com.alibaba.nacos.api.ability.register.AbstractAbilityRegistry; import java.util.Map; @@ -26,7 +26,7 @@ import java.util.Map; * @description It is used to register client abilities. * @date 2022/8/31 12:32 **/ -public class ClientAbilities extends AbstractAbilityBitOperate { +public class ClientAbilities extends AbstractAbilityRegistry { private static final ClientAbilities INSTANCE = new ClientAbilities(); @@ -34,14 +34,14 @@ public class ClientAbilities extends AbstractAbilityBitOperate { /* * example: * There is a function named "compression". - * The key is "compression", the value is the offset of the flag bit of this ability in the ability table. The value should be unique. + * The key is from

AbilityKey

, the value is whether turn on. * * You can add a new public field in

AbilityKey

like: - * DATA_COMPRESSION - * This field can be used outside. + * DATA_COMPRESSION("compression", 1) + * This field can be used outside, and the offset should be unique. * * And then you need to declare the offset of the flag bit of this ability in the ability table, you can: - * abilityOffset.put(AbilityKey.DATA_COMPRESSION, 1); means that is the first bit from left to right in the table. + * supportedAbilities.put(AbilityKey.DATA_COMPRESSION, true); means that is the first bit from left to right in the table. * */ // put ability here, which you want current client supports @@ -61,12 +61,12 @@ public class ClientAbilities extends AbstractAbilityBitOperate { return INSTANCE.getAbilityBitFlags(); } - /**. - * get the ability offset for server + /** + * get static ability current server supports * - * @return ability offset + * @return static ability */ - public static Map getOffset() { - return INSTANCE.offset(); + public static Map getStaticAbilities(){ + return INSTANCE.getSupportedAbilities(); } } diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java index 2f959087d..bd01a53b8 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java @@ -17,7 +17,7 @@ package com.alibaba.nacos.api.ability.register.impl; import com.alibaba.nacos.api.ability.constant.AbilityKey; -import com.alibaba.nacos.api.ability.register.AbstractAbilityBitOperate; +import com.alibaba.nacos.api.ability.register.AbstractAbilityRegistry; import java.util.Map; @@ -26,7 +26,7 @@ import java.util.Map; * @description It is used to register server abilities. * @date 2022/8/31 12:32 **/ -public class ServerAbilities extends AbstractAbilityBitOperate { +public class ServerAbilities extends AbstractAbilityRegistry { private static final ServerAbilities INSTANCE = new ServerAbilities(); @@ -34,14 +34,14 @@ public class ServerAbilities extends AbstractAbilityBitOperate { /* * example: * There is a function named "compression". - * The key is "compression", the value is the offset of the flag bit of this ability in the ability table. The value should be unique. + * The key is from

AbilityKey

, the value is whether turn on. * * You can add a new public field in

AbilityKey

like: - * DATA_COMPRESSION - * This field can be used outside. + * DATA_COMPRESSION("compression", 1) + * This field can be used outside, and the offset should be unique. * * And then you need to declare the offset of the flag bit of this ability in the ability table, you can: - * abilityOffset.put(AbilityKey.DATA_COMPRESSION, 1); means that is the first bit from left to right in the table. + * supportedAbilities.put(AbilityKey.DATA_COMPRESSION, true); means that is the first bit from left to right in the table. * */ // put ability here, which you want current server supports @@ -61,13 +61,13 @@ public class ServerAbilities extends AbstractAbilityBitOperate { return INSTANCE.getAbilityBitFlags(); } - /**. - * get the ability offset for server + /** + * get static ability current server supports * - * @return ability offset + * @return static ability */ - public static Map getOffset() { - return INSTANCE.offset(); + public static Map getStaticAbilities(){ + return INSTANCE.getSupportedAbilities(); } } diff --git a/api/src/main/java/com/alibaba/nacos/api/utils/AbilityTableUtils.java b/api/src/main/java/com/alibaba/nacos/api/utils/AbilityTableUtils.java index a97d2a2c2..fe75aab2c 100644 --- a/api/src/main/java/com/alibaba/nacos/api/utils/AbilityTableUtils.java +++ b/api/src/main/java/com/alibaba/nacos/api/utils/AbilityTableUtils.java @@ -17,11 +17,13 @@ package com.alibaba.nacos.api.utils; import com.alibaba.nacos.api.ability.constant.AbilityKey; -import com.alibaba.nacos.api.ability.register.AbstractAbilityBitOperate; +import com.alibaba.nacos.api.ability.register.AbstractAbilityRegistry; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; @@ -69,7 +71,7 @@ public class AbilityTableUtils { * get ability table by bits * * @param bits bit flag - * @param offsetMap offset from {@link AbstractAbilityBitOperate} + * @param offsetMap offset from {@link AbstractAbilityRegistry} * @return Return the Map containing AbilityTableKey and isRunning. */ public static Map getAbilityTableBy(byte[] bits, Map offsetMap) { @@ -103,7 +105,7 @@ public class AbilityTableUtils { /**. * get ability bit table by existed ability table and offset map * - * @param offsetMap offset from {@link AbstractAbilityBitOperate} + * @param offsetMap offset from {@link AbstractAbilityRegistry} * @return Return the Map containing AbilityTableKey and isRunning. */ public static byte[] getAbilityBiTableBy(Map offsetMap, Map abilityTable) { @@ -113,4 +115,18 @@ public class AbilityTableUtils { .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); return getAbilityBitBy(res.values()); } + + /** + * get ability bit table by existed ability table and abilityKeys array + * + * @param abilityKeys abilityKeys array + * @param abilityTable existed ability table + * @return filter ability which value is false in abilityTable + */ + public static byte[] getAbilityBiTableBy(AbilityKey[] abilityKeys, Map abilityTable) { + // filter the element which abilityTable don't have or value is false + List keyList = Arrays.stream(abilityKeys).collect(Collectors.toList()); + keyList.removeIf(key -> !abilityTable.getOrDefault(key, false)); + return getAbilityBitBy(keyList.stream().map(AbilityKey::getOffset).collect(Collectors.toList())); + } } diff --git a/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java b/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java index 534b3b202..eef2427a5 100644 --- a/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java +++ b/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java @@ -20,7 +20,6 @@ import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.ability.constant.AbilityStatus; import com.alibaba.nacos.api.ability.entity.AbilityTable; import com.alibaba.nacos.api.ability.register.impl.ClientAbilities; -import com.alibaba.nacos.api.utils.AbilityTableUtils; import com.alibaba.nacos.common.ability.AbstractAbilityControlManager; import com.alibaba.nacos.common.ability.DefaultAbilityControlManager; @@ -40,7 +39,7 @@ public class ClientAbilityControlManager extends DefaultAbilityControlManager { @Override protected Map getCurrentNodeSupportAbility() { - return AbilityTableUtils.getAbilityTableBy(ClientAbilities.getBitFlags(), ClientAbilities.getOffset()); + return ClientAbilities.getStaticAbilities(); } @Override diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java index 51e77b837..96c5e1c45 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java @@ -17,7 +17,7 @@ package com.alibaba.nacos.common.ability; import com.alibaba.nacos.api.ability.constant.AbilityKey; -import com.alibaba.nacos.api.ability.register.AbstractAbilityBitOperate; +import com.alibaba.nacos.api.ability.register.AbstractAbilityRegistry; import com.alibaba.nacos.api.ability.entity.AbilityTable; import com.alibaba.nacos.common.ability.inter.AbilityControlManager; import com.alibaba.nacos.common.notify.Event; @@ -45,7 +45,7 @@ public abstract class AbstractAbilityControlManager implements AbilityControlMan /** * Abilities current supporting *

- * key: ability key from {@link AbstractAbilityBitOperate} + * key: ability key from {@link AbstractAbilityRegistry} * value: whether to turn on */ protected final Map currentRunningAbility = new ConcurrentHashMap<>(); diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/DefaultAbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/DefaultAbilityControlManager.java index 46268198f..01fc7a60b 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/DefaultAbilityControlManager.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/DefaultAbilityControlManager.java @@ -17,7 +17,7 @@ package com.alibaba.nacos.common.ability; import com.alibaba.nacos.api.ability.constant.AbilityKey; -import com.alibaba.nacos.api.ability.register.AbstractAbilityBitOperate; +import com.alibaba.nacos.api.ability.register.AbstractAbilityRegistry; import com.alibaba.nacos.api.ability.entity.AbilityTable; import com.alibaba.nacos.common.JustForTest; import com.alibaba.nacos.common.ability.handler.HandlerMapping; @@ -164,7 +164,7 @@ public abstract class DefaultAbilityControlManager extends AbstractAbilityContro /** * Remove the component instance of

handlerMappingClazz

. * - * @param abilityKey ability key from {@link AbstractAbilityBitOperate} + * @param abilityKey ability key from {@link AbstractAbilityRegistry} * @param handlerMappingClazz implement of {@link HandlerMapping} * @param lock lock for operation * @param handlerMappingsMap handler collection map @@ -242,7 +242,7 @@ public abstract class DefaultAbilityControlManager extends AbstractAbilityContro /** * Invoke componments which linked to ability key asyn. * - * @param key ability key from {@link AbstractAbilityBitOperate} + * @param key ability key from {@link AbstractAbilityRegistry} * @param isEnabled turn on/off * @param handlerMappingsMap handler collection */ @@ -254,7 +254,7 @@ public abstract class DefaultAbilityControlManager extends AbstractAbilityContro /** * Invoke componments which linked to ability key syn. * - * @param key ability key from {@link AbstractAbilityBitOperate} + * @param key ability key from {@link AbstractAbilityRegistry} * @param isEnabled turn on/off * @param handlerMappingsMap handler collection */ diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityControlManager.java index 0972ff980..304d673d4 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityControlManager.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityControlManager.java @@ -18,7 +18,7 @@ package com.alibaba.nacos.common.ability.inter; import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.ability.constant.AbilityStatus; -import com.alibaba.nacos.api.ability.register.AbstractAbilityBitOperate; +import com.alibaba.nacos.api.ability.register.AbstractAbilityRegistry; import com.alibaba.nacos.api.ability.entity.AbilityTable; import java.util.Map; @@ -34,7 +34,7 @@ public interface AbilityControlManager { * Whether the ability is supported for Connection. If the ability of current node is closed, it will return false. * * @param connectionId the connection range of ability table. - * @param abilityKey key name which comes from {@link AbstractAbilityBitOperate}. + * @param abilityKey key name which comes from {@link AbstractAbilityRegistry}. * @return whether the ability is supported in certain connection. */ AbilityStatus isSupport(String connectionId, AbilityKey abilityKey); diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityHandlerRegistry.java b/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityHandlerRegistry.java index 52d1b432f..5cbc2a8a5 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityHandlerRegistry.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityHandlerRegistry.java @@ -17,7 +17,7 @@ package com.alibaba.nacos.common.ability.inter; import com.alibaba.nacos.api.ability.constant.AbilityKey; -import com.alibaba.nacos.api.ability.register.AbstractAbilityBitOperate; +import com.alibaba.nacos.api.ability.register.AbstractAbilityRegistry; import com.alibaba.nacos.common.ability.AbstractAbilityControlManager; import com.alibaba.nacos.common.ability.handler.HandlerMapping; @@ -48,7 +48,7 @@ public interface AbilityHandlerRegistry { * Register the component which is managed by {@link AbstractAbilityControlManager}. * if you are hoping that a component will be invoked when turn on/off the ability whose key is

abilityKey

. * - * @param abilityKey component key from {@link AbstractAbilityBitOperate} + * @param abilityKey component key from {@link AbstractAbilityRegistry} * @param priority a positive number, the higher the priority is, the faster it will be called. `1` is the lowest priority. * @param handlerMapping component instance. */ @@ -57,7 +57,7 @@ public interface AbilityHandlerRegistry { /**. * Default method to register component with the lowest priority. * - * @param abilityKey component key from {@link AbstractAbilityBitOperate} + * @param abilityKey component key from {@link AbstractAbilityRegistry} * @param handlerMapping component instance. */ default void registerComponent(AbilityKey abilityKey, HandlerMapping handlerMapping) { @@ -67,7 +67,7 @@ public interface AbilityHandlerRegistry { /** * Remove the component instance of

handlerMappingClazz

. * - * @param abilityKey ability key from {@link AbstractAbilityBitOperate} + * @param abilityKey ability key from {@link AbstractAbilityRegistry} * @param handlerMappingClazz implement of {@link HandlerMapping} * @return the count of components have removed */ @@ -75,7 +75,7 @@ public interface AbilityHandlerRegistry { /** * Remove all {@link HandlerMapping} interested in the special ability. - * @param abilityKey abnility key from {@link AbstractAbilityBitOperate} + * @param abilityKey abnility key from {@link AbstractAbilityRegistry} * @return the count of components have removed */ int removeAll(AbilityKey abilityKey); diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java index c6771ab76..7519de40f 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java @@ -48,6 +48,7 @@ import io.grpc.stub.StreamObserver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Arrays; import java.util.Map; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; @@ -319,7 +320,7 @@ public abstract class GrpcClient extends RpcClient { // ability table will be null if server doesn't support ability table ServerCheckResponse serverCheckResponse = (ServerCheckResponse) response; Map abilityTable = AbilityTableUtils - .getAbilityTableBy(serverCheckResponse.getAbilities(), ServerAbilities.getOffset()); + .getAbilityTableBy(serverCheckResponse.getAbilities(), AbilityKey.offset()); AbilityTable table = new AbilityTable(); table.setServer(true) .setConnectionId(serverCheckResponse.getConnectionId()) @@ -342,7 +343,10 @@ public abstract class GrpcClient extends RpcClient { ConnectionSetupRequest conSetupRequest = new ConnectionSetupRequest(); conSetupRequest.setClientVersion(VersionUtils.getFullClientVersion()); conSetupRequest.setLabels(super.getLabels()); - conSetupRequest.setAbilityTable(getAbilityBit()); + // set ability table + byte[] bitTable = AbilityTableUtils.getAbilityBiTableBy(AbilityKey.values(), + NacosAbilityManagerHolder.getInstance().getCurrentRunningAbility()); + conSetupRequest.setAbilityTable(bitTable); conSetupRequest.setServer(isServer()); conSetupRequest.setTenant(super.getTenant()); grpcConn.sendRequest(conSetupRequest); @@ -357,13 +361,6 @@ public abstract class GrpcClient extends RpcClient { return null; } - /**. - * get ability, server or client - * - * @return bit table - */ - protected abstract byte[] getAbilityBit(); - /** * Return whether server environment * The same offset may refer to different functions in the client capability table and the server capability table. diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClusterClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClusterClient.java index fdae2aa2f..74919ba07 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClusterClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClusterClient.java @@ -16,10 +16,7 @@ package com.alibaba.nacos.common.remote.client.grpc; -import com.alibaba.nacos.api.ability.register.impl.ServerAbilities; import com.alibaba.nacos.api.common.Constants; -import com.alibaba.nacos.api.utils.AbilityTableUtils; -import com.alibaba.nacos.common.ability.discover.NacosAbilityManagerHolder; /** * gRPC client for cluster. @@ -38,12 +35,6 @@ public class GrpcClusterClient extends GrpcClient { super(name); } - @Override - public byte[] getAbilityBit() { - // calculate the ability bit table based on ability of current client - return AbilityTableUtils.getAbilityBiTableBy(ServerAbilities.getOffset(), NacosAbilityManagerHolder.getInstance().getCurrentRunningAbility()); - } - @Override protected boolean isServer() { return true; diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcSdkClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcSdkClient.java index 9c85b2b3c..46cd691f6 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcSdkClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcSdkClient.java @@ -16,10 +16,7 @@ package com.alibaba.nacos.common.remote.client.grpc; -import com.alibaba.nacos.api.ability.register.impl.ClientAbilities; import com.alibaba.nacos.api.common.Constants; -import com.alibaba.nacos.api.utils.AbilityTableUtils; -import com.alibaba.nacos.common.ability.discover.NacosAbilityManagerHolder; /** * gRPC client for sdk. @@ -38,12 +35,6 @@ public class GrpcSdkClient extends GrpcClient { super(name); } - @Override - public byte[] getAbilityBit() { - // calculate the ability bit table based on ability of current client - return AbilityTableUtils.getAbilityBiTableBy(ClientAbilities.getOffset(), NacosAbilityManagerHolder.getInstance().getCurrentRunningAbility()); - } - @Override protected boolean isServer() { return false; diff --git a/common/src/test/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClientTest.java b/common/src/test/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClientTest.java index dd6f8f965..af7104d13 100644 --- a/common/src/test/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClientTest.java +++ b/common/src/test/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClientTest.java @@ -47,10 +47,6 @@ public class GrpcClientTest { @Before public void setUp() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { grpcClient = spy(new GrpcClient("testClient") { - @Override - public byte[] getAbilityBit() { - return new byte[1]; - } @Override protected boolean isServer() { diff --git a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java index e61d39553..825faa807 100644 --- a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java +++ b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java @@ -20,7 +20,6 @@ import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.ability.constant.AbilityStatus; import com.alibaba.nacos.api.ability.entity.AbilityTable; import com.alibaba.nacos.api.ability.register.impl.ServerAbilities; -import com.alibaba.nacos.api.utils.AbilityTableUtils; import com.alibaba.nacos.common.JustForTest; import com.alibaba.nacos.common.ability.AbstractAbilityControlManager; import com.alibaba.nacos.common.ability.DefaultAbilityControlManager; @@ -78,7 +77,7 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im @Override protected Map getCurrentNodeSupportAbility() { - return AbilityTableUtils.getAbilityTableBy(ServerAbilities.getBitFlags(), ServerAbilities.getOffset()); + return ServerAbilities.getStaticAbilities(); } @Override diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java index b143834ba..b8cf7508b 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java @@ -16,8 +16,7 @@ package com.alibaba.nacos.core.remote.grpc; -import com.alibaba.nacos.api.ability.register.impl.ClientAbilities; -import com.alibaba.nacos.api.ability.register.impl.ServerAbilities; +import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.common.Constants; import com.alibaba.nacos.api.grpc.auto.BiRequestStreamGrpc; import com.alibaba.nacos.api.grpc.auto.Payload; @@ -123,15 +122,8 @@ public class GrpcBiStreamRequestAcceptor extends BiRequestStreamGrpc.BiRequestSt setUpRequest.getClientVersion(), appName, setUpRequest.getLabels()); metaInfo.setTenant(setUpRequest.getTenant()); Connection connection = new GrpcConnection(metaInfo, responseObserver, CONTEXT_KEY_CHANNEL.get()); - if (setUpRequest.isServer()) { - // if from server - connection.setAbilityTable(AbilityTableUtils.getAbilityTableBy(setUpRequest.getAbilityTable(), - ServerAbilities.getOffset())); - } else { - // if from client - connection.setAbilityTable(AbilityTableUtils.getAbilityTableBy(setUpRequest.getAbilityTable(), - ClientAbilities.getOffset())); - } + connection.setAbilityTable(AbilityTableUtils.getAbilityTableBy(setUpRequest.getAbilityTable(), + AbilityKey.offset())); boolean rejectSdkOnStarting = metaInfo.isSdkSource() && !ApplicationUtils.isStarted(); if (rejectSdkOnStarting || !connectionManager.register(connectionId, connection)) { diff --git a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityControlManagerTest.java b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityControlManagerTest.java index 16d753d4f..038cd0f82 100644 --- a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityControlManagerTest.java +++ b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityControlManagerTest.java @@ -17,6 +17,7 @@ package com.alibaba.nacos.test.ability; import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.constant.AbilityStatus; import com.alibaba.nacos.api.ability.entity.AbilityTable; import com.alibaba.nacos.common.ability.handler.HandlerMapping; import org.junit.Assert; @@ -68,8 +69,8 @@ public class AbilityControlManagerTest { table.setAbility(newTable); table.setServer(true); clientAbilityControlManager.addNewTable(table); - Assert.assertFalse(clientAbilityControlManager.isSupport("test-00001", AbilityKey.TEST_2)); - Assert.assertTrue(clientAbilityControlManager.isSupport("test-00001", AbilityKey.TEST_1)); + Assert.assertEquals(AbilityStatus.NOT_SUPPORTED, clientAbilityControlManager.isSupport("test-00001", AbilityKey.TEST_2)); + Assert.assertEquals(AbilityStatus.SUPPORTED, clientAbilityControlManager.isSupport("test-00001", AbilityKey.TEST_1)); } @Test @@ -82,8 +83,8 @@ public class AbilityControlManagerTest { table.setAbility(newTable); table.setServer(true); serverAbilityControlManager.addNewTable(table); - Assert.assertFalse(serverAbilityControlManager.isSupport("test-00001", AbilityKey.TEST_2)); - Assert.assertTrue(serverAbilityControlManager.isSupport("test-00001", AbilityKey.TEST_1)); + Assert.assertEquals(AbilityStatus.NOT_SUPPORTED, serverAbilityControlManager.isSupport("test-00001", AbilityKey.TEST_2)); + Assert.assertEquals(AbilityStatus.SUPPORTED, serverAbilityControlManager.isSupport("test-00001", AbilityKey.TEST_1)); Assert.assertTrue(serverAbilityControlManager.isClusterEnableAbility(AbilityKey.TEST_1)); Map otherServer = new HashMap<>(); From 118cde52e7432277b1c3733ed7d5a1622691a73c Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Wed, 31 Aug 2022 16:59:43 +0800 Subject: [PATCH 17/55] Separate client capability and server capability: ClientAbilities and ServerAbilities. --- .../api/ability/constant/AbilityKey.java | 129 +++++++----------- .../api/ability/constant/AbilityStatus.java | 40 ++++++ .../api/ability/entity/AbilityTable.java | 17 ++- .../register/AbstractAbilityRegistry.java | 62 +++++++++ .../register/impl/ClientAbilities.java | 72 ++++++++++ .../register/impl/ServerAbilities.java | 73 ++++++++++ .../request/ConnectionSetupRequest.java | 13 ++ .../nacos/api/utils/AbilityTableUtils.java | 44 +++++- .../api/utils/AbilityTableUtilsTest.java | 56 -------- .../ability/ClientAbilityControlManager.java | 27 ++-- .../client/config/impl/ClientWorker.java | 6 - .../client/naming/remote/TestConnection.java | 16 +++ .../AbstractAbilityControlManager.java | 26 +++- .../ability/DefaultAbilityControlManager.java | 55 ++++---- .../ability/inter/AbilityControlManager.java | 10 +- .../ability/inter/AbilityHandlerRegistry.java | 22 +-- .../listener/ClientAbilityEventListener.java | 17 ++- .../nacos/common/remote/client/RpcClient.java | 12 -- .../remote/client/RpcClientFactory.java | 2 - .../common/remote/client/grpc/GrpcClient.java | 18 ++- .../remote/client/grpc/GrpcClusterClient.java | 5 + .../remote/client/grpc/GrpcSdkClient.java | 5 + .../remote/client/grpc/GrpcClientTest.java | 6 + .../control/ServerAbilityControlManager.java | 57 ++++---- .../inte/ClusterAbilityControlSupport.java | 17 +-- .../alibaba/nacos/core/remote/Connection.java | 7 +- .../grpc/GrpcBiStreamRequestAcceptor.java | 3 +- .../core/remote/grpc/GrpcRequestAcceptor.java | 4 +- .../ability/AbilityControlManagerTest.java | 98 ++++++------- .../TestClientAbilityControlManager.java | 3 +- .../TestServerAbilityControlManager.java | 15 +- 31 files changed, 612 insertions(+), 325 deletions(-) create mode 100644 api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityStatus.java create mode 100644 api/src/main/java/com/alibaba/nacos/api/ability/register/AbstractAbilityRegistry.java create mode 100644 api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java create mode 100644 api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java delete mode 100644 api/src/test/java/com/alibaba/nacos/api/utils/AbilityTableUtilsTest.java diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java index cf194ccca..11a26e54a 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java @@ -16,96 +16,59 @@ package com.alibaba.nacos.api.ability.constant; -import com.alibaba.nacos.api.utils.AbilityTableUtils; - -import java.util.Collections; -import java.util.HashMap; +import java.util.Arrays; import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; /**. * @author Daydreamer - * @description Ability table key. It can be a replacement of {@link com.alibaba.nacos.api.ability.ServerAbilities} - * and {@link com.alibaba.nacos.api.ability.ClientAbilities}. - * @date 2022/7/12 19:23 + * @description Ability key constant. + * @date 2022/8/31 12:27 **/ -@SuppressWarnings("unchecked") -public class AbilityKey { - - private static final HashMap CURRENT_SERVER_SUPPORT_ABILITY = new HashMap<>(); - - private static final HashMap CURRENT_SERVER_ABILITY_OFFSET = new HashMap<>(); - - private static final byte[] ABILITY_BIT_FLAGS; - - private AbilityKey() { +public enum AbilityKey { + + /**. + * just for junit test + */ + TEST_1("test_1", 1), + + /**. + * just for junit test + */ + TEST_2("test_2", 2); + + /**. + * the name of a certain ability + */ + private final String name; + + /**. + * the offset in ability table + */ + private final int offset; + + AbilityKey(String name, int offset) { + this.name = name; + this.offset = offset; + } + + public String getName() { + return name; + } + + public int getOffset() { + return offset; + } + + private static final Map OFFSET_MAP; + + public static Map offset() { + return OFFSET_MAP; } static { - /* - * example: - * There is a function named "compression". - * The key is "compression", the value is the offset of the flag bit of this ability in the ability table. The value should be unique. - * - * You can add a new public static field like: - * public static final String COMPRESSION = "compression"; - * This field can be used outside. - * - * And then you need to declare the offset of the flag bit of this ability in the ability table, you can: - * CURRENT_SERVER_ABILITY_OFFSET.put("compression", 1); means that is the first bit from left to right in the table. - * - */ - - // put ability here, which you want current server supports - + OFFSET_MAP = Arrays.stream(AbilityKey.values()) + .collect(Collectors.toMap(Function.identity(), AbilityKey::getOffset)); } - - /**. - * Return ability table of current node - * But this ability is static which means that this ability table is all function this node supports if no one to ask it to close some functions. - * If you want to get what function current node is supporting, you should call AbilityControlManager#getCurrentAbility - * By the way, AbilityControlManager is singleton, you can get it by static method - * - * @return ability table - */ - public static Map getCurrentNodeSupportAbility() { - return Collections.unmodifiableMap(CURRENT_SERVER_SUPPORT_ABILITY); - } - - /**. - * Return the static ability bit table - * - * @return ability bit table - */ - public static byte[] getAbilityBitFlags() { - return ABILITY_BIT_FLAGS.clone(); - } - - /**. - * Is it a legal key - * - * @param key input - * @return whether a legal key - */ - public static boolean isLegal(String key) { - return CURRENT_SERVER_SUPPORT_ABILITY.containsKey(key); - } - - static { - // init the bits table - ABILITY_BIT_FLAGS = AbilityTableUtils.getAbilityBitBy(CURRENT_SERVER_ABILITY_OFFSET.values()); - // init the ability table, default all true - CURRENT_SERVER_ABILITY_OFFSET.forEach((k, v) -> { - CURRENT_SERVER_SUPPORT_ABILITY.put(k, Boolean.TRUE); - }); - } - - /**. - * Return the ability bit offsets - * - * @return bit offset - */ - public static Map offset() { - return CURRENT_SERVER_ABILITY_OFFSET; - } - } diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityStatus.java b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityStatus.java new file mode 100644 index 000000000..a762c0373 --- /dev/null +++ b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityStatus.java @@ -0,0 +1,40 @@ +/* + * Copyright 1999-2022 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.nacos.api.ability.constant; + +/**. + * @author Daydreamer + * @description It is used to know a certain ability whether supporting. + * @date 2022/8/31 12:27 + **/ +public enum AbilityStatus { + + /**. + * Support a certain ability + */ + SUPPORTED, + + /**. + * Not support a certain ability + */ + NOT_SUPPORTED, + + /**. + * Cannot find ability table, unknown + */ + UNKNOWN +} diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/entity/AbilityTable.java b/api/src/main/java/com/alibaba/nacos/api/ability/entity/AbilityTable.java index 921a092a7..63fda78da 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/entity/AbilityTable.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/entity/AbilityTable.java @@ -34,10 +34,10 @@ public class AbilityTable implements Cloneable { /**. * ability table - * key: name from {@link AbilityKey} + * key: name from {@link com.alibaba.nacos.api.ability.constant.AbilityKey} * value: whether to turn on */ - private Map ability; + private Map ability; /**. * whether it from a server node @@ -70,7 +70,7 @@ public class AbilityTable implements Cloneable { return this; } - public AbilityTable(String connectionId, Map ability, boolean isServer, String version) { + public AbilityTable(String connectionId, Map ability, boolean isServer, String version) { this.connectionId = connectionId; this.ability = ability; this.isServer = isServer; @@ -86,13 +86,18 @@ public class AbilityTable implements Cloneable { return this; } - public Map getAbility() { + public Map getAbility() { return ability; } - public AbilityTable setAbility(Map ability) { + public AbilityTable setAbility(Map ability) { this.ability = ability; return this; } - + + @Override + public String toString() { + return "AbilityTable{" + "connectionId='" + connectionId + '\'' + ", ability=" + ability + ", isServer=" + + isServer + ", version='" + version + '\'' + '}'; + } } diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/register/AbstractAbilityRegistry.java b/api/src/main/java/com/alibaba/nacos/api/ability/register/AbstractAbilityRegistry.java new file mode 100644 index 000000000..4ad0df43d --- /dev/null +++ b/api/src/main/java/com/alibaba/nacos/api/ability/register/AbstractAbilityRegistry.java @@ -0,0 +1,62 @@ +/* + * Copyright 1999-2022 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.nacos.api.ability.register; + +import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.utils.AbilityTableUtils; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/**. + * @author Daydreamer + * @description Operation for bit table. + * @date 2022/7/12 19:23 + **/ +public abstract class AbstractAbilityRegistry { + + protected final Map supportedAbilities = new HashMap<>(); + + private byte[] abilityBitFlag; + + /**. + * Return the static ability bit table + * + * @return ability bit table + */ + public byte[] getAbilityBitFlags() { + return abilityBitFlag.clone(); + } + + /**. + * put the bit offset to {@link AbstractAbilityRegistry#abilityBitFlag} + */ + protected void init() { + // init the bits table + abilityBitFlag = AbilityTableUtils.getAbilityBiTableBy(AbilityKey.values(), supportedAbilities); + } + + /** + * get static ability current server supports + * + * @return static ability + */ + public Map getSupportedAbilities() { + return Collections.unmodifiableMap(supportedAbilities); + } +} diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java new file mode 100644 index 000000000..c4ec32be5 --- /dev/null +++ b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java @@ -0,0 +1,72 @@ +/* + * Copyright 1999-2022 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.nacos.api.ability.register.impl; + +import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.register.AbstractAbilityRegistry; + +import java.util.Map; + +/**. + * @author Daydreamer + * @description It is used to register client abilities. + * @date 2022/8/31 12:32 + **/ +public class ClientAbilities extends AbstractAbilityRegistry { + + private static final ClientAbilities INSTANCE = new ClientAbilities(); + + { + /* + * example: + * There is a function named "compression". + * The key is from

AbilityKey

, the value is whether turn on. + * + * You can add a new public field in

AbilityKey

like: + * DATA_COMPRESSION("compression", 1) + * This field can be used outside, and the offset should be unique. + * + * And then you need to declare the offset of the flag bit of this ability in the ability table, you can: + * supportedAbilities.put(AbilityKey.DATA_COMPRESSION, true); means that is the first bit from left to right in the table. + * + */ + // put ability here, which you want current client supports + } + + private ClientAbilities() { + // put key to bit offset + init(); + } + + /**. + * get the ability offset for server + * + * @return ability offset + */ + public static byte[] getBitFlags() { + return INSTANCE.getAbilityBitFlags(); + } + + /** + * get static ability current server supports + * + * @return static ability + */ + public static Map getStaticAbilities(){ + return INSTANCE.getSupportedAbilities(); + } +} diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java new file mode 100644 index 000000000..bd01a53b8 --- /dev/null +++ b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java @@ -0,0 +1,73 @@ +/* + * Copyright 1999-2022 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.nacos.api.ability.register.impl; + +import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.register.AbstractAbilityRegistry; + +import java.util.Map; + +/**. + * @author Daydreamer + * @description It is used to register server abilities. + * @date 2022/8/31 12:32 + **/ +public class ServerAbilities extends AbstractAbilityRegistry { + + private static final ServerAbilities INSTANCE = new ServerAbilities(); + + { + /* + * example: + * There is a function named "compression". + * The key is from

AbilityKey

, the value is whether turn on. + * + * You can add a new public field in

AbilityKey

like: + * DATA_COMPRESSION("compression", 1) + * This field can be used outside, and the offset should be unique. + * + * And then you need to declare the offset of the flag bit of this ability in the ability table, you can: + * supportedAbilities.put(AbilityKey.DATA_COMPRESSION, true); means that is the first bit from left to right in the table. + * + */ + // put ability here, which you want current server supports + } + + private ServerAbilities() { + // put key to bit offset + init(); + } + + /**. + * get bit table + * + * @return ability offset + */ + public static byte[] getBitFlags() { + return INSTANCE.getAbilityBitFlags(); + } + + /** + * get static ability current server supports + * + * @return static ability + */ + public static Map getStaticAbilities(){ + return INSTANCE.getSupportedAbilities(); + } + +} diff --git a/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequest.java b/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequest.java index 046a897a4..15b3c35d5 100644 --- a/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequest.java +++ b/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequest.java @@ -35,6 +35,19 @@ public class ConnectionSetupRequest extends InternalRequest { private byte[] abilityTable; + /**. + * server will resolve {@link ConnectionSetupRequest#abilityTable} to server abilities, or to client abilities + */ + private boolean isServer; + + public boolean isServer() { + return isServer; + } + + public void setServer(boolean server) { + isServer = server; + } + public ConnectionSetupRequest() { } diff --git a/api/src/main/java/com/alibaba/nacos/api/utils/AbilityTableUtils.java b/api/src/main/java/com/alibaba/nacos/api/utils/AbilityTableUtils.java index 11ad28cc0..fe75aab2c 100644 --- a/api/src/main/java/com/alibaba/nacos/api/utils/AbilityTableUtils.java +++ b/api/src/main/java/com/alibaba/nacos/api/utils/AbilityTableUtils.java @@ -17,12 +17,16 @@ package com.alibaba.nacos.api.utils; import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.register.AbstractAbilityRegistry; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; /**. * @author Daydreamer @@ -67,18 +71,18 @@ public class AbilityTableUtils { * get ability table by bits * * @param bits bit flag - * @param offsetMap offset from {@link AbilityKey} + * @param offsetMap offset from {@link AbstractAbilityRegistry} * @return Return the Map containing AbilityTableKey and isRunning. */ - public static Map getAbilityTableBy(byte[] bits, Map offsetMap) { + public static Map getAbilityTableBy(byte[] bits, Map offsetMap) { if (bits == null || offsetMap.size() == 0) { return Collections.emptyMap(); } int length = bits.length; - Set> entries = offsetMap.entrySet(); - Map res = new HashMap<>(offsetMap.size()); - for (Map.Entry entry : entries) { - String abilityKey = entry.getKey(); + Set> entries = offsetMap.entrySet(); + Map res = new HashMap<>(offsetMap.size()); + for (Map.Entry entry : entries) { + AbilityKey abilityKey = entry.getKey(); Integer offset = entry.getValue(); // if not exists int index = offset / 8 + (offset % 8 == 0 ? -1 : 0); @@ -97,4 +101,32 @@ public class AbilityTableUtils { } return res; } + + /**. + * get ability bit table by existed ability table and offset map + * + * @param offsetMap offset from {@link AbstractAbilityRegistry} + * @return Return the Map containing AbilityTableKey and isRunning. + */ + public static byte[] getAbilityBiTableBy(Map offsetMap, Map abilityTable) { + // filter the element which abilityTable don't have or value is false + Map res = offsetMap.entrySet().stream() + .filter(item -> abilityTable.getOrDefault(item.getKey(), false)) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + return getAbilityBitBy(res.values()); + } + + /** + * get ability bit table by existed ability table and abilityKeys array + * + * @param abilityKeys abilityKeys array + * @param abilityTable existed ability table + * @return filter ability which value is false in abilityTable + */ + public static byte[] getAbilityBiTableBy(AbilityKey[] abilityKeys, Map abilityTable) { + // filter the element which abilityTable don't have or value is false + List keyList = Arrays.stream(abilityKeys).collect(Collectors.toList()); + keyList.removeIf(key -> !abilityTable.getOrDefault(key, false)); + return getAbilityBitBy(keyList.stream().map(AbilityKey::getOffset).collect(Collectors.toList())); + } } diff --git a/api/src/test/java/com/alibaba/nacos/api/utils/AbilityTableUtilsTest.java b/api/src/test/java/com/alibaba/nacos/api/utils/AbilityTableUtilsTest.java deleted file mode 100644 index c2fea2c40..000000000 --- a/api/src/test/java/com/alibaba/nacos/api/utils/AbilityTableUtilsTest.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 1999-2022 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.nacos.api.utils; - -import org.junit.Assert; -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - -public class AbilityTableUtilsTest { - - @Test - public void testGetByteArray() { - Map offset = new HashMap<>(); - offset.put("a", 1); - offset.put("b", 2); - offset.put("c", 10); - offset.put("d", 127); - byte[] abilityBitBy = AbilityTableUtils.getAbilityBitBy(offset.values()); - Assert.assertEquals(16, abilityBitBy.length); - Assert.assertEquals((byte) (3 << 6), abilityBitBy[0]); - Assert.assertEquals((byte) (1 << 6), abilityBitBy[1]); - } - - @Test - public void testGetAbilityTable() { - Map offset = new HashMap<>(); - offset.put("a", 1); - offset.put("b", 2); - offset.put("c", 10); - offset.put("d", 127); - byte[] abilityBitBy = AbilityTableUtils.getAbilityBitBy(offset.values()); - Map abilityTableBy = AbilityTableUtils.getAbilityTableBy(abilityBitBy, offset); - Assert.assertEquals(4, abilityTableBy.size()); - Assert.assertEquals(Boolean.TRUE, abilityTableBy.get("a")); - Assert.assertEquals(Boolean.TRUE, abilityTableBy.get("b")); - Assert.assertEquals(Boolean.TRUE, abilityTableBy.get("c")); - Assert.assertEquals(Boolean.TRUE, abilityTableBy.get("d")); - Assert.assertEquals(Boolean.FALSE, abilityTableBy.getOrDefault("asdasd", false)); - } -} diff --git a/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java b/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java index 9d39574f8..eef2427a5 100644 --- a/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java +++ b/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java @@ -16,11 +16,15 @@ package com.alibaba.nacos.client.ability; +import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.constant.AbilityStatus; import com.alibaba.nacos.api.ability.entity.AbilityTable; +import com.alibaba.nacos.api.ability.register.impl.ClientAbilities; import com.alibaba.nacos.common.ability.AbstractAbilityControlManager; import com.alibaba.nacos.common.ability.DefaultAbilityControlManager; import java.util.Collections; +import java.util.Map; import java.util.Optional; /**. @@ -34,17 +38,20 @@ public class ClientAbilityControlManager extends DefaultAbilityControlManager { } @Override - public boolean isSupport(String connectionId, String abilityKey) { - Boolean isRunning = currentRunningAbility.getOrDefault(abilityKey, false); - if (!isRunning) { - return false; - } + protected Map getCurrentNodeSupportAbility() { + return ClientAbilities.getStaticAbilities(); + } + + @Override + public AbilityStatus isSupport(String connectionId, AbilityKey abilityKey) { AbilityTable abilityTable = nodeAbilityTable.get(connectionId); - // false if null - return abilityTable != null - && Optional.ofNullable(abilityTable.getAbility()) - .orElse(Collections.emptyMap()) - .getOrDefault(abilityKey, false); + if (abilityTable == null) { + return AbilityStatus.UNKNOWN; + } + Boolean isSupport = Optional.ofNullable(abilityTable.getAbility()) + .orElse(Collections.emptyMap()) + .getOrDefault(abilityKey, false); + return isSupport ? AbilityStatus.SUPPORTED : AbilityStatus.NOT_SUPPORTED; } @Override diff --git a/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java b/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java index fc450b990..a227d537e 100644 --- a/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java +++ b/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java @@ -17,7 +17,6 @@ package com.alibaba.nacos.client.config.impl; import com.alibaba.nacos.api.PropertyKeyConst; -import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.common.Constants; import com.alibaba.nacos.api.config.ConfigType; import com.alibaba.nacos.api.config.listener.Listener; @@ -885,7 +884,6 @@ public class ClientWorker implements Closeable { if (rpcClient.isWaitInitiated()) { initRpcClientHandler(rpcClient); rpcClient.setTenant(getTenant()); - rpcClient.clientAbilities(initAbilities()); rpcClient.start(); } @@ -893,10 +891,6 @@ public class ClientWorker implements Closeable { } } - - private byte[] initAbilities() { - return AbilityKey.getAbilityBitFlags(); - } /** * build config string. diff --git a/client/src/test/java/com/alibaba/nacos/client/naming/remote/TestConnection.java b/client/src/test/java/com/alibaba/nacos/client/naming/remote/TestConnection.java index 6d02c962d..43fc088fd 100644 --- a/client/src/test/java/com/alibaba/nacos/client/naming/remote/TestConnection.java +++ b/client/src/test/java/com/alibaba/nacos/client/naming/remote/TestConnection.java @@ -1,3 +1,19 @@ +/* + * Copyright 1999-2022 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.nacos.client.naming.remote; import com.alibaba.nacos.api.exception.NacosException; diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java index e1723a9e2..96c5e1c45 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java @@ -17,6 +17,7 @@ package com.alibaba.nacos.common.ability; import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.register.AbstractAbilityRegistry; import com.alibaba.nacos.api.ability.entity.AbilityTable; import com.alibaba.nacos.common.ability.inter.AbilityControlManager; import com.alibaba.nacos.common.notify.Event; @@ -26,6 +27,7 @@ import org.slf4j.LoggerFactory; import java.util.HashMap; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReentrantLock; @@ -43,10 +45,10 @@ public abstract class AbstractAbilityControlManager implements AbilityControlMan /** * Abilities current supporting *

- * key: ability key from {@link AbilityKey} + * key: ability key from {@link AbstractAbilityRegistry} * value: whether to turn on */ - protected final Map currentRunningAbility = new ConcurrentHashMap<>(); + protected final Map currentRunningAbility = new ConcurrentHashMap<>(); /** * Ability table collections @@ -64,10 +66,17 @@ public abstract class AbstractAbilityControlManager implements AbilityControlMan // register events registerAbilityEvent(); // put abilities - currentRunningAbility.putAll(AbilityKey.getCurrentNodeSupportAbility()); + currentRunningAbility.putAll(getCurrentNodeSupportAbility()); // initialize init(); } + + /** + * This is a hook for subclass to init current node ability + * + * @return current node ability + */ + protected abstract Map getCurrentNodeSupportAbility(); private void registerAbilityEvent(){ @@ -83,7 +92,7 @@ public abstract class AbstractAbilityControlManager implements AbilityControlMan * @return is running */ @Override - public boolean isCurrentNodeAbilityRunning(String abilityKey) { + public boolean isCurrentNodeAbilityRunning(AbilityKey abilityKey) { return currentRunningAbility.getOrDefault(abilityKey, false); } @@ -109,6 +118,13 @@ public abstract class AbstractAbilityControlManager implements AbilityControlMan // hook method add(table); // add to node + Set abilityKeys = table.getAbility().keySet(); + Map clientAbilities = table.getAbility(); + abilityKeys.forEach(abilityKey -> { + Boolean res = currentRunningAbility.getOrDefault(abilityKey, false); + Boolean coming = clientAbilities.getOrDefault(abilityKey, false); + clientAbilities.put(abilityKey, res && coming); + }); nodeAbilityTable.put(connectionId, table); } finally { lockForAbilityTable.unlock(); @@ -204,7 +220,7 @@ public abstract class AbstractAbilityControlManager implements AbilityControlMan * @return ability table */ @Override - public Map getCurrentRunningAbility() { + public Map getCurrentRunningAbility() { return new HashMap<>(this.currentRunningAbility); } diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/DefaultAbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/DefaultAbilityControlManager.java index b3012392e..01fc7a60b 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/DefaultAbilityControlManager.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/DefaultAbilityControlManager.java @@ -17,6 +17,7 @@ package com.alibaba.nacos.common.ability; import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.register.AbstractAbilityRegistry; import com.alibaba.nacos.api.ability.entity.AbilityTable; import com.alibaba.nacos.common.JustForTest; import com.alibaba.nacos.common.ability.handler.HandlerMapping; @@ -46,16 +47,18 @@ import java.util.concurrent.locks.ReentrantLock; * @description It is a relatively complete capability control center implementation. * @date 2022/7/12 19:18 **/ +@SuppressWarnings("PMD.AbstractClassShouldStartWithAbstractNamingRule") public abstract class DefaultAbilityControlManager extends AbstractAbilityControlManager implements AbilityHandlerRegistry { private static final Logger LOGGER = LoggerFactory.getLogger(DefaultAbilityControlManager.class); - /** - * . These handlers will be invoked when the flag of ability change key: ability key from {@link AbilityKey} value: - * componments who want to be invoked if its interested ability turn on/off + /**. + * These handlers will be invoked when the flag of ability change key: + * ability key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey} value: + * components who want to be invoked if its interested ability turn on/off */ - private final Map> handlerMappings = new ConcurrentHashMap<>(); + private final Map> handlerMappings = new ConcurrentHashMap<>(); /**. * run for HandlerMapping @@ -76,7 +79,7 @@ public abstract class DefaultAbilityControlManager extends AbstractAbilityContro * @return if turn success */ @Override - public boolean enableCurrentNodeAbility(String abilityKey) { + public boolean enableCurrentNodeAbility(AbilityKey abilityKey) { return doTurn(true, abilityKey); } @@ -87,7 +90,7 @@ public abstract class DefaultAbilityControlManager extends AbstractAbilityContro * @return if turn success */ @Override - public boolean disableCurrentNodeAbility(String abilityKey) { + public boolean disableCurrentNodeAbility(AbilityKey abilityKey) { return doTurn(false, abilityKey); } @@ -98,7 +101,7 @@ public abstract class DefaultAbilityControlManager extends AbstractAbilityContro * @param abilityKey ability key from {@link AbilityKey} * @return if turn success */ - private boolean doTurn(boolean isOn, String abilityKey) { + private boolean doTurn(boolean isOn, AbilityKey abilityKey) { Boolean isEnabled = currentRunningAbility.get(abilityKey); // if not supporting this key if (isEnabled == null) { @@ -130,12 +133,12 @@ public abstract class DefaultAbilityControlManager extends AbstractAbilityContro * @param handlerMapping component instance. */ @Override - public void registerComponent(String abilityKey, HandlerMapping handlerMapping, int priority) { + public void registerComponent(AbilityKey abilityKey, HandlerMapping handlerMapping, int priority) { doRegisterComponent(abilityKey, handlerMapping, this.handlerMappings, lockForHandlerMappings, priority, currentRunningAbility); } @Override - public int removeComponent(String abilityKey, Class handlerMappingClazz) { + public int removeComponent(AbilityKey abilityKey, Class handlerMappingClazz) { return doRemove(abilityKey, handlerMappingClazz, lockForHandlerMappings, handlerMappings); } @@ -161,14 +164,14 @@ public abstract class DefaultAbilityControlManager extends AbstractAbilityContro /** * Remove the component instance of

handlerMappingClazz

. * - * @param abilityKey ability key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey} + * @param abilityKey ability key from {@link AbstractAbilityRegistry} * @param handlerMappingClazz implement of {@link HandlerMapping} * @param lock lock for operation * @param handlerMappingsMap handler collection map * @return the count of components have removed */ - protected int doRemove(String abilityKey, Class handlerMappingClazz, Lock lock, - Map> handlerMappingsMap) { + protected int doRemove(AbilityKey abilityKey, Class handlerMappingClazz, Lock lock, + Map> handlerMappingsMap) { List handlerMappings = handlerMappingsMap.get(abilityKey); if (CollectionUtils.isEmpty(handlerMappings)) { return 0; @@ -190,7 +193,7 @@ public abstract class DefaultAbilityControlManager extends AbstractAbilityContro } @Override - public int removeAll(String abilityKey) { + public int removeAll(AbilityKey abilityKey) { List remove = this.handlerMappings.remove(abilityKey); return Optional.ofNullable(remove).orElse(Collections.emptyList()).size(); } @@ -204,9 +207,9 @@ public abstract class DefaultAbilityControlManager extends AbstractAbilityContro * @param lockForHandlerMappings lock to ensure concurrency * @param abilityTable behavioral basis of handler */ - protected void doRegisterComponent(String abilityKey, HandlerMapping handlerMapping, - Map> handlerMappings, Lock lockForHandlerMappings, - int priority, Map abilityTable) { + protected void doRegisterComponent(AbilityKey abilityKey, HandlerMapping handlerMapping, + Map> handlerMappings, Lock lockForHandlerMappings, + int priority, Map abilityTable) { if (!currentRunningAbility.containsKey(abilityKey)) { LOGGER.warn("[AbilityHandlePostProcessor] Failed to register processor: {}, because illegal key!", handlerMapping.getClass().getSimpleName()); @@ -239,24 +242,24 @@ public abstract class DefaultAbilityControlManager extends AbstractAbilityContro /** * Invoke componments which linked to ability key asyn. * - * @param key ability key from {@link AbilityKey} + * @param key ability key from {@link AbstractAbilityRegistry} * @param isEnabled turn on/off * @param handlerMappingsMap handler collection */ - protected void triggerHandlerMappingAsyn(String key, boolean isEnabled, - Map> handlerMappingsMap) { + protected void triggerHandlerMappingAsyn(AbilityKey key, boolean isEnabled, + Map> handlerMappingsMap) { simpleThreadPool.execute(() -> doTriggerSyn(key, isEnabled, handlerMappingsMap)); } /** * Invoke componments which linked to ability key syn. * - * @param key ability key from {@link AbilityKey} + * @param key ability key from {@link AbstractAbilityRegistry} * @param isEnabled turn on/off * @param handlerMappingsMap handler collection */ - protected void doTriggerSyn(String key, boolean isEnabled, - Map> handlerMappingsMap) { + protected void doTriggerSyn(AbilityKey key, boolean isEnabled, + Map> handlerMappingsMap) { List handlerWithPriorities = handlerMappingsMap.get(key); // return if empty if (CollectionUtils.isEmpty(handlerWithPriorities)) { @@ -281,7 +284,7 @@ public abstract class DefaultAbilityControlManager extends AbstractAbilityContro } @JustForTest - protected Map> handlerMapping() { + protected Map> handlerMapping() { return this.handlerMappings; } @@ -318,17 +321,17 @@ public abstract class DefaultAbilityControlManager extends AbstractAbilityContro private static final long serialVersionUID = -1232411212311111L; - private String abilityKey; + private AbilityKey abilityKey; private boolean isOn; private AbilityUpdateEvent(){} - public String getAbilityKey() { + public AbilityKey getAbilityKey() { return abilityKey; } - public void setAbilityKey(String abilityKey) { + public void setAbilityKey(AbilityKey abilityKey) { this.abilityKey = abilityKey; } diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityControlManager.java index 75aac8893..304d673d4 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityControlManager.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityControlManager.java @@ -17,6 +17,8 @@ package com.alibaba.nacos.common.ability.inter; import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.constant.AbilityStatus; +import com.alibaba.nacos.api.ability.register.AbstractAbilityRegistry; import com.alibaba.nacos.api.ability.entity.AbilityTable; import java.util.Map; @@ -32,10 +34,10 @@ public interface AbilityControlManager { * Whether the ability is supported for Connection. If the ability of current node is closed, it will return false. * * @param connectionId the connection range of ability table. - * @param abilityKey key name which comes from {@link AbilityKey}. + * @param abilityKey key name which comes from {@link AbstractAbilityRegistry}. * @return whether the ability is supported in certain connection. */ - boolean isSupport(String connectionId, String abilityKey); + AbilityStatus isSupport(String connectionId, AbilityKey abilityKey); /** * Whether the ability current node supporting is running. Return false if current node doesn't support. @@ -43,7 +45,7 @@ public interface AbilityControlManager { * @param abilityKey ability key * @return is running */ - boolean isCurrentNodeAbilityRunning(String abilityKey); + boolean isCurrentNodeAbilityRunning(AbilityKey abilityKey); /** * Register a new ability table. @@ -72,7 +74,7 @@ public interface AbilityControlManager { * * @return ability table */ - Map getCurrentRunningAbility(); + Map getCurrentRunningAbility(); /**. * Initialize the manager diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityHandlerRegistry.java b/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityHandlerRegistry.java index c27254784..5cbc2a8a5 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityHandlerRegistry.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityHandlerRegistry.java @@ -16,6 +16,8 @@ package com.alibaba.nacos.common.ability.inter; +import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.register.AbstractAbilityRegistry; import com.alibaba.nacos.common.ability.AbstractAbilityControlManager; import com.alibaba.nacos.common.ability.handler.HandlerMapping; @@ -32,7 +34,7 @@ public interface AbilityHandlerRegistry { * @param abilityKey ability key * @return if turn success */ - boolean enableCurrentNodeAbility(String abilityKey); + boolean enableCurrentNodeAbility(AbilityKey abilityKey); /**. * Turn off the ability whose key is

abilityKey

@@ -40,42 +42,42 @@ public interface AbilityHandlerRegistry { * @param abilityKey ability key * @return if turn success */ - boolean disableCurrentNodeAbility(String abilityKey); + boolean disableCurrentNodeAbility(AbilityKey abilityKey); /**. * Register the component which is managed by {@link AbstractAbilityControlManager}. * if you are hoping that a component will be invoked when turn on/off the ability whose key is

abilityKey

. * - * @param abilityKey component key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey} + * @param abilityKey component key from {@link AbstractAbilityRegistry} * @param priority a positive number, the higher the priority is, the faster it will be called. `1` is the lowest priority. * @param handlerMapping component instance. */ - void registerComponent(String abilityKey, HandlerMapping handlerMapping, int priority); + void registerComponent(AbilityKey abilityKey, HandlerMapping handlerMapping, int priority); /**. * Default method to register component with the lowest priority. * - * @param abilityKey component key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey} + * @param abilityKey component key from {@link AbstractAbilityRegistry} * @param handlerMapping component instance. */ - default void registerComponent(String abilityKey, HandlerMapping handlerMapping) { + default void registerComponent(AbilityKey abilityKey, HandlerMapping handlerMapping) { registerComponent(abilityKey, handlerMapping, 1); } /** * Remove the component instance of

handlerMappingClazz

. * - * @param abilityKey ability key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey} + * @param abilityKey ability key from {@link AbstractAbilityRegistry} * @param handlerMappingClazz implement of {@link HandlerMapping} * @return the count of components have removed */ - int removeComponent(String abilityKey, Class handlerMappingClazz); + int removeComponent(AbilityKey abilityKey, Class handlerMappingClazz); /** * Remove all {@link HandlerMapping} interested in the special ability. - * @param abilityKey abnility key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey} + * @param abilityKey abnility key from {@link AbstractAbilityRegistry} * @return the count of components have removed */ - int removeAll(String abilityKey); + int removeAll(AbilityKey abilityKey); } diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/listener/ClientAbilityEventListener.java b/common/src/main/java/com/alibaba/nacos/common/ability/listener/ClientAbilityEventListener.java index 0c2004365..0093709c5 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/listener/ClientAbilityEventListener.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/listener/ClientAbilityEventListener.java @@ -1,5 +1,20 @@ -package com.alibaba.nacos.common.ability.listener; +/* + * Copyright 1999-2022 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.nacos.common.ability.listener; import com.alibaba.nacos.common.ability.discover.NacosAbilityManagerHolder; import com.alibaba.nacos.common.remote.client.Connection; diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java index 9db2e1e84..59d8134ec 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java @@ -90,8 +90,6 @@ public abstract class RpcClient implements Closeable { private static final long DEFAULT_TIMEOUT_MILLS = 3000L; - protected byte[] clientAbilities; - /** * default keep alive time 5s. */ @@ -133,16 +131,6 @@ public abstract class RpcClient implements Closeable { } } - /** - * init client abilities. - * - * @param clientAbilities clientAbilities. - */ - public RpcClient clientAbilities(byte[] clientAbilities) { - this.clientAbilities = clientAbilities; - return this; - } - /** * init server list factory. only can init once. * diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClientFactory.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClientFactory.java index 8b40c9cfb..2d71b9e46 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClientFactory.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClientFactory.java @@ -16,7 +16,6 @@ package com.alibaba.nacos.common.remote.client; -import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.common.remote.ConnectionType; import com.alibaba.nacos.common.remote.client.grpc.GrpcClient; @@ -140,7 +139,6 @@ public class RpcClientFactory { client.setThreadPoolCoreSize(threadPoolCoreSize); client.setThreadPoolMaxSize(threadPoolMaxSize); client.labels(labels); - client.clientAbilities(AbilityKey.getAbilityBitFlags()); return client; }); } diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java index a68c81e58..7519de40f 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java @@ -18,6 +18,7 @@ package com.alibaba.nacos.common.remote.client.grpc; import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.ability.entity.AbilityTable; +import com.alibaba.nacos.api.ability.register.impl.ServerAbilities; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.grpc.auto.BiRequestStreamGrpc; import com.alibaba.nacos.api.grpc.auto.Payload; @@ -47,6 +48,7 @@ import io.grpc.stub.StreamObserver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Arrays; import java.util.Map; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; @@ -317,7 +319,7 @@ public abstract class GrpcClient extends RpcClient { // submit ability table as soon as possible // ability table will be null if server doesn't support ability table ServerCheckResponse serverCheckResponse = (ServerCheckResponse) response; - Map abilityTable = AbilityTableUtils + Map abilityTable = AbilityTableUtils .getAbilityTableBy(serverCheckResponse.getAbilities(), AbilityKey.offset()); AbilityTable table = new AbilityTable(); table.setServer(true) @@ -341,7 +343,11 @@ public abstract class GrpcClient extends RpcClient { ConnectionSetupRequest conSetupRequest = new ConnectionSetupRequest(); conSetupRequest.setClientVersion(VersionUtils.getFullClientVersion()); conSetupRequest.setLabels(super.getLabels()); - conSetupRequest.setAbilityTable(super.clientAbilities == null ? AbilityKey.getAbilityBitFlags() : clientAbilities); + // set ability table + byte[] bitTable = AbilityTableUtils.getAbilityBiTableBy(AbilityKey.values(), + NacosAbilityManagerHolder.getInstance().getCurrentRunningAbility()); + conSetupRequest.setAbilityTable(bitTable); + conSetupRequest.setServer(isServer()); conSetupRequest.setTenant(super.getTenant()); grpcConn.sendRequest(conSetupRequest); //wait to register connection setup @@ -355,6 +361,14 @@ public abstract class GrpcClient extends RpcClient { return null; } + /** + * Return whether server environment + * The same offset may refer to different functions in the client capability table and the server capability table. + * + * @return whether server environment + */ + protected abstract boolean isServer(); + } diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClusterClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClusterClient.java index 7b63653b6..74919ba07 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClusterClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClusterClient.java @@ -35,6 +35,11 @@ public class GrpcClusterClient extends GrpcClient { super(name); } + @Override + protected boolean isServer() { + return true; + } + @Override public int rpcPortOffset() { return Integer.parseInt(System.getProperty(NACOS_SERVER_GRPC_PORT_OFFSET_KEY, diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcSdkClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcSdkClient.java index 34cf40824..46cd691f6 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcSdkClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcSdkClient.java @@ -35,6 +35,11 @@ public class GrpcSdkClient extends GrpcClient { super(name); } + @Override + protected boolean isServer() { + return false; + } + @Override public int rpcPortOffset() { return Integer.parseInt(System.getProperty(NACOS_SERVER_GRPC_PORT_OFFSET_KEY, diff --git a/common/src/test/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClientTest.java b/common/src/test/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClientTest.java index 5a81ab3ed..af7104d13 100644 --- a/common/src/test/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClientTest.java +++ b/common/src/test/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClientTest.java @@ -47,6 +47,12 @@ public class GrpcClientTest { @Before public void setUp() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { grpcClient = spy(new GrpcClient("testClient") { + + @Override + protected boolean isServer() { + return false; + } + @Override public int rpcPortOffset() { return 1000; diff --git a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java index 44a01258f..825faa807 100644 --- a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java +++ b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java @@ -16,7 +16,10 @@ package com.alibaba.nacos.core.ability.control; +import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.constant.AbilityStatus; import com.alibaba.nacos.api.ability.entity.AbilityTable; +import com.alibaba.nacos.api.ability.register.impl.ServerAbilities; import com.alibaba.nacos.common.JustForTest; import com.alibaba.nacos.common.ability.AbstractAbilityControlManager; import com.alibaba.nacos.common.ability.DefaultAbilityControlManager; @@ -48,7 +51,7 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im /**. * ability for cluster */ - private final Map clusterAbilityTable = new ConcurrentHashMap<>(); + private final Map clusterAbilityTable = new ConcurrentHashMap<>(); /**. * ability for server @@ -58,7 +61,7 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im /** * components for cluster. these will be invoked if cluster ability table changes. */ - private final Map> clusterHandlerMapping = new ConcurrentHashMap<>(); + private final Map> clusterHandlerMapping = new ConcurrentHashMap<>(); private Lock lockForClusterComponents = new ReentrantLock(); @@ -73,17 +76,19 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im } @Override - public boolean isSupport(String connectionId, String abilityKey) { - Boolean isRunning = currentRunningAbility.getOrDefault(abilityKey, false); - if (!isRunning) { - return false; - } + protected Map getCurrentNodeSupportAbility() { + return ServerAbilities.getStaticAbilities(); + } + + @Override + public AbilityStatus isSupport(String connectionId, AbilityKey abilityKey) { AbilityTable abilityTable = nodeAbilityTable.get(connectionId); - // false if null - return abilityTable != null - && Optional.ofNullable(abilityTable.getAbility()) - .orElse(Collections.emptyMap()) - .getOrDefault(abilityKey, false); + if (abilityTable == null) { + return AbilityStatus.UNKNOWN; + } + Boolean isSupport = Optional.ofNullable(abilityTable.getAbility()).orElse(Collections.emptyMap()) + .getOrDefault(abilityKey, false); + return isSupport ? AbilityStatus.SUPPORTED : AbilityStatus.NOT_SUPPORTED; } /**. @@ -93,12 +98,12 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im * @return whether it is turn on */ @Override - public boolean isClusterEnableAbility(String abilityKey) { + public boolean isClusterEnableAbility(AbilityKey abilityKey) { return clusterAbilityTable.getOrDefault(abilityKey, Boolean.FALSE); } @Override - public Map getClusterAbility() { + public Map getClusterAbility() { return Collections.unmodifiableMap(clusterAbilityTable); } @@ -110,17 +115,17 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im * @param handlerMapping component */ @Override - public void registerComponentForCluster(String abilityKey, HandlerMapping handlerMapping, int priority) { + public void registerComponentForCluster(AbilityKey abilityKey, HandlerMapping handlerMapping, int priority) { doRegisterComponent(abilityKey, handlerMapping, this.clusterHandlerMapping, lockForClusterComponents, priority, clusterAbilityTable); } @Override - public int removeClusterComponent(String abilityKey, Class handlerMappingClazz) { + public int removeClusterComponent(AbilityKey abilityKey, Class handlerMappingClazz) { return doRemove(abilityKey, handlerMappingClazz, lockForClusterComponents, clusterHandlerMapping); } @Override - public int removeAllForCluster(String abilityKey) { + public int removeAllForCluster(AbilityKey abilityKey) { List remove = this.clusterHandlerMapping.remove(abilityKey); return Optional.ofNullable(remove).orElse(Collections.emptyList()).size(); } @@ -134,8 +139,8 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im if (isServer) { serversAbilityTable.put(table.getConnectionId(), table); // enter cluster - Map nodeAbility = table.getAbility(); - Set keySet = clusterAbilityTable.keySet(); + Map nodeAbility = table.getAbility(); + Set keySet = clusterAbilityTable.keySet(); keySet.forEach(abilityKey -> { Boolean isEnabled = clusterAbilityTable.get(abilityKey); Boolean val = nodeAbility.getOrDefault(abilityKey, Boolean.FALSE); @@ -153,7 +158,7 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im } } - private ClusterAbilityUpdateEvent buildClusterEvent(String abilityKey, boolean isOn) { + private ClusterAbilityUpdateEvent buildClusterEvent(AbilityKey abilityKey, boolean isOn) { // notify ClusterAbilityUpdateEvent event = new ClusterAbilityUpdateEvent(); event.setAbilityKey(abilityKey); @@ -176,7 +181,7 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im serversAbilityTable.remove(connectionId); // remove from cluster if (MapUtil.isNotEmpty(serversAbilityTable)) { - Set keySet = clusterAbilityTable.keySet(); + Set keySet = clusterAbilityTable.keySet(); keySet.forEach(abilityKey -> { Boolean isEnabled = clusterAbilityTable.getOrDefault(abilityKey, Boolean.FALSE); // nothing to do if enabled @@ -219,17 +224,17 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im private static final long serialVersionUID = -122222411212200111L; - private String abilityKey; + private AbilityKey abilityKey; private boolean isOn; private ClusterAbilityUpdateEvent(){} - public String getAbilityKey() { + public AbilityKey getAbilityKey() { return abilityKey; } - public void setAbilityKey(String abilityKey) { + public void setAbilityKey(AbilityKey abilityKey) { this.abilityKey = abilityKey; } @@ -244,12 +249,12 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im } @JustForTest - protected void setClusterAbilityTable(Map map) { + protected void setClusterAbilityTable(Map map) { clusterAbilityTable.putAll(map); } @JustForTest - protected Map> clusterHandlerMapping() { + protected Map> clusterHandlerMapping() { return this.clusterHandlerMapping; } diff --git a/core/src/main/java/com/alibaba/nacos/core/ability/inte/ClusterAbilityControlSupport.java b/core/src/main/java/com/alibaba/nacos/core/ability/inte/ClusterAbilityControlSupport.java index 1150b2005..9b989a078 100644 --- a/core/src/main/java/com/alibaba/nacos/core/ability/inte/ClusterAbilityControlSupport.java +++ b/core/src/main/java/com/alibaba/nacos/core/ability/inte/ClusterAbilityControlSupport.java @@ -16,6 +16,7 @@ package com.alibaba.nacos.core.ability.inte; +import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.common.ability.handler.HandlerMapping; import com.alibaba.nacos.common.ability.inter.AbilityControlManager; @@ -33,7 +34,7 @@ public interface ClusterAbilityControlSupport { * * @return the cluster abilities. */ - Map getClusterAbility(); + Map getClusterAbility(); /**. * Register components for cluster. These will be trigger when its interested ability changes @@ -42,7 +43,7 @@ public interface ClusterAbilityControlSupport { * @param priority a positive number, the higher the priority, the faster it will be called * @param handlerMapping component */ - void registerComponentForCluster(String abilityKey, HandlerMapping handlerMapping, int priority); + void registerComponentForCluster(AbilityKey abilityKey, HandlerMapping handlerMapping, int priority); /**. * Default method to register component @@ -50,25 +51,25 @@ public interface ClusterAbilityControlSupport { * @param abilityKey component key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey}. * @param handlerMapping component instance. */ - default void registerComponentForCluster(String abilityKey, HandlerMapping handlerMapping) { + default void registerComponentForCluster(AbilityKey abilityKey, HandlerMapping handlerMapping) { registerComponentForCluster(abilityKey, handlerMapping, 1); } /** * Remove the component instance of

handlerMappingClazz

. * - * @param abilityKey ability key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey} + * @param abilityKey ability key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey}. * @param handlerMappingClazz implement of {@link HandlerMapping} * @return the count of components have removed */ - int removeClusterComponent(String abilityKey, Class handlerMappingClazz); + int removeClusterComponent(AbilityKey abilityKey, Class handlerMappingClazz); /** * Remove all {@link HandlerMapping} interested in the special ability. - * @param abilityKey abnility key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey} + * @param abilityKey abnility key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey}. * @return the count of components have removed */ - int removeAllForCluster(String abilityKey); + int removeAllForCluster(AbilityKey abilityKey); /**. * Whether current cluster supports ability @@ -76,5 +77,5 @@ public interface ClusterAbilityControlSupport { * @param abilityKey ability key * @return whether it is turn on */ - boolean isClusterEnableAbility(String abilityKey); + boolean isClusterEnableAbility(AbilityKey abilityKey); } diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java b/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java index 2553d24a7..2e159bce1 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java @@ -17,6 +17,7 @@ package com.alibaba.nacos.core.remote; import com.alibaba.nacos.api.ability.ClientAbilities; +import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.remote.Requester; import java.util.Map; @@ -32,7 +33,7 @@ public abstract class Connection implements Requester { private boolean traced = false; - private Map abilityTable; + private Map abilityTable; private ClientAbilities abilities; @@ -54,11 +55,11 @@ public abstract class Connection implements Requester { this.traced = traced; } - public Map getAbilityTable() { + public Map getAbilityTable() { return abilityTable; } - public void setAbilityTable(Map abilityTable) { + public void setAbilityTable(Map abilityTable) { this.abilityTable = abilityTable; } diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java index 6f2c32b7f..b8cf7508b 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java @@ -122,7 +122,8 @@ public class GrpcBiStreamRequestAcceptor extends BiRequestStreamGrpc.BiRequestSt setUpRequest.getClientVersion(), appName, setUpRequest.getLabels()); metaInfo.setTenant(setUpRequest.getTenant()); Connection connection = new GrpcConnection(metaInfo, responseObserver, CONTEXT_KEY_CHANNEL.get()); - connection.setAbilityTable(AbilityTableUtils.getAbilityTableBy(setUpRequest.getAbilityTable(), AbilityKey.offset())); + connection.setAbilityTable(AbilityTableUtils.getAbilityTableBy(setUpRequest.getAbilityTable(), + AbilityKey.offset())); boolean rejectSdkOnStarting = metaInfo.isSdkSource() && !ApplicationUtils.isStarted(); if (rejectSdkOnStarting || !connectionManager.register(connectionId, connection)) { diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java index d16ce16ab..a2869d6cd 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java @@ -16,7 +16,7 @@ package com.alibaba.nacos.core.remote.grpc; -import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.register.impl.ServerAbilities; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.grpc.auto.Payload; import com.alibaba.nacos.api.grpc.auto.RequestGrpc; @@ -90,7 +90,7 @@ public class GrpcRequestAcceptor extends RequestGrpc.RequestImplBase { // server check. if (ServerCheckRequest.class.getSimpleName().equals(type)) { Payload serverCheckResponseP = GrpcUtils.convert(new ServerCheckResponse(CONTEXT_KEY_CONN_ID.get(), - AbilityKey.getAbilityBitFlags())); + ServerAbilities.getBitFlags())); traceIfNecessary(serverCheckResponseP, false); responseObserver.onNext(serverCheckResponseP); responseObserver.onCompleted(); diff --git a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityControlManagerTest.java b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityControlManagerTest.java index 99d7cced7..038cd0f82 100644 --- a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityControlManagerTest.java +++ b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityControlManagerTest.java @@ -16,6 +16,8 @@ package com.alibaba.nacos.test.ability; +import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.constant.AbilityStatus; import com.alibaba.nacos.api.ability.entity.AbilityTable; import com.alibaba.nacos.common.ability.handler.HandlerMapping; import org.junit.Assert; @@ -43,74 +45,74 @@ public class AbilityControlManagerTest { @Before public void inject() { - Map newTable = new HashMap<>(); - newTable.put("stop-raft", true); + Map newTable = new HashMap<>(); + newTable.put(AbilityKey.TEST_1, true); clientAbilityControlManager.setCurrentSupportingAbility(newTable); - Map table = new HashMap<>(); - table.put("stop-raft", true); + Map table = new HashMap<>(); + table.put(AbilityKey.TEST_1, true); serverAbilityControlManager.setCurrentSupportingAbility(table); - Map cluster = new HashMap<>(); - cluster.put("stop-raft", true); + Map cluster = new HashMap<>(); + cluster.put(AbilityKey.TEST_1, true); serverAbilityControlManager.setClusterAbility(cluster); serverAbilityControlManager.setCurrentSupportingAbility(newTable); } @Test public void testClientAdd() { - Map newTable = new HashMap<>(); - newTable.put("test-no-existed", true); - newTable.put("stop-raft", true); + Map newTable = new HashMap<>(); + newTable.put(AbilityKey.TEST_2, true); + newTable.put(AbilityKey.TEST_1, true); AbilityTable table = new AbilityTable(); table.setConnectionId("test-00001"); table.setAbility(newTable); table.setServer(true); clientAbilityControlManager.addNewTable(table); - Assert.assertFalse(clientAbilityControlManager.isSupport("test-00001", "test-no-existed")); - Assert.assertTrue(clientAbilityControlManager.isSupport("test-00001", "stop-raft")); + Assert.assertEquals(AbilityStatus.NOT_SUPPORTED, clientAbilityControlManager.isSupport("test-00001", AbilityKey.TEST_2)); + Assert.assertEquals(AbilityStatus.SUPPORTED, clientAbilityControlManager.isSupport("test-00001", AbilityKey.TEST_1)); } @Test public void testServerAdd() { - Map newTable = new HashMap<>(); - newTable.put("test-no-existed", true); - newTable.put("stop-raft", true); + Map newTable = new HashMap<>(); + newTable.put(AbilityKey.TEST_2, true); + newTable.put(AbilityKey.TEST_1, true); AbilityTable table = new AbilityTable(); table.setConnectionId("test-00001"); table.setAbility(newTable); table.setServer(true); serverAbilityControlManager.addNewTable(table); - Assert.assertFalse(serverAbilityControlManager.isSupport("test-00001", "test-no-existed")); - Assert.assertTrue(serverAbilityControlManager.isSupport("test-00001", "stop-raft")); - Assert.assertTrue(serverAbilityControlManager.isClusterEnableAbility("stop-raft")); + Assert.assertEquals(AbilityStatus.NOT_SUPPORTED, serverAbilityControlManager.isSupport("test-00001", AbilityKey.TEST_2)); + Assert.assertEquals(AbilityStatus.SUPPORTED, serverAbilityControlManager.isSupport("test-00001", AbilityKey.TEST_1)); + Assert.assertTrue(serverAbilityControlManager.isClusterEnableAbility(AbilityKey.TEST_1)); - Map otherServer = new HashMap<>(); - otherServer.put("test-no-existed", true); - otherServer.put("stop-raft", false); + Map otherServer = new HashMap<>(); + otherServer.put(AbilityKey.TEST_2, true); + otherServer.put(AbilityKey.TEST_1, false); AbilityTable otherServerTable = new AbilityTable(); otherServerTable.setConnectionId("test-00000"); otherServerTable.setAbility(otherServer); otherServerTable.setServer(true); serverAbilityControlManager.addNewTable(otherServerTable); - Assert.assertFalse(serverAbilityControlManager.isClusterEnableAbility("stop-raft")); + Assert.assertFalse(serverAbilityControlManager.isClusterEnableAbility(AbilityKey.TEST_1)); - Map clientTa = new HashMap<>(); - clientTa.put("test-no-existed", true); - clientTa.put("stop-raft", false); + Map clientTa = new HashMap<>(); + clientTa.put(AbilityKey.TEST_2, true); + clientTa.put(AbilityKey.TEST_1, false); AbilityTable clientTable = new AbilityTable(); clientTable.setConnectionId("test-00002"); clientTable.setAbility(clientTa); clientTable.setServer(false); serverAbilityControlManager.addNewTable(clientTable); - Assert.assertFalse(serverAbilityControlManager.isClusterEnableAbility("stop-raft")); + Assert.assertFalse(serverAbilityControlManager.isClusterEnableAbility(AbilityKey.TEST_1)); } @Test public void testClientRemove() { - Map clientTa = new HashMap<>(); - clientTa.put("test-no-existed", true); - clientTa.put("stop-raft", false); + Map clientTa = new HashMap<>(); + clientTa.put(AbilityKey.TEST_2, true); + clientTa.put(AbilityKey.TEST_1, false); AbilityTable clientTable = new AbilityTable(); clientTable.setConnectionId("test-01111"); clientTable.setAbility(clientTa); @@ -125,56 +127,56 @@ public class AbilityControlManagerTest { public void testComponent() throws InterruptedException { enabled = 0; // invoke enable() or disable() when registering - serverAbilityControlManager.registerComponent("stop-raft", new TestHandlerMapping(), -1); + serverAbilityControlManager.registerComponent(AbilityKey.TEST_1, new TestHandlerMapping(), -1); Assert.assertEquals(1, serverAbilityControlManager.handlerMappingCount()); - serverAbilityControlManager.enableCurrentNodeAbility("stop-raft"); + serverAbilityControlManager.enableCurrentNodeAbility(AbilityKey.TEST_1); // wait for invoking handler asyn Thread.sleep(200L); // nothing happens if it has enabled Assert.assertEquals(enabled, 1); - Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning("stop-raft")); + Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); // invoke disable() - serverAbilityControlManager.disableCurrentNodeAbility("stop-raft"); + serverAbilityControlManager.disableCurrentNodeAbility(AbilityKey.TEST_1); // wait for invoking handler asyn Thread.sleep(200L); // disable will invoke handler Assert.assertEquals(enabled, 0); - Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning("stop-raft")); + Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); - serverAbilityControlManager.disableCurrentNodeAbility("stop-raft"); + serverAbilityControlManager.disableCurrentNodeAbility(AbilityKey.TEST_1); // wait for invoking handler asyn Thread.sleep(200L); // nothing to do because it has disable Assert.assertEquals(enabled, 0); - Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning("stop-raft")); + Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); - serverAbilityControlManager.enableCurrentNodeAbility("stop-raft"); + serverAbilityControlManager.enableCurrentNodeAbility(AbilityKey.TEST_1); // wait for invoking handler asyn Thread.sleep(200L); Assert.assertEquals(enabled, 1); - Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning("stop-raft")); + Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); - serverAbilityControlManager.enableCurrentNodeAbility("stop-raft"); + serverAbilityControlManager.enableCurrentNodeAbility(AbilityKey.TEST_1); // wait for invoking handler asyn Thread.sleep(200L); Assert.assertEquals(enabled, 1); - Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning("stop-raft")); + Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); } @Test public void testClusterComponent() throws InterruptedException { clusterEnabled = 0; // invoke enable() because it turn on - serverAbilityControlManager.registerComponentForCluster("stop-raft", new ClusterHandlerMapping(), -1); + serverAbilityControlManager.registerComponentForCluster(AbilityKey.TEST_1, new ClusterHandlerMapping(), -1); Assert.assertEquals(1, serverAbilityControlManager.clusterHandlerMappingCount()); - Assert.assertTrue(serverAbilityControlManager.isClusterEnableAbility("stop-raft")); + Assert.assertTrue(serverAbilityControlManager.isClusterEnableAbility(AbilityKey.TEST_1)); Assert.assertEquals(clusterEnabled, 1); - Map serverAbility = new HashMap<>(); - serverAbility.put("test-no-existed", true); - serverAbility.put("stop-raft", false); + Map serverAbility = new HashMap<>(); + serverAbility.put(AbilityKey.TEST_2, true); + serverAbility.put(AbilityKey.TEST_1, false); AbilityTable serverTable = new AbilityTable(); serverTable.setConnectionId("test-01111"); serverTable.setAbility(serverAbility); @@ -184,20 +186,20 @@ public class AbilityControlManagerTest { Thread.sleep(200L); // disabled - Assert.assertFalse(serverAbilityControlManager.isClusterEnableAbility("stop-raft")); + Assert.assertFalse(serverAbilityControlManager.isClusterEnableAbility(AbilityKey.TEST_1)); Assert.assertEquals(clusterEnabled, 0); // remove this table to enabled serverAbilityControlManager.removeTable("test-01111"); // wait for invoking handler asyn Thread.sleep(200L); - Assert.assertTrue(serverAbilityControlManager.isClusterEnableAbility("stop-raft")); + Assert.assertTrue(serverAbilityControlManager.isClusterEnableAbility(AbilityKey.TEST_1)); Assert.assertEquals(clusterEnabled, 1); } @Test public void testCurrentNodeAbility() { - Set keySet = serverAbilityControlManager.getCurrentRunningAbility().keySet(); + Set keySet = serverAbilityControlManager.getCurrentRunningAbility().keySet(); // diable all keySet.forEach(key -> serverAbilityControlManager.disableCurrentNodeAbility(key)); // get all @@ -215,7 +217,7 @@ public class AbilityControlManagerTest { @Test public void testPriority() throws InterruptedException { TestServerAbilityControlManager testServerAbilityControlManager = new TestServerAbilityControlManager(); - String key = "key"; + AbilityKey key = AbilityKey.TEST_1; TestPriority clusterHandlerMapping1 = new TestPriority("1"); TestPriority clusterHandlerMapping2 = new TestPriority("2"); TestPriority clusterHandlerMapping3 = new TestPriority("3"); diff --git a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/TestClientAbilityControlManager.java b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/TestClientAbilityControlManager.java index 5e9fc0899..e506e2952 100644 --- a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/TestClientAbilityControlManager.java +++ b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/TestClientAbilityControlManager.java @@ -16,6 +16,7 @@ package com.alibaba.nacos.test.ability; +import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.client.ability.ClientAbilityControlManager; import com.alibaba.nacos.common.JustForTest; @@ -24,7 +25,7 @@ import java.util.Map; public class TestClientAbilityControlManager extends ClientAbilityControlManager { @JustForTest - public void setCurrentSupportingAbility(Map ability) { + public void setCurrentSupportingAbility(Map ability) { currentRunningAbility.putAll(ability); } } diff --git a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/TestServerAbilityControlManager.java b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/TestServerAbilityControlManager.java index 2c48bc821..3571c6060 100644 --- a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/TestServerAbilityControlManager.java +++ b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/TestServerAbilityControlManager.java @@ -16,6 +16,7 @@ package com.alibaba.nacos.test.ability; +import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.common.JustForTest; import com.alibaba.nacos.common.ability.handler.HandlerMapping; import com.alibaba.nacos.core.ability.control.ServerAbilityControlManager; @@ -27,12 +28,12 @@ import java.util.Map; public class TestServerAbilityControlManager extends ServerAbilityControlManager { @JustForTest - public void setCurrentSupportingAbility(Map ability) { + public void setCurrentSupportingAbility(Map ability) { currentRunningAbility.putAll(ability); } @JustForTest - public void setClusterAbility(Map ability) { + public void setClusterAbility(Map ability) { super.setClusterAbilityTable(ability); } @@ -42,7 +43,7 @@ public class TestServerAbilityControlManager extends ServerAbilityControlManager } @JustForTest - public List getHandlerMapping(String abilityKey) { + public List getHandlerMapping(AbilityKey abilityKey) { return super.handlerMapping().get(abilityKey); } @@ -52,7 +53,7 @@ public class TestServerAbilityControlManager extends ServerAbilityControlManager } @JustForTest - public List getClusterHandlerMapping(String abilityKey) { + public List getClusterHandlerMapping(AbilityKey abilityKey) { return super.clusterHandlerMapping().get(abilityKey); } @@ -60,19 +61,19 @@ public class TestServerAbilityControlManager extends ServerAbilityControlManager * Just a test method. */ @JustForTest - public void registerClusterHandlerMapping(String key, HandlerMapping handlerMapping, int priority) { + public void registerClusterHandlerMapping(AbilityKey key, HandlerMapping handlerMapping, int priority) { List orDefault = super.clusterHandlerMapping().getOrDefault(key, new ArrayList<>()); orDefault.add(new HandlerWithPriority(handlerMapping, priority)); clusterHandlerMapping().put(key, orDefault); } @JustForTest - public void triggerCluster(String abilityKey) { + public void triggerCluster(AbilityKey abilityKey) { triggerHandlerMappingAsyn(abilityKey, true, clusterHandlerMapping()); } @JustForTest - public void trigger(String abilityKey) { + public void trigger(AbilityKey abilityKey) { triggerHandlerMappingAsyn(abilityKey, true, handlerMapping()); } } From 41d278d6f1db8aa2e08f88944e37aee0099ab379 Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Thu, 1 Sep 2022 20:31:48 +0800 Subject: [PATCH 18/55] Add junit test --- .../api/utils/AbilityTableUtilsTest.java | 118 +++++++++++ .../ability/AbilityControlManagerTest.java | 189 ++++++++++++++++++ .../TestClientAbilityControlManager.java | 19 +- .../ability/AbilityControlManagerTest.java | 20 +- .../TestServerAbilityControlManager.java | 2 +- 5 files changed, 334 insertions(+), 14 deletions(-) create mode 100644 api/src/test/java/com/alibaba/nacos/api/utils/AbilityTableUtilsTest.java create mode 100644 client/src/test/java/com/alibaba/nacos/client/ability/AbilityControlManagerTest.java rename {test/core-test/src/test/java/com/alibaba/nacos/test => client/src/test/java/com/alibaba/nacos/client}/ability/TestClientAbilityControlManager.java (66%) rename {test/core-test/src/test/java/com/alibaba/nacos/test => core/src/test/java/com/alibaba/nacos/core}/ability/AbilityControlManagerTest.java (95%) rename {test/core-test/src/test/java/com/alibaba/nacos/test => core/src/test/java/com/alibaba/nacos/core}/ability/TestServerAbilityControlManager.java (98%) diff --git a/api/src/test/java/com/alibaba/nacos/api/utils/AbilityTableUtilsTest.java b/api/src/test/java/com/alibaba/nacos/api/utils/AbilityTableUtilsTest.java new file mode 100644 index 000000000..8d3e6ce32 --- /dev/null +++ b/api/src/test/java/com/alibaba/nacos/api/utils/AbilityTableUtilsTest.java @@ -0,0 +1,118 @@ +/* + * Copyright 1999-2022 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.nacos.api.utils; + +import com.alibaba.nacos.api.ability.constant.AbilityKey; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public class AbilityTableUtilsTest { + + @Test + public void testGetAbilityBitBy() { + byte[] abilityBitBy = AbilityTableUtils.getAbilityBitBy(Arrays.asList(1, 8, 9, 17)); + Assert.assertEquals(abilityBitBy[0], -127); + Assert.assertEquals(abilityBitBy[1], -128); + Assert.assertEquals(abilityBitBy[2], -128); + // clear + byte[] abilityBits = AbilityTableUtils.getAbilityBitBy(Collections.emptyList()); + Assert.assertEquals(abilityBits.length , 1); + Assert.assertEquals(abilityBits[0] , 0); + } + + @Test + public void testGetAbilityTableBy() { + byte[] bytes = new byte[]{0}; + Map abilityTableBy = + AbilityTableUtils.getAbilityTableBy(bytes, AbilityKey.offset()); + Assert.assertEquals(abilityTableBy.getOrDefault(AbilityKey.TEST_1, false), false); + Assert.assertEquals(abilityTableBy.getOrDefault(AbilityKey.TEST_2, false), false); + + byte[] bytes1 = new byte[]{-64}; + Map abilityTableBy1 = + AbilityTableUtils.getAbilityTableBy(bytes1, AbilityKey.offset()); + Assert.assertEquals(abilityTableBy1.get(AbilityKey.TEST_1), true); + Assert.assertEquals(abilityTableBy1.get(AbilityKey.TEST_2), true); + + byte[] bytes2 = new byte[]{-128}; + Map abilityTableBy2 = + AbilityTableUtils.getAbilityTableBy(bytes2, AbilityKey.offset()); + Assert.assertEquals(abilityTableBy2.getOrDefault(AbilityKey.TEST_1, false), true); + Assert.assertEquals(abilityTableBy2.getOrDefault(AbilityKey.TEST_2, false), false); + + byte[] bytes3 = new byte[]{64}; + Map abilityTableBy3 = + AbilityTableUtils.getAbilityTableBy(bytes3, AbilityKey.offset()); + Assert.assertEquals(abilityTableBy3.getOrDefault(AbilityKey.TEST_1, false), false); + Assert.assertEquals(abilityTableBy3.getOrDefault(AbilityKey.TEST_2, false), true); + } + + @Test + public void testGetAbilityBiTableBy() { + Map map = new HashMap<>(); + byte[] bytes1 = AbilityTableUtils.getAbilityBiTableBy(AbilityKey.values(), map); + Assert.assertEquals(1, bytes1.length); + Assert.assertEquals(bytes1[0], 0); + + map.put(AbilityKey.TEST_1, true); + byte[] bytes2 = AbilityTableUtils.getAbilityBiTableBy(AbilityKey.values(), map); + Assert.assertEquals(1, bytes1.length); + Assert.assertEquals(bytes2[0], -128); + + map.put(AbilityKey.TEST_1, false); + map.put(AbilityKey.TEST_2, true); + byte[] bytes3 = AbilityTableUtils.getAbilityBiTableBy(AbilityKey.values(), map); + Assert.assertEquals(1, bytes3.length); + Assert.assertEquals(bytes3[0], 64); + + map.put(AbilityKey.TEST_1, true); + byte[] bytes4 = AbilityTableUtils.getAbilityBiTableBy(AbilityKey.values(), map); + Assert.assertEquals(1, bytes4.length); + Assert.assertEquals(bytes4[0], -64); + } + + @Test + public void testGetAbilityBiTable() { + Map offset = AbilityKey.offset(); + Map abilities = new HashMap<>(); + byte[] bytes1 = AbilityTableUtils.getAbilityBiTableBy(offset, abilities); + Assert.assertEquals(1, bytes1.length); + Assert.assertEquals(bytes1[0], 0); + + abilities.put(AbilityKey.TEST_1, true); + byte[] bytes2 = AbilityTableUtils.getAbilityBiTableBy(offset, abilities); + Assert.assertEquals(1, bytes2.length); + Assert.assertEquals(bytes2[0], -128); + + abilities.put(AbilityKey.TEST_2, true); + byte[] bytes3 = AbilityTableUtils.getAbilityBiTableBy(offset, abilities); + Assert.assertEquals(1, bytes3.length); + Assert.assertEquals(bytes3[0], -64); + + offset = new HashMap<>(); + offset.put(AbilityKey.TEST_1, 2); + byte[] bytes4 = AbilityTableUtils.getAbilityBiTableBy(offset, abilities); + Assert.assertEquals(1, bytes4.length); + Assert.assertEquals(bytes4[0], 64); + } + +} diff --git a/client/src/test/java/com/alibaba/nacos/client/ability/AbilityControlManagerTest.java b/client/src/test/java/com/alibaba/nacos/client/ability/AbilityControlManagerTest.java new file mode 100644 index 000000000..b60abf7ff --- /dev/null +++ b/client/src/test/java/com/alibaba/nacos/client/ability/AbilityControlManagerTest.java @@ -0,0 +1,189 @@ +/* + * Copyright 1999-2022 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.nacos.client.ability; + +import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.constant.AbilityStatus; +import com.alibaba.nacos.api.ability.entity.AbilityTable; +import com.alibaba.nacos.common.ability.handler.HandlerMapping; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; + +public class AbilityControlManagerTest { + + private TestClientAbilityControlManager clientAbilityControlManager = new TestClientAbilityControlManager(); + + private volatile int enabled = 0; + + private volatile LinkedList testPriority = new LinkedList<>(); + + @Before + public void inject() { + Map newTable = new HashMap<>(); + newTable.put(AbilityKey.TEST_1, true); + clientAbilityControlManager.setCurrentSupportingAbility(newTable); + } + + @Test + public void testClientAdd() { + Map newTable = new HashMap<>(); + newTable.put(AbilityKey.TEST_2, true); + newTable.put(AbilityKey.TEST_1, true); + AbilityTable table = new AbilityTable(); + table.setConnectionId("test-00001"); + table.setAbility(newTable); + table.setServer(true); + clientAbilityControlManager.addNewTable(table); + Assert.assertEquals(AbilityStatus.NOT_SUPPORTED, clientAbilityControlManager.isSupport("test-00001", AbilityKey.TEST_2)); + Assert.assertEquals(AbilityStatus.SUPPORTED, clientAbilityControlManager.isSupport("test-00001", AbilityKey.TEST_1)); + } + + @Test + public void testClientRemove() { + Map clientTa = new HashMap<>(); + clientTa.put(AbilityKey.TEST_2, true); + clientTa.put(AbilityKey.TEST_1, false); + AbilityTable clientTable = new AbilityTable(); + clientTable.setConnectionId("test-01111"); + clientTable.setAbility(clientTa); + clientTable.setServer(true); + clientAbilityControlManager.addNewTable(clientTable); + Assert.assertTrue(clientAbilityControlManager.contains(clientTable.getConnectionId())); + clientAbilityControlManager.removeTable("test-01111"); + Assert.assertFalse(clientAbilityControlManager.contains(clientTable.getConnectionId())); + } + + @Test + public void testComponent() throws InterruptedException { + enabled = 0; + // invoke enable() or disable() when registering + clientAbilityControlManager.registerComponent(AbilityKey.TEST_1, new TestHandlerMapping(), -1); + Assert.assertEquals(1, clientAbilityControlManager.handlerMappingCount()); + + clientAbilityControlManager.enableCurrentNodeAbility(AbilityKey.TEST_1); + // wait for invoking handler asyn + Thread.sleep(200L); + // nothing happens if it has enabled + Assert.assertEquals(enabled, 1); + Assert.assertTrue(clientAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); + + // invoke disable() + clientAbilityControlManager.disableCurrentNodeAbility(AbilityKey.TEST_1); + // wait for invoking handler asyn + Thread.sleep(200L); + // disable will invoke handler + Assert.assertEquals(enabled, 0); + Assert.assertFalse(clientAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); + + clientAbilityControlManager.disableCurrentNodeAbility(AbilityKey.TEST_1); + // wait for invoking handler asyn + Thread.sleep(200L); + // nothing to do because it has disable + Assert.assertEquals(enabled, 0); + Assert.assertFalse(clientAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); + + clientAbilityControlManager.enableCurrentNodeAbility(AbilityKey.TEST_1); + // wait for invoking handler asyn + Thread.sleep(200L); + Assert.assertEquals(enabled, 1); + Assert.assertTrue(clientAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); + + clientAbilityControlManager.enableCurrentNodeAbility(AbilityKey.TEST_1); + // wait for invoking handler asyn + Thread.sleep(200L); + Assert.assertEquals(enabled, 1); + Assert.assertTrue(clientAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); + } + + @Test + public void testPriority() throws InterruptedException { + TestClientAbilityControlManager testClientAbilityControlManager = new TestClientAbilityControlManager(); + AbilityKey key = AbilityKey.TEST_1; + TestPriority clusterHandlerMapping1 = new TestPriority("1"); + TestPriority clusterHandlerMapping2 = new TestPriority("2"); + TestPriority clusterHandlerMapping3 = new TestPriority("3"); + // first one, invoke enable() + testClientAbilityControlManager.registerComponent(key, clusterHandlerMapping2, 128); + // last one, invoke enable() + testClientAbilityControlManager.registerComponent(key, clusterHandlerMapping3); + // second one, invoke enable() + testClientAbilityControlManager.registerComponent(key, clusterHandlerMapping1, 12); + // trigger cluster + testClientAbilityControlManager.trigger(key); + Assert.assertEquals(3, testClientAbilityControlManager.getHandlerMapping(key).size()); + // wait for invoking + Thread.sleep(200L); + Assert.assertEquals("2", testPriority.poll()); + Assert.assertEquals("3", testPriority.poll()); + Assert.assertEquals("1", testPriority.poll()); + // here are priority + Assert.assertEquals("2", testPriority.poll()); + Assert.assertEquals("1", testPriority.poll()); + Assert.assertEquals("3", testPriority.poll()); + + // remove + testClientAbilityControlManager.registerComponent(key, new TestHandlerMapping(), -1); + Assert.assertEquals(4, testClientAbilityControlManager.getHandlerMapping(key).size()); + Assert.assertEquals(1, testClientAbilityControlManager.removeComponent(key, TestHandlerMapping.class)); + Assert.assertEquals(3, testClientAbilityControlManager.getHandlerMapping(key).size()); + testClientAbilityControlManager.removeAll(key); + Assert.assertNull(testClientAbilityControlManager.getHandlerMapping(key)); + } + + class TestPriority implements HandlerMapping { + + String mark; + + public TestPriority(String mark) { + // unique one + this.mark = mark.intern(); + } + + @Override + public void enable() { + testPriority.offer(mark); + } + + @Override + public void disable() { + testPriority.offer(mark); + } + } + + + class TestHandlerMapping implements HandlerMapping { + + @Override + public void enable() { + enabled++; + } + + @Override + public void disable() { + enabled--; + } + + } + +} + + diff --git a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/TestClientAbilityControlManager.java b/client/src/test/java/com/alibaba/nacos/client/ability/TestClientAbilityControlManager.java similarity index 66% rename from test/core-test/src/test/java/com/alibaba/nacos/test/ability/TestClientAbilityControlManager.java rename to client/src/test/java/com/alibaba/nacos/client/ability/TestClientAbilityControlManager.java index e506e2952..df52b85f3 100644 --- a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/TestClientAbilityControlManager.java +++ b/client/src/test/java/com/alibaba/nacos/client/ability/TestClientAbilityControlManager.java @@ -14,12 +14,12 @@ * limitations under the License. */ -package com.alibaba.nacos.test.ability; +package com.alibaba.nacos.client.ability; import com.alibaba.nacos.api.ability.constant.AbilityKey; -import com.alibaba.nacos.client.ability.ClientAbilityControlManager; import com.alibaba.nacos.common.JustForTest; +import java.util.List; import java.util.Map; public class TestClientAbilityControlManager extends ClientAbilityControlManager { @@ -28,4 +28,19 @@ public class TestClientAbilityControlManager extends ClientAbilityControlManager public void setCurrentSupportingAbility(Map ability) { currentRunningAbility.putAll(ability); } + + @JustForTest + public int handlerMappingCount() { + return super.handlerMapping().size(); + } + + @JustForTest + public List getHandlerMapping(AbilityKey abilityKey) { + return super.handlerMapping().get(abilityKey); + } + + @JustForTest + public void trigger(AbilityKey abilityKey) { + triggerHandlerMappingAsyn(abilityKey, true, handlerMapping()); + } } diff --git a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityControlManagerTest.java b/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java similarity index 95% rename from test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityControlManagerTest.java rename to core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java index 038cd0f82..cd9d062c6 100644 --- a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityControlManagerTest.java +++ b/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.alibaba.nacos.test.ability; +package com.alibaba.nacos.core.ability; import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.ability.constant.AbilityStatus; @@ -33,8 +33,6 @@ import java.util.Set; @SpringBootTest public class AbilityControlManagerTest { - private TestClientAbilityControlManager clientAbilityControlManager = new TestClientAbilityControlManager(); - private TestServerAbilityControlManager serverAbilityControlManager = new TestServerAbilityControlManager(); private volatile int clusterEnabled = 0; @@ -47,7 +45,7 @@ public class AbilityControlManagerTest { public void inject() { Map newTable = new HashMap<>(); newTable.put(AbilityKey.TEST_1, true); - clientAbilityControlManager.setCurrentSupportingAbility(newTable); + serverAbilityControlManager.setCurrentSupportingAbility(newTable); Map table = new HashMap<>(); table.put(AbilityKey.TEST_1, true); @@ -68,9 +66,9 @@ public class AbilityControlManagerTest { table.setConnectionId("test-00001"); table.setAbility(newTable); table.setServer(true); - clientAbilityControlManager.addNewTable(table); - Assert.assertEquals(AbilityStatus.NOT_SUPPORTED, clientAbilityControlManager.isSupport("test-00001", AbilityKey.TEST_2)); - Assert.assertEquals(AbilityStatus.SUPPORTED, clientAbilityControlManager.isSupport("test-00001", AbilityKey.TEST_1)); + serverAbilityControlManager.addNewTable(table); + Assert.assertEquals(AbilityStatus.NOT_SUPPORTED, serverAbilityControlManager.isSupport("test-00001", AbilityKey.TEST_2)); + Assert.assertEquals(AbilityStatus.SUPPORTED, serverAbilityControlManager.isSupport("test-00001", AbilityKey.TEST_1)); } @Test @@ -117,10 +115,10 @@ public class AbilityControlManagerTest { clientTable.setConnectionId("test-01111"); clientTable.setAbility(clientTa); clientTable.setServer(true); - clientAbilityControlManager.addNewTable(clientTable); - Assert.assertTrue(clientAbilityControlManager.contains(clientTable.getConnectionId())); - clientAbilityControlManager.removeTable("test-01111"); - Assert.assertFalse(clientAbilityControlManager.contains(clientTable.getConnectionId())); + serverAbilityControlManager.addNewTable(clientTable); + Assert.assertTrue(serverAbilityControlManager.contains(clientTable.getConnectionId())); + serverAbilityControlManager.removeTable("test-01111"); + Assert.assertFalse(serverAbilityControlManager.contains(clientTable.getConnectionId())); } @Test diff --git a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/TestServerAbilityControlManager.java b/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java similarity index 98% rename from test/core-test/src/test/java/com/alibaba/nacos/test/ability/TestServerAbilityControlManager.java rename to core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java index 3571c6060..e5d7a002b 100644 --- a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/TestServerAbilityControlManager.java +++ b/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.alibaba.nacos.test.ability; +package com.alibaba.nacos.core.ability; import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.common.JustForTest; From 182b821938d322a4b75d12ec3d1984cc97c60d31 Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Fri, 2 Sep 2022 21:56:03 +0800 Subject: [PATCH 19/55] Remove the component listening to cluster ability, disable the cluster capability table when the connected server does not support capability negotiation. --- .../register/AbstractAbilityRegistry.java | 2 +- .../register/impl/ClientAbilities.java | 4 +- .../register/impl/ServerAbilities.java | 4 +- .../nacos/api/utils/AbilityTableUtils.java | 4 +- .../api/utils/AbilityTableUtilsTest.java | 4 +- .../ability/AbilityControlManagerTest.java | 1 - .../AbstractAbilityControlManager.java | 27 ++- .../common/remote/client/grpc/GrpcClient.java | 13 +- .../control/ServerAbilityControlManager.java | 76 +++------ .../inte/ClusterAbilityControlSupport.java | 41 +---- .../grpc/GrpcBiStreamRequestAcceptor.java | 7 +- .../ability/AbilityControlManagerTest.java | 160 +++--------------- .../TestServerAbilityControlManager.java | 37 +--- 13 files changed, 83 insertions(+), 297 deletions(-) diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/register/AbstractAbilityRegistry.java b/api/src/main/java/com/alibaba/nacos/api/ability/register/AbstractAbilityRegistry.java index 4ad0df43d..60be843fa 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/register/AbstractAbilityRegistry.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/register/AbstractAbilityRegistry.java @@ -51,7 +51,7 @@ public abstract class AbstractAbilityRegistry { abilityBitFlag = AbilityTableUtils.getAbilityBiTableBy(AbilityKey.values(), supportedAbilities); } - /** + /**. * get static ability current server supports * * @return static ability diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java index c4ec32be5..39a4f7232 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java @@ -61,12 +61,12 @@ public class ClientAbilities extends AbstractAbilityRegistry { return INSTANCE.getAbilityBitFlags(); } - /** + /**. * get static ability current server supports * * @return static ability */ - public static Map getStaticAbilities(){ + public static Map getStaticAbilities() { return INSTANCE.getSupportedAbilities(); } } diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java index bd01a53b8..ca5fecdef 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java @@ -61,12 +61,12 @@ public class ServerAbilities extends AbstractAbilityRegistry { return INSTANCE.getAbilityBitFlags(); } - /** + /**. * get static ability current server supports * * @return static ability */ - public static Map getStaticAbilities(){ + public static Map getStaticAbilities() { return INSTANCE.getSupportedAbilities(); } diff --git a/api/src/main/java/com/alibaba/nacos/api/utils/AbilityTableUtils.java b/api/src/main/java/com/alibaba/nacos/api/utils/AbilityTableUtils.java index fe75aab2c..d99587075 100644 --- a/api/src/main/java/com/alibaba/nacos/api/utils/AbilityTableUtils.java +++ b/api/src/main/java/com/alibaba/nacos/api/utils/AbilityTableUtils.java @@ -116,12 +116,12 @@ public class AbilityTableUtils { return getAbilityBitBy(res.values()); } - /** + /**. * get ability bit table by existed ability table and abilityKeys array * * @param abilityKeys abilityKeys array * @param abilityTable existed ability table - * @return filter ability which value is false in abilityTable + * @return filter ability which value is false in abilityTable */ public static byte[] getAbilityBiTableBy(AbilityKey[] abilityKeys, Map abilityTable) { // filter the element which abilityTable don't have or value is false diff --git a/api/src/test/java/com/alibaba/nacos/api/utils/AbilityTableUtilsTest.java b/api/src/test/java/com/alibaba/nacos/api/utils/AbilityTableUtilsTest.java index 8d3e6ce32..bbd2ce770 100644 --- a/api/src/test/java/com/alibaba/nacos/api/utils/AbilityTableUtilsTest.java +++ b/api/src/test/java/com/alibaba/nacos/api/utils/AbilityTableUtilsTest.java @@ -35,8 +35,8 @@ public class AbilityTableUtilsTest { Assert.assertEquals(abilityBitBy[2], -128); // clear byte[] abilityBits = AbilityTableUtils.getAbilityBitBy(Collections.emptyList()); - Assert.assertEquals(abilityBits.length , 1); - Assert.assertEquals(abilityBits[0] , 0); + Assert.assertEquals(abilityBits.length, 1); + Assert.assertEquals(abilityBits[0], 0); } @Test diff --git a/client/src/test/java/com/alibaba/nacos/client/ability/AbilityControlManagerTest.java b/client/src/test/java/com/alibaba/nacos/client/ability/AbilityControlManagerTest.java index b60abf7ff..c18cbaf75 100644 --- a/client/src/test/java/com/alibaba/nacos/client/ability/AbilityControlManagerTest.java +++ b/client/src/test/java/com/alibaba/nacos/client/ability/AbilityControlManagerTest.java @@ -169,7 +169,6 @@ public class AbilityControlManagerTest { } } - class TestHandlerMapping implements HandlerMapping { @Override diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java index 96c5e1c45..66d4c8f7e 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java @@ -117,15 +117,18 @@ public abstract class AbstractAbilityControlManager implements AbilityControlMan } // hook method add(table); - // add to node - Set abilityKeys = table.getAbility().keySet(); + // null if not support ability table Map clientAbilities = table.getAbility(); - abilityKeys.forEach(abilityKey -> { - Boolean res = currentRunningAbility.getOrDefault(abilityKey, false); - Boolean coming = clientAbilities.getOrDefault(abilityKey, false); - clientAbilities.put(abilityKey, res && coming); - }); - nodeAbilityTable.put(connectionId, table); + if (clientAbilities != null) { + // add to nod + Set abilityKeys = table.getAbility().keySet(); + abilityKeys.forEach(abilityKey -> { + Boolean res = currentRunningAbility.getOrDefault(abilityKey, false); + Boolean coming = clientAbilities.getOrDefault(abilityKey, false); + clientAbilities.put(abilityKey, res && coming); + }); + nodeAbilityTable.put(connectionId, table); + } } finally { lockForAbilityTable.unlock(); } @@ -143,17 +146,9 @@ public abstract class AbstractAbilityControlManager implements AbilityControlMan */ @Override public final void removeTable(String connectionId) { - // if not exists - if(connectionId == null || !nodeAbilityTable.containsKey(connectionId)){ - return; - } AbilityTable removingTable = null; lockForAbilityTable.lock(); try { - // check - if (!nodeAbilityTable.containsKey(connectionId)) { - return; - } // hook method remove(connectionId); // remove diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java index 7519de40f..73ae05692 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java @@ -18,7 +18,6 @@ package com.alibaba.nacos.common.remote.client.grpc; import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.ability.entity.AbilityTable; -import com.alibaba.nacos.api.ability.register.impl.ServerAbilities; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.grpc.auto.BiRequestStreamGrpc; import com.alibaba.nacos.api.grpc.auto.Payload; @@ -48,7 +47,6 @@ import io.grpc.stub.StreamObserver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Arrays; import java.util.Map; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; @@ -319,12 +317,15 @@ public abstract class GrpcClient extends RpcClient { // submit ability table as soon as possible // ability table will be null if server doesn't support ability table ServerCheckResponse serverCheckResponse = (ServerCheckResponse) response; - Map abilityTable = AbilityTableUtils - .getAbilityTableBy(serverCheckResponse.getAbilities(), AbilityKey.offset()); AbilityTable table = new AbilityTable(); table.setServer(true) - .setConnectionId(serverCheckResponse.getConnectionId()) - .setAbility(abilityTable); + .setConnectionId(serverCheckResponse.getConnectionId()); + // if not supported, it will be null + if (serverCheckResponse.getAbilities() != null) { + Map abilityTable = AbilityTableUtils + .getAbilityTableBy(serverCheckResponse.getAbilities(), AbilityKey.offset()); + table.setAbility(abilityTable); + } NacosAbilityManagerHolder.getInstance().addNewTable(table); BiRequestStreamGrpc.BiRequestStreamStub biRequestStreamStub = BiRequestStreamGrpc diff --git a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java index 825faa807..12ddc7885 100644 --- a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java +++ b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java @@ -23,21 +23,16 @@ import com.alibaba.nacos.api.ability.register.impl.ServerAbilities; import com.alibaba.nacos.common.JustForTest; import com.alibaba.nacos.common.ability.AbstractAbilityControlManager; import com.alibaba.nacos.common.ability.DefaultAbilityControlManager; -import com.alibaba.nacos.common.ability.handler.HandlerMapping; import com.alibaba.nacos.common.notify.NotifyCenter; +import com.alibaba.nacos.common.utils.ConcurrentHashSet; import com.alibaba.nacos.common.utils.MapUtil; import com.alibaba.nacos.core.ability.inte.ClusterAbilityControlSupport; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.util.Collections; -import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; /**. * @author Daydreamer @@ -46,8 +41,6 @@ import java.util.concurrent.locks.ReentrantLock; **/ public class ServerAbilityControlManager extends DefaultAbilityControlManager implements ClusterAbilityControlSupport { - private static final Logger LOGGER = LoggerFactory.getLogger(ServerAbilityControlManager.class); - /**. * ability for cluster */ @@ -57,13 +50,11 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im * ability for server */ private final Map serversAbilityTable = new ConcurrentHashMap<>(); - - /** - * components for cluster. these will be invoked if cluster ability table changes. - */ - private final Map> clusterHandlerMapping = new ConcurrentHashMap<>(); - private Lock lockForClusterComponents = new ReentrantLock(); + /**. + * Number of servers that do not support capability negotiation + */ + private final ConcurrentHashSet serverNoAbilityNegotiation = new ConcurrentHashSet<>(); public ServerAbilityControlManager() { // add current node into @@ -92,14 +83,17 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im } /**. - * Whether current cluster supports ability + * Whether all the servers currently connected support a certain capability * * @param abilityKey ability key * @return whether it is turn on */ @Override - public boolean isClusterEnableAbility(AbilityKey abilityKey) { - return clusterAbilityTable.getOrDefault(abilityKey, Boolean.FALSE); + public AbilityStatus isClusterEnableAbilityNow(AbilityKey abilityKey) { + if (serverNoAbilityNegotiation.size() > 0) { + return AbilityStatus.UNKNOWN; + } + return clusterAbilityTable.getOrDefault(abilityKey, Boolean.FALSE) ? AbilityStatus.SUPPORTED : AbilityStatus.NOT_SUPPORTED; } @Override @@ -107,29 +101,6 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im return Collections.unmodifiableMap(clusterAbilityTable); } - /**. - * Register components for cluster. These will be trigger when its interested ability changes - * - * @param abilityKey ability key - * @param priority the higher the priority, the faster it will be called - * @param handlerMapping component - */ - @Override - public void registerComponentForCluster(AbilityKey abilityKey, HandlerMapping handlerMapping, int priority) { - doRegisterComponent(abilityKey, handlerMapping, this.clusterHandlerMapping, lockForClusterComponents, priority, clusterAbilityTable); - } - - @Override - public int removeClusterComponent(AbilityKey abilityKey, Class handlerMappingClazz) { - return doRemove(abilityKey, handlerMappingClazz, lockForClusterComponents, clusterHandlerMapping); - } - - @Override - public int removeAllForCluster(AbilityKey abilityKey) { - List remove = this.clusterHandlerMapping.remove(abilityKey); - return Optional.ofNullable(remove).orElse(Collections.emptyList()).size(); - } - @Override protected void add(AbilityTable table) { // from which env @@ -148,13 +119,15 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im Boolean newRes = val && isEnabled; // if ability changes if (!newRes.equals(isEnabled)) { - triggerHandlerMappingAsyn(abilityKey, false, this.clusterHandlerMapping); clusterAbilityTable.replace(abilityKey, false); // notify NotifyCenter.publishEvent(buildClusterEvent(abilityKey, false)); } }); } + } else if (isServer && table.getAbility() == null) { + // add mark if server doesn't support ability table + serverNoAbilityNegotiation.add(table.getConnectionId()); } } @@ -171,13 +144,15 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im protected void remove(String connectionId) { // from which AbilityTable abilityTable = nodeAbilityTable.get(connectionId); + // if not support + serverNoAbilityNegotiation.remove(connectionId); // return if null if (abilityTable == null) { return; } // from which env if (abilityTable.isServer()) { - // remove from server ability collection + // remove from server ability collection if support serversAbilityTable.remove(connectionId); // remove from cluster if (MapUtil.isNotEmpty(serversAbilityTable)) { @@ -198,7 +173,6 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im clusterAbilityTable.replace(abilityKey, newVal); // if change if (!isEnabled.equals(newVal)) { - triggerHandlerMappingAsyn(abilityKey, newVal, this.clusterHandlerMapping); // notify NotifyCenter.publishEvent(buildClusterEvent(abilityKey, newVal)); } @@ -207,16 +181,6 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im } } - @Override - protected void doDestroy() { - if (MapUtil.isNotEmpty(clusterHandlerMapping)) { - if (MapUtil.isNotEmpty(clusterHandlerMapping)) { - clusterHandlerMapping.keySet().forEach(key -> doTriggerSyn(key, false, clusterHandlerMapping)); - } - } - LOGGER.warn("[ServerAbilityControlManager] - Destruction of the end"); - } - /**. * notify when current node ability changing */ @@ -252,10 +216,10 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im protected void setClusterAbilityTable(Map map) { clusterAbilityTable.putAll(map); } - + @JustForTest - protected Map> clusterHandlerMapping() { - return this.clusterHandlerMapping; + protected Set serverNotSupport() { + return serverNoAbilityNegotiation; } } diff --git a/core/src/main/java/com/alibaba/nacos/core/ability/inte/ClusterAbilityControlSupport.java b/core/src/main/java/com/alibaba/nacos/core/ability/inte/ClusterAbilityControlSupport.java index 9b989a078..71f32488f 100644 --- a/core/src/main/java/com/alibaba/nacos/core/ability/inte/ClusterAbilityControlSupport.java +++ b/core/src/main/java/com/alibaba/nacos/core/ability/inte/ClusterAbilityControlSupport.java @@ -17,7 +17,7 @@ package com.alibaba.nacos.core.ability.inte; import com.alibaba.nacos.api.ability.constant.AbilityKey; -import com.alibaba.nacos.common.ability.handler.HandlerMapping; +import com.alibaba.nacos.api.ability.constant.AbilityStatus; import com.alibaba.nacos.common.ability.inter.AbilityControlManager; import java.util.Map; @@ -37,45 +37,10 @@ public interface ClusterAbilityControlSupport { Map getClusterAbility(); /**. - * Register components for cluster. These will be trigger when its interested ability changes - * - * @param abilityKey ability key - * @param priority a positive number, the higher the priority, the faster it will be called - * @param handlerMapping component - */ - void registerComponentForCluster(AbilityKey abilityKey, HandlerMapping handlerMapping, int priority); - - /**. - * Default method to register component - * - * @param abilityKey component key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey}. - * @param handlerMapping component instance. - */ - default void registerComponentForCluster(AbilityKey abilityKey, HandlerMapping handlerMapping) { - registerComponentForCluster(abilityKey, handlerMapping, 1); - } - - /** - * Remove the component instance of

handlerMappingClazz

. - * - * @param abilityKey ability key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey}. - * @param handlerMappingClazz implement of {@link HandlerMapping} - * @return the count of components have removed - */ - int removeClusterComponent(AbilityKey abilityKey, Class handlerMappingClazz); - - /** - * Remove all {@link HandlerMapping} interested in the special ability. - * @param abilityKey abnility key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey}. - * @return the count of components have removed - */ - int removeAllForCluster(AbilityKey abilityKey); - - /**. - * Whether current cluster supports ability + * Whether all the servers currently connected support a certain capability * * @param abilityKey ability key * @return whether it is turn on */ - boolean isClusterEnableAbility(AbilityKey abilityKey); + AbilityStatus isClusterEnableAbilityNow(AbilityKey abilityKey); } diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java index b8cf7508b..4a550d80b 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java @@ -122,8 +122,11 @@ public class GrpcBiStreamRequestAcceptor extends BiRequestStreamGrpc.BiRequestSt setUpRequest.getClientVersion(), appName, setUpRequest.getLabels()); metaInfo.setTenant(setUpRequest.getTenant()); Connection connection = new GrpcConnection(metaInfo, responseObserver, CONTEXT_KEY_CHANNEL.get()); - connection.setAbilityTable(AbilityTableUtils.getAbilityTableBy(setUpRequest.getAbilityTable(), - AbilityKey.offset())); + // null if supported + if (setUpRequest.getAbilityTable() != null) { + connection.setAbilityTable(AbilityTableUtils.getAbilityTableBy(setUpRequest.getAbilityTable(), + AbilityKey.offset())); + } boolean rejectSdkOnStarting = metaInfo.isSdkSource() && !ApplicationUtils.isStarted(); if (rejectSdkOnStarting || !connectionManager.register(connectionId, connection)) { diff --git a/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java b/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java index cd9d062c6..b15dce4c7 100644 --- a/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java +++ b/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java @@ -26,7 +26,6 @@ import org.junit.Test; import org.springframework.boot.test.context.SpringBootTest; import java.util.HashMap; -import java.util.LinkedList; import java.util.Map; import java.util.Set; @@ -35,11 +34,7 @@ public class AbilityControlManagerTest { private TestServerAbilityControlManager serverAbilityControlManager = new TestServerAbilityControlManager(); - private volatile int clusterEnabled = 0; - private volatile int enabled = 0; - - private volatile LinkedList testPriority = new LinkedList<>(); @Before public void inject() { @@ -83,7 +78,6 @@ public class AbilityControlManagerTest { serverAbilityControlManager.addNewTable(table); Assert.assertEquals(AbilityStatus.NOT_SUPPORTED, serverAbilityControlManager.isSupport("test-00001", AbilityKey.TEST_2)); Assert.assertEquals(AbilityStatus.SUPPORTED, serverAbilityControlManager.isSupport("test-00001", AbilityKey.TEST_1)); - Assert.assertTrue(serverAbilityControlManager.isClusterEnableAbility(AbilityKey.TEST_1)); Map otherServer = new HashMap<>(); otherServer.put(AbilityKey.TEST_2, true); @@ -93,7 +87,6 @@ public class AbilityControlManagerTest { otherServerTable.setAbility(otherServer); otherServerTable.setServer(true); serverAbilityControlManager.addNewTable(otherServerTable); - Assert.assertFalse(serverAbilityControlManager.isClusterEnableAbility(AbilityKey.TEST_1)); Map clientTa = new HashMap<>(); clientTa.put(AbilityKey.TEST_2, true); @@ -103,7 +96,31 @@ public class AbilityControlManagerTest { clientTable.setAbility(clientTa); clientTable.setServer(false); serverAbilityControlManager.addNewTable(clientTable); - Assert.assertFalse(serverAbilityControlManager.isClusterEnableAbility(AbilityKey.TEST_1)); + + // if not support + AbilityTable serverTable = new AbilityTable(); + serverTable.setConnectionId("test-001231"); + serverTable.setServer(true); + serverAbilityControlManager.addNewTable(serverTable); + // unknown because not support + Assert.assertEquals(serverAbilityControlManager.isClusterEnableAbilityNow(AbilityKey.TEST_1), AbilityStatus.UNKNOWN); + Assert.assertEquals(serverAbilityControlManager.getServerNotSupportAbility().size(), 1); + Assert.assertTrue(serverAbilityControlManager.getServerNotSupportAbility().contains("test-001231")); + + AbilityTable serverTable1 = new AbilityTable(); + serverTable1.setConnectionId("test-001231231"); + serverTable1.setServer(true); + serverAbilityControlManager.addNewTable(serverTable1); + // unknown because not support + Assert.assertEquals(serverAbilityControlManager.isClusterEnableAbilityNow(AbilityKey.TEST_1), AbilityStatus.UNKNOWN); + Assert.assertEquals(serverAbilityControlManager.getServerNotSupportAbility().size(), 2); + Assert.assertTrue(serverAbilityControlManager.getServerNotSupportAbility().contains("test-001231231")); + + // remove then support + serverAbilityControlManager.removeTable("test-001231"); + Assert.assertEquals(serverAbilityControlManager.isClusterEnableAbilityNow(AbilityKey.TEST_1), AbilityStatus.UNKNOWN); + serverAbilityControlManager.removeTable("test-001231231"); + Assert.assertEquals(serverAbilityControlManager.isClusterEnableAbilityNow(AbilityKey.TEST_1), AbilityStatus.NOT_SUPPORTED); } @Test @@ -162,38 +179,6 @@ public class AbilityControlManagerTest { Assert.assertEquals(enabled, 1); Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); } - - @Test - public void testClusterComponent() throws InterruptedException { - clusterEnabled = 0; - // invoke enable() because it turn on - serverAbilityControlManager.registerComponentForCluster(AbilityKey.TEST_1, new ClusterHandlerMapping(), -1); - Assert.assertEquals(1, serverAbilityControlManager.clusterHandlerMappingCount()); - Assert.assertTrue(serverAbilityControlManager.isClusterEnableAbility(AbilityKey.TEST_1)); - Assert.assertEquals(clusterEnabled, 1); - - Map serverAbility = new HashMap<>(); - serverAbility.put(AbilityKey.TEST_2, true); - serverAbility.put(AbilityKey.TEST_1, false); - AbilityTable serverTable = new AbilityTable(); - serverTable.setConnectionId("test-01111"); - serverTable.setAbility(serverAbility); - serverTable.setServer(true); - serverAbilityControlManager.addNewTable(serverTable); - // wait for invoking handler asyn - Thread.sleep(200L); - - // disabled - Assert.assertFalse(serverAbilityControlManager.isClusterEnableAbility(AbilityKey.TEST_1)); - Assert.assertEquals(clusterEnabled, 0); - - // remove this table to enabled - serverAbilityControlManager.removeTable("test-01111"); - // wait for invoking handler asyn - Thread.sleep(200L); - Assert.assertTrue(serverAbilityControlManager.isClusterEnableAbility(AbilityKey.TEST_1)); - Assert.assertEquals(clusterEnabled, 1); - } @Test public void testCurrentNodeAbility() { @@ -212,101 +197,6 @@ public class AbilityControlManagerTest { }); } - @Test - public void testPriority() throws InterruptedException { - TestServerAbilityControlManager testServerAbilityControlManager = new TestServerAbilityControlManager(); - AbilityKey key = AbilityKey.TEST_1; - TestPriority clusterHandlerMapping1 = new TestPriority("1"); - TestPriority clusterHandlerMapping2 = new TestPriority("2"); - TestPriority clusterHandlerMapping3 = new TestPriority("3"); - // first one, invoke enable() - testServerAbilityControlManager.registerComponentForCluster(key, clusterHandlerMapping2, 128); - // last one, invoke enable() - testServerAbilityControlManager.registerComponentForCluster(key, clusterHandlerMapping3); - // second one, invoke enable() - testServerAbilityControlManager.registerComponentForCluster(key, clusterHandlerMapping1, 12); - // trigger cluster - testServerAbilityControlManager.triggerCluster(key); - Assert.assertEquals(3, testServerAbilityControlManager.getClusterHandlerMapping(key).size()); - // wait for invoking - Thread.sleep(200L); - Assert.assertEquals("2", testPriority.poll()); - Assert.assertEquals("3", testPriority.poll()); - Assert.assertEquals("1", testPriority.poll()); - // here are priority - Assert.assertEquals("2", testPriority.poll()); - Assert.assertEquals("1", testPriority.poll()); - Assert.assertEquals("3", testPriority.poll()); - // remove - testServerAbilityControlManager.registerClusterHandlerMapping(key, new ClusterHandlerMapping(), -1); - Assert.assertEquals(4, testServerAbilityControlManager.getClusterHandlerMapping(key).size()); - Assert.assertEquals(1, testServerAbilityControlManager.removeClusterComponent(key, ClusterHandlerMapping.class)); - Assert.assertEquals(3, testServerAbilityControlManager.getClusterHandlerMapping(key).size()); - testServerAbilityControlManager.removeAllForCluster(key); - Assert.assertNull(testServerAbilityControlManager.getClusterHandlerMapping(key)); - - // first one - testServerAbilityControlManager.registerComponent(key, clusterHandlerMapping2, 128); - // last one - testServerAbilityControlManager.registerComponent(key, clusterHandlerMapping3); - // second one - testServerAbilityControlManager.registerComponent(key, clusterHandlerMapping1, 12); - Assert.assertEquals(3, testServerAbilityControlManager.getHandlerMapping(key).size()); - // wait for invoking - Thread.sleep(200L); - // trigger - testServerAbilityControlManager.trigger(key); - // wait for invoking - Thread.sleep(200L); - Assert.assertEquals("2", testPriority.poll()); - Assert.assertEquals("3", testPriority.poll()); - Assert.assertEquals("1", testPriority.poll()); - // here are priority - Assert.assertEquals("2", testPriority.poll()); - Assert.assertEquals("1", testPriority.poll()); - Assert.assertEquals("3", testPriority.poll()); - // remove - testServerAbilityControlManager.registerComponent(key, new ClusterHandlerMapping(), -1); - Assert.assertEquals(4, testServerAbilityControlManager.getHandlerMapping(key).size()); - Assert.assertEquals(1, testServerAbilityControlManager.removeComponent(key, ClusterHandlerMapping.class)); - Assert.assertEquals(3, testServerAbilityControlManager.getHandlerMapping(key).size()); - testServerAbilityControlManager.removeAll(key); - Assert.assertNull(testServerAbilityControlManager.getClusterHandlerMapping(key)); - } - - class TestPriority implements HandlerMapping { - - String mark; - - public TestPriority(String mark) { - // unique one - this.mark = mark.intern(); - } - - @Override - public void enable() { - testPriority.offer(mark); - } - - @Override - public void disable() { - testPriority.offer(mark); - } - } - - class ClusterHandlerMapping implements HandlerMapping { - - @Override - public void enable() { - clusterEnabled++; - } - - @Override - public void disable() { - clusterEnabled--; - } - } - class TestHandlerMapping implements HandlerMapping { @Override diff --git a/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java b/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java index e5d7a002b..f53f9e1cd 100644 --- a/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java +++ b/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java @@ -18,12 +18,10 @@ package com.alibaba.nacos.core.ability; import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.common.JustForTest; -import com.alibaba.nacos.common.ability.handler.HandlerMapping; import com.alibaba.nacos.core.ability.control.ServerAbilityControlManager; -import java.util.ArrayList; -import java.util.List; import java.util.Map; +import java.util.Set; public class TestServerAbilityControlManager extends ServerAbilityControlManager { @@ -43,37 +41,8 @@ public class TestServerAbilityControlManager extends ServerAbilityControlManager } @JustForTest - public List getHandlerMapping(AbilityKey abilityKey) { - return super.handlerMapping().get(abilityKey); - } - - @JustForTest - public int clusterHandlerMappingCount() { - return super.clusterHandlerMapping().size(); + public Set getServerNotSupportAbility() { + return super.serverNotSupport(); } - @JustForTest - public List getClusterHandlerMapping(AbilityKey abilityKey) { - return super.clusterHandlerMapping().get(abilityKey); - } - - /** - * Just a test method. - */ - @JustForTest - public void registerClusterHandlerMapping(AbilityKey key, HandlerMapping handlerMapping, int priority) { - List orDefault = super.clusterHandlerMapping().getOrDefault(key, new ArrayList<>()); - orDefault.add(new HandlerWithPriority(handlerMapping, priority)); - clusterHandlerMapping().put(key, orDefault); - } - - @JustForTest - public void triggerCluster(AbilityKey abilityKey) { - triggerHandlerMappingAsyn(abilityKey, true, clusterHandlerMapping()); - } - - @JustForTest - public void trigger(AbilityKey abilityKey) { - triggerHandlerMappingAsyn(abilityKey, true, handlerMapping()); - } } From ac2523ab7de44e5cdabc27933ed65339dc6546a0 Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Sat, 3 Sep 2022 14:11:55 +0800 Subject: [PATCH 20/55] Add the priority to AbilityControlManager. --- .../ability/ClientAbilityControlManager.java | 8 +++++++- ...common.ability.DefaultAbilityControlManager | 18 ++++++++++++++++++ common/pom.xml | 1 - .../ability/AbstractAbilityControlManager.java | 8 ++++++++ .../discover/NacosAbilityManagerHolder.java | 14 +++++++++----- .../control/ServerAbilityControlManager.java | 5 +++++ ...common.ability.DefaultAbilityControlManager | 1 - 7 files changed, 47 insertions(+), 8 deletions(-) create mode 100644 client/src/main/resources/META-INF/services/com.alibaba.nacos.common.ability.DefaultAbilityControlManager rename {common => core}/src/main/resources/META-INF/services/com.alibaba.nacos.common.ability.DefaultAbilityControlManager (91%) diff --git a/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java b/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java index eef2427a5..cd3e38f66 100644 --- a/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java +++ b/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java @@ -63,5 +63,11 @@ public class ClientAbilityControlManager extends DefaultAbilityControlManager { protected void remove(String connectionId) { // nothing to do } - + + @Override + public int getPriority() { + // if server ability manager exist, you should choose the server one + return 0; + } + } diff --git a/client/src/main/resources/META-INF/services/com.alibaba.nacos.common.ability.DefaultAbilityControlManager b/client/src/main/resources/META-INF/services/com.alibaba.nacos.common.ability.DefaultAbilityControlManager new file mode 100644 index 000000000..6434f25b1 --- /dev/null +++ b/client/src/main/resources/META-INF/services/com.alibaba.nacos.common.ability.DefaultAbilityControlManager @@ -0,0 +1,18 @@ +# +# Copyright 1999-2022 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. +# +# + +com.alibaba.nacos.client.ability.ClientAbilityControlManager \ No newline at end of file diff --git a/common/pom.xml b/common/pom.xml index bda1fd571..b1c91f19d 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -84,7 +84,6 @@ true nacos-version.txt - META-INF/services/com.alibaba.nacos.common.ability.DefaultAbilityControlManager diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java index 66d4c8f7e..7b523e9be 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java @@ -208,6 +208,14 @@ public abstract class AbstractAbilityControlManager implements AbilityControlMan // default destroy // nothing to do } + + /** + * A Nacos application can only have one {@link AbilityControlManager}. + * When multiple control centers exist, it is used to determine which one is preferred + * + * @return priority + */ + public abstract int getPriority(); /** * Return ability table of current node diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/discover/NacosAbilityManagerHolder.java b/common/src/main/java/com/alibaba/nacos/common/ability/discover/NacosAbilityManagerHolder.java index dc3fe479d..668e96b9d 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/discover/NacosAbilityManagerHolder.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/discover/NacosAbilityManagerHolder.java @@ -24,7 +24,10 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Collection; +import java.util.Comparator; +import java.util.List; import java.util.ServiceConfigurationError; +import java.util.stream.Collectors; /** * This class is used to discover {@link AbstractAbilityControlManager} implements. All the @@ -55,14 +58,15 @@ public class NacosAbilityManagerHolder { // if server load = NacosServiceLoader.load(DefaultAbilityControlManager.class); } catch (ServiceConfigurationError e) { - // if client or not ability control manager - load = NacosServiceLoader.load(DefaultAbilityControlManager.class); + throw new RuntimeException("[AbilityControlManager] Cannot find AbilityControlManger"); } // the priority of the server is higher + List collect = load.stream() + .sorted(Comparator.comparingInt(AbstractAbilityControlManager::getPriority)) + .collect(Collectors.toList()); + // get the highest priority one if (load.size() > 0) { - load.forEach(clazz -> { - abstractAbilityControlManager = clazz; - }); + abstractAbilityControlManager = collect.get(collect.size() - 1); LOGGER.info("[AbilityControlManager] Successfully initialize AbilityControlManager"); } } diff --git a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java index 12ddc7885..32d7ae975 100644 --- a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java +++ b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java @@ -181,6 +181,11 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im } } + @Override + public int getPriority() { + return 1; + } + /**. * notify when current node ability changing */ diff --git a/common/src/main/resources/META-INF/services/com.alibaba.nacos.common.ability.DefaultAbilityControlManager b/core/src/main/resources/META-INF/services/com.alibaba.nacos.common.ability.DefaultAbilityControlManager similarity index 91% rename from common/src/main/resources/META-INF/services/com.alibaba.nacos.common.ability.DefaultAbilityControlManager rename to core/src/main/resources/META-INF/services/com.alibaba.nacos.common.ability.DefaultAbilityControlManager index c5e3caeac..f2545ddc3 100644 --- a/common/src/main/resources/META-INF/services/com.alibaba.nacos.common.ability.DefaultAbilityControlManager +++ b/core/src/main/resources/META-INF/services/com.alibaba.nacos.common.ability.DefaultAbilityControlManager @@ -15,5 +15,4 @@ # # -com.alibaba.nacos.client.ability.ClientAbilityControlManager com.alibaba.nacos.core.ability.control.ServerAbilityControlManager \ No newline at end of file From 4de709cc0a51567caca3157bd5b56b6b8d1fafde Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Sat, 3 Sep 2022 14:27:41 +0800 Subject: [PATCH 21/55] Supports server change ability by editing config. --- .../core/ability/config/AbilityConfigs.java | 107 +++++++++++++++ .../ability/config/AbilityConfigsTest.java | 129 ++++++++++++++++++ .../ability/config/TestAbilityConfig.java | 19 +++ 3 files changed, 255 insertions(+) create mode 100644 core/src/main/java/com/alibaba/nacos/core/ability/config/AbilityConfigs.java create mode 100644 core/src/test/java/com/alibaba/nacos/core/ability/config/AbilityConfigsTest.java create mode 100644 core/src/test/java/com/alibaba/nacos/core/ability/config/TestAbilityConfig.java diff --git a/core/src/main/java/com/alibaba/nacos/core/ability/config/AbilityConfigs.java b/core/src/main/java/com/alibaba/nacos/core/ability/config/AbilityConfigs.java new file mode 100644 index 000000000..084dc7f6a --- /dev/null +++ b/core/src/main/java/com/alibaba/nacos/core/ability/config/AbilityConfigs.java @@ -0,0 +1,107 @@ +/* + * Copyright 1999-2022 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.nacos.core.ability.config; + +import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.register.impl.ServerAbilities; +import com.alibaba.nacos.common.JustForTest; +import com.alibaba.nacos.common.ability.discover.NacosAbilityManagerHolder; +import com.alibaba.nacos.common.ability.inter.AbilityHandlerRegistry; +import com.alibaba.nacos.common.event.ServerConfigChangeEvent; +import com.alibaba.nacos.common.notify.Event; +import com.alibaba.nacos.common.notify.NotifyCenter; +import com.alibaba.nacos.common.notify.listener.Subscriber; +import com.alibaba.nacos.common.utils.ConcurrentHashSet; +import com.alibaba.nacos.sys.env.EnvUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Configuration; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/**. + * @author Daydreamer + * @description Dynamically load ability from config + * @date 2022/8/31 12:27 + **/ +@Configuration +public class AbilityConfigs extends Subscriber { + + public static final String PREFIX = "nacos.core.ability."; + + private static final Logger LOGGER = LoggerFactory.getLogger(AbilityConfigs.class); + + private final Set serverAbilityKeys = new ConcurrentHashSet<>(); + + private AbilityHandlerRegistry abilityHandlerRegistry = NacosAbilityManagerHolder.getInstance(); + + public AbilityConfigs() { + // load ability + serverAbilityKeys.addAll(ServerAbilities.getStaticAbilities().keySet()); + NotifyCenter.registerSubscriber(this); + } + + @Override + public void onEvent(ServerConfigChangeEvent event) { + // load config + Map newValues = new HashMap<>(serverAbilityKeys.size()); + serverAbilityKeys.forEach(abilityKey -> { + String key = PREFIX + abilityKey.getName(); + try { + // default true + Boolean property = EnvUtil.getProperty(key, Boolean.class, true); + newValues.put(abilityKey, property); + } catch (Exception e) { + LOGGER.warn("Update ability config from env failed, use old val, ability : {} , because : {}", key, e); + } + }); + // update + refresh(newValues); + } + + /**. + * refresh ability + */ + private void refresh(Map newValues) { + newValues.forEach((abilityKey, val) -> { + // do nothing if has turned on/off + if (val) { + abilityHandlerRegistry.enableCurrentNodeAbility(abilityKey); + } else { + abilityHandlerRegistry.disableCurrentNodeAbility(abilityKey); + } + }); + } + + @Override + public Class subscribeType() { + return ServerConfigChangeEvent.class; + } + + @JustForTest + protected Set getServerAbilityKeys() { + return serverAbilityKeys; + } + + @JustForTest + protected void setAbilityHandlerRegistry(AbilityHandlerRegistry abilityHandlerRegistry) { + this.abilityHandlerRegistry = abilityHandlerRegistry; + } + +} diff --git a/core/src/test/java/com/alibaba/nacos/core/ability/config/AbilityConfigsTest.java b/core/src/test/java/com/alibaba/nacos/core/ability/config/AbilityConfigsTest.java new file mode 100644 index 000000000..edb2fde21 --- /dev/null +++ b/core/src/test/java/com/alibaba/nacos/core/ability/config/AbilityConfigsTest.java @@ -0,0 +1,129 @@ +/* + * Copyright 1999-2022 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.nacos.core.ability.config; + +import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.common.ability.handler.HandlerMapping; +import com.alibaba.nacos.common.event.ServerConfigChangeEvent; +import com.alibaba.nacos.core.ability.TestServerAbilityControlManager; +import com.alibaba.nacos.core.ability.control.ServerAbilityControlManager; +import com.alibaba.nacos.sys.env.EnvUtil; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.springframework.mock.env.MockEnvironment; + +import java.util.HashMap; +import java.util.Map; + +/**. + * @author Daydreamer + * @description + * @date 2022/9/3 12:27 + **/ +public class AbilityConfigsTest { + + private MockEnvironment environment; + + private TestAbilityConfig abilityConfigs; + + private int tmp; + + private ServerAbilityControlManager serverAbilityControlManager; + + @Before + public void setUp() throws Exception { + environment = new MockEnvironment(); + EnvUtil.setEnvironment(environment); + abilityConfigs = new TestAbilityConfig(); + inject(abilityConfigs); + serverAbilityControlManager.enableCurrentNodeAbility(AbilityKey.TEST_1); + serverAbilityControlManager.enableCurrentNodeAbility(AbilityKey.TEST_2); + serverAbilityControlManager.registerComponent(AbilityKey.TEST_1, new TestHandler()); + serverAbilityControlManager.registerComponent(AbilityKey.TEST_2, new TestHandler()); + // tmp is 2 now + } + + void inject(AbilityConfigs abilityConfigs) { + TestServerAbilityControlManager serverAbilityControlManager = new TestServerAbilityControlManager(); + Map newTable = new HashMap<>(); + newTable.put(AbilityKey.TEST_1, true); + newTable.put(AbilityKey.TEST_2, true); + serverAbilityControlManager.setCurrentSupportingAbility(newTable); + abilityConfigs.setAbilityHandlerRegistry(serverAbilityControlManager); + this.serverAbilityControlManager = serverAbilityControlManager; + } + + @Test + public void testInit() { + Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); + Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_2)); + } + + @Test + public void testConfigChange() throws InterruptedException { + // test no change + environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.TEST_1.getName(), Boolean.TRUE.toString()); + environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.TEST_2.getName(), Boolean.TRUE.toString()); + abilityConfigs.onEvent(new ServerConfigChangeEvent()); + Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); + Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_2)); + //wait for invoke + Thread.sleep(100); + Assert.assertEquals(tmp, 2); + + // test change + environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.TEST_1.getName(), Boolean.FALSE.toString()); + abilityConfigs.onEvent(new ServerConfigChangeEvent()); + Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); + Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_2)); + //wait for invoke + Thread.sleep(100); + Assert.assertEquals(tmp, 1); + + environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.TEST_1.getName(), Boolean.TRUE.toString()); + abilityConfigs.onEvent(new ServerConfigChangeEvent()); + Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); + //wait for invoke + Thread.sleep(100); + Assert.assertEquals(tmp, 2); + + environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.TEST_1.getName(), Boolean.FALSE.toString()); + environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.TEST_2.getName(), Boolean.FALSE.toString()); + abilityConfigs.onEvent(new ServerConfigChangeEvent()); + Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); + Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_2)); + //wait for invoke + Thread.sleep(100); + Assert.assertEquals(tmp, 0); + } + + + class TestHandler implements HandlerMapping { + + @Override + public void enable() { + tmp++; + } + + @Override + public void disable() { + tmp--; + } + } + +} diff --git a/core/src/test/java/com/alibaba/nacos/core/ability/config/TestAbilityConfig.java b/core/src/test/java/com/alibaba/nacos/core/ability/config/TestAbilityConfig.java new file mode 100644 index 000000000..072d43bc2 --- /dev/null +++ b/core/src/test/java/com/alibaba/nacos/core/ability/config/TestAbilityConfig.java @@ -0,0 +1,19 @@ +package com.alibaba.nacos.core.ability.config; + +import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.common.ability.inter.AbilityHandlerRegistry; + +import java.util.Set; + +public class TestAbilityConfig extends AbilityConfigs { + + public TestAbilityConfig() { + Set serverAbilityKeys = super.getServerAbilityKeys(); + serverAbilityKeys.add(AbilityKey.TEST_1); + serverAbilityKeys.add(AbilityKey.TEST_2); + } + + public void setAbilityControlManager(AbilityHandlerRegistry abilityHandlerRegistry) { + super.setAbilityHandlerRegistry(abilityHandlerRegistry); + } +} From eada63e8d076a1d0db1879d1d3e240e727ed9992 Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Sat, 3 Sep 2022 16:01:24 +0800 Subject: [PATCH 22/55] Fix checkstyle and support server ability manager load config. --- .../control/ServerAbilityControlManager.java | 18 +++++++++++++++- .../ability/config/AbilityConfigsTest.java | 1 - .../ability/config/TestAbilityConfig.java | 21 +++++++++++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java index 32d7ae975..d47cc50ad 100644 --- a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java +++ b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java @@ -26,9 +26,12 @@ import com.alibaba.nacos.common.ability.DefaultAbilityControlManager; import com.alibaba.nacos.common.notify.NotifyCenter; import com.alibaba.nacos.common.utils.ConcurrentHashSet; import com.alibaba.nacos.common.utils.MapUtil; +import com.alibaba.nacos.core.ability.config.AbilityConfigs; import com.alibaba.nacos.core.ability.inte.ClusterAbilityControlSupport; +import com.alibaba.nacos.sys.env.EnvUtil; import java.util.Collections; +import java.util.HashMap; import java.util.Map; import java.util.Optional; import java.util.Set; @@ -68,7 +71,20 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im @Override protected Map getCurrentNodeSupportAbility() { - return ServerAbilities.getStaticAbilities(); + Set abilityKeys = ServerAbilities.getStaticAbilities().keySet(); + Map abilityTable = new HashMap<>(abilityKeys.size()); + abilityKeys.forEach(abilityKey -> { + String key = AbilityConfigs.PREFIX + abilityKey.getName(); + try { + // default true + Boolean property = EnvUtil.getProperty(key, Boolean.class, true); + abilityTable.put(abilityKey, property); + } catch (Exception e) { + // default true + abilityTable.put(abilityKey, true); + } + }); + return abilityTable; } @Override diff --git a/core/src/test/java/com/alibaba/nacos/core/ability/config/AbilityConfigsTest.java b/core/src/test/java/com/alibaba/nacos/core/ability/config/AbilityConfigsTest.java index edb2fde21..3a5ba7d6c 100644 --- a/core/src/test/java/com/alibaba/nacos/core/ability/config/AbilityConfigsTest.java +++ b/core/src/test/java/com/alibaba/nacos/core/ability/config/AbilityConfigsTest.java @@ -112,7 +112,6 @@ public class AbilityConfigsTest { Assert.assertEquals(tmp, 0); } - class TestHandler implements HandlerMapping { @Override diff --git a/core/src/test/java/com/alibaba/nacos/core/ability/config/TestAbilityConfig.java b/core/src/test/java/com/alibaba/nacos/core/ability/config/TestAbilityConfig.java index 072d43bc2..d24b1677c 100644 --- a/core/src/test/java/com/alibaba/nacos/core/ability/config/TestAbilityConfig.java +++ b/core/src/test/java/com/alibaba/nacos/core/ability/config/TestAbilityConfig.java @@ -1,3 +1,19 @@ +/* + * Copyright 1999-2022 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.nacos.core.ability.config; import com.alibaba.nacos.api.ability.constant.AbilityKey; @@ -5,6 +21,11 @@ import com.alibaba.nacos.common.ability.inter.AbilityHandlerRegistry; import java.util.Set; +/**. + * @author Daydreamer + * @description Dynamically load ability from config. just for test + * @date 2022/8/31 12:27 + **/ public class TestAbilityConfig extends AbilityConfigs { public TestAbilityConfig() { From 138f0758eb60f69f24de75960c5773f6a98cf49d Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Sat, 3 Sep 2022 16:12:25 +0800 Subject: [PATCH 23/55] Remove dead code. --- .../nacos/common/ability/AbstractAbilityControlManager.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java index 7b523e9be..469f1b99d 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java @@ -58,8 +58,6 @@ public abstract class AbstractAbilityControlManager implements AbilityControlMan */ protected final Map nodeAbilityTable = new ConcurrentHashMap<>(); - private final ReentrantLock lockForProcessors = new ReentrantLock(); - private final ReentrantLock lockForAbilityTable = new ReentrantLock(); protected AbstractAbilityControlManager() { From 6b2d3b1f3aa3385a13c275814f49f62a36f04046 Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Sun, 4 Sep 2022 16:31:45 +0800 Subject: [PATCH 24/55] Return nothing if existed connection from other cluster node doesn't support ability table. --- .../nacos/core/ability/control/ServerAbilityControlManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java index d47cc50ad..23a511e15 100644 --- a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java +++ b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java @@ -114,7 +114,7 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im @Override public Map getClusterAbility() { - return Collections.unmodifiableMap(clusterAbilityTable); + return serverNoAbilityNegotiation.size() > 0 ? null : Collections.unmodifiableMap(clusterAbilityTable); } @Override From fd6938566f1653781a389ce30a8979cd78371fc2 Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Sun, 4 Sep 2022 16:50:25 +0800 Subject: [PATCH 25/55] Add junit test --- .../ability/AbilityControlManagerTest.java | 41 ++++++++++++++++--- .../TestServerAbilityControlManager.java | 1 + 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java b/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java index b15dce4c7..8a01dbc2d 100644 --- a/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java +++ b/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java @@ -40,11 +40,6 @@ public class AbilityControlManagerTest { public void inject() { Map newTable = new HashMap<>(); newTable.put(AbilityKey.TEST_1, true); - serverAbilityControlManager.setCurrentSupportingAbility(newTable); - - Map table = new HashMap<>(); - table.put(AbilityKey.TEST_1, true); - serverAbilityControlManager.setCurrentSupportingAbility(table); Map cluster = new HashMap<>(); cluster.put(AbilityKey.TEST_1, true); @@ -195,6 +190,42 @@ public class AbilityControlManagerTest { keySet.forEach(key -> { Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(key)); }); + + // add node doesn't support ability table + AbilityTable abilityTable = new AbilityTable(); + abilityTable.setServer(true); + abilityTable.setConnectionId("adsadsa1"); + serverAbilityControlManager.addNewTable(abilityTable); + // cluster abilities close + Assert.assertEquals(serverAbilityControlManager.isClusterEnableAbilityNow(AbilityKey.TEST_1), AbilityStatus.UNKNOWN); + + AbilityTable abilityTable1 = new AbilityTable(); + abilityTable1.setServer(true); + abilityTable1.setConnectionId("adsadsa2"); + serverAbilityControlManager.addNewTable(abilityTable1); + // cluster abilities still close + Assert.assertEquals(serverAbilityControlManager.isClusterEnableAbilityNow(AbilityKey.TEST_1), AbilityStatus.UNKNOWN); + Assert.assertNull(serverAbilityControlManager.getClusterAbility()); + + AbilityTable abilityTable2 = new AbilityTable(); + abilityTable2.setServer(true); + abilityTable2.setConnectionId("adsadsa3"); + Map clientTa = new HashMap<>(); + clientTa.put(AbilityKey.TEST_2, true); + clientTa.put(AbilityKey.TEST_1, false); + abilityTable2.setAbility(clientTa); + serverAbilityControlManager.addNewTable(abilityTable2); + // cluster abilities still close + Assert.assertEquals(serverAbilityControlManager.isClusterEnableAbilityNow(AbilityKey.TEST_1), AbilityStatus.UNKNOWN); + Assert.assertNull(serverAbilityControlManager.getClusterAbility()); + + // remove + serverAbilityControlManager.removeTable("adsadsa3"); + serverAbilityControlManager.removeTable("adsadsa2"); + serverAbilityControlManager.removeTable("adsadsa1"); + // cluster abilities open + Assert.assertEquals(serverAbilityControlManager.isClusterEnableAbilityNow(AbilityKey.TEST_1), AbilityStatus.SUPPORTED); + Assert.assertNotNull(serverAbilityControlManager.getClusterAbility()); } class TestHandlerMapping implements HandlerMapping { diff --git a/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java b/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java index f53f9e1cd..3953cf54e 100644 --- a/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java +++ b/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java @@ -27,6 +27,7 @@ public class TestServerAbilityControlManager extends ServerAbilityControlManager @JustForTest public void setCurrentSupportingAbility(Map ability) { + currentRunningAbility.clear(); currentRunningAbility.putAll(ability); } From eb6ea55fef20cf76f6da870d3b6f00c63befe5dc Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Sun, 4 Sep 2022 17:11:26 +0800 Subject: [PATCH 26/55] load server abilities from ServerAbilities if config doesn't define --- .../control/ServerAbilityControlManager.java | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java index 23a511e15..61d32bc64 100644 --- a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java +++ b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java @@ -32,6 +32,7 @@ import com.alibaba.nacos.sys.env.EnvUtil; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Optional; import java.util.Set; @@ -71,19 +72,30 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im @Override protected Map getCurrentNodeSupportAbility() { - Set abilityKeys = ServerAbilities.getStaticAbilities().keySet(); + // static abilities + Map staticAbilities = ServerAbilities.getStaticAbilities(); + // all function server can support + Set abilityKeys = staticAbilities.keySet(); Map abilityTable = new HashMap<>(abilityKeys.size()); + // if not define in config, then load from ServerAbilities + Set unIncludedInConfig = new HashSet<>(); abilityKeys.forEach(abilityKey -> { String key = AbilityConfigs.PREFIX + abilityKey.getName(); try { - // default true - Boolean property = EnvUtil.getProperty(key, Boolean.class, true); - abilityTable.put(abilityKey, property); + Boolean property = EnvUtil.getProperty(key, Boolean.class); + // if not null + if (property != null) { + abilityTable.put(abilityKey, property); + } else { + unIncludedInConfig.add(abilityKey); + } } catch (Exception e) { - // default true - abilityTable.put(abilityKey, true); + // from ServerAbilities + unIncludedInConfig.add(abilityKey); } }); + // load from ServerAbilities + unIncludedInConfig.forEach(abilityKey -> abilityTable.put(abilityKey, staticAbilities.get(abilityKey))); return abilityTable; } From eedb84f2a197a88e436c69b6b0aa34ff347a2dc1 Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Mon, 5 Sep 2022 16:22:42 +0800 Subject: [PATCH 27/55] Send the newest abilities to client. --- .../alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java index a2869d6cd..9318408f6 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java @@ -16,6 +16,7 @@ package com.alibaba.nacos.core.remote.grpc; +import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.ability.register.impl.ServerAbilities; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.grpc.auto.Payload; @@ -26,6 +27,8 @@ import com.alibaba.nacos.api.remote.request.ServerCheckRequest; import com.alibaba.nacos.api.remote.response.ErrorResponse; import com.alibaba.nacos.api.remote.response.Response; import com.alibaba.nacos.api.remote.response.ServerCheckResponse; +import com.alibaba.nacos.api.utils.AbilityTableUtils; +import com.alibaba.nacos.common.ability.discover.NacosAbilityManagerHolder; import com.alibaba.nacos.common.remote.client.grpc.GrpcUtils; import com.alibaba.nacos.core.remote.Connection; import com.alibaba.nacos.core.remote.ConnectionManager; @@ -90,7 +93,8 @@ public class GrpcRequestAcceptor extends RequestGrpc.RequestImplBase { // server check. if (ServerCheckRequest.class.getSimpleName().equals(type)) { Payload serverCheckResponseP = GrpcUtils.convert(new ServerCheckResponse(CONTEXT_KEY_CONN_ID.get(), - ServerAbilities.getBitFlags())); + AbilityTableUtils.getAbilityBiTableBy(AbilityKey.offset(), + NacosAbilityManagerHolder.getInstance().getCurrentRunningAbility()))); traceIfNecessary(serverCheckResponseP, false); responseObserver.onNext(serverCheckResponseP); responseObserver.onCompleted(); From 89b450537e8a6f7af87bc9cc03e87b38290b5951 Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Thu, 8 Sep 2022 18:23:35 +0800 Subject: [PATCH 28/55] Add the response to setup request. --- .../register/impl/ServerAbilities.java | 2 + .../remote/request/ConnectResetRequest.java | 20 ++++++ .../api/remote/request/SetupAckRequest.java | 49 +++++++++++++++ .../api/remote/response/SetupAckResponse.java | 26 ++++++++ .../nacos/common/remote/client/RpcClient.java | 10 +++ .../common/remote/client/grpc/GrpcClient.java | 61 ++++++++++++++++++- .../core/ability/config/AbilityConfigs.java | 8 ++- .../nacos/core/remote/ConnectionManager.java | 1 + .../grpc/GrpcBiStreamRequestAcceptor.java | 13 +++- .../core/remote/grpc/GrpcRequestAcceptor.java | 1 - 10 files changed, 184 insertions(+), 7 deletions(-) create mode 100644 api/src/main/java/com/alibaba/nacos/api/remote/request/SetupAckRequest.java create mode 100644 api/src/main/java/com/alibaba/nacos/api/remote/response/SetupAckResponse.java diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java index ca5fecdef..f3a098b4b 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java @@ -45,6 +45,8 @@ public class ServerAbilities extends AbstractAbilityRegistry { * */ // put ability here, which you want current server supports + supportedAbilities.put(AbilityKey.TEST_1, true); + supportedAbilities.put(AbilityKey.TEST_2, true); } private ServerAbilities() { diff --git a/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectResetRequest.java b/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectResetRequest.java index 1a2e14424..75c6fa0ca 100644 --- a/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectResetRequest.java +++ b/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectResetRequest.java @@ -30,11 +30,31 @@ public class ConnectResetRequest extends ServerRequest { String serverPort; + String connectionId; + @Override public String getModule() { return INTERNAL_MODULE; } + /** + * Getter method for property connectionId. + * + * @return property value of connectionId + */ + public String getConnectionId() { + return connectionId; + } + + /** + * Setter method for property connectionId. + * + * @param connectionId value to be assigned to property connectionId + */ + public void setConnectionId(String connectionId) { + this.connectionId = connectionId; + } + /** * Getter method for property serverIp. * diff --git a/api/src/main/java/com/alibaba/nacos/api/remote/request/SetupAckRequest.java b/api/src/main/java/com/alibaba/nacos/api/remote/request/SetupAckRequest.java new file mode 100644 index 000000000..66f6eb238 --- /dev/null +++ b/api/src/main/java/com/alibaba/nacos/api/remote/request/SetupAckRequest.java @@ -0,0 +1,49 @@ +/* + * Copyright 1999-2022 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.nacos.api.remote.request; + +import static com.alibaba.nacos.api.common.Constants.Remote.INTERNAL_MODULE; + +/**. + * @author Daydreamer + * @description Server tells the client that the connection is established + * @date 2022/7/12 19:21 + **/ +public class SetupAckRequest extends ServerRequest { + + private String connectionId; + + public SetupAckRequest() { + } + + public SetupAckRequest(String connectionId) { + this.connectionId = connectionId; + } + + public String getConnectionId() { + return connectionId; + } + + public void setConnectionId(String connectionId) { + this.connectionId = connectionId; + } + + @Override + public String getModule() { + return INTERNAL_MODULE; + } +} diff --git a/api/src/main/java/com/alibaba/nacos/api/remote/response/SetupAckResponse.java b/api/src/main/java/com/alibaba/nacos/api/remote/response/SetupAckResponse.java new file mode 100644 index 000000000..ce4abcb94 --- /dev/null +++ b/api/src/main/java/com/alibaba/nacos/api/remote/response/SetupAckResponse.java @@ -0,0 +1,26 @@ +/* + * Copyright 1999-2022 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.nacos.api.remote.response; + +/**. + * @author Daydreamer + * @description Server tells the client that the connection is established + * @date 2022/7/12 19:21 + **/ +public class SetupAckResponse extends Response { + +} diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java index 59d8134ec..6a65ae146 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java @@ -433,6 +433,7 @@ public abstract class RpcClient implements Closeable { } else { switchServerAsync(); } + afterReset(connectResetRequest); } } } catch (Exception e) { @@ -444,6 +445,15 @@ public abstract class RpcClient implements Closeable { } } + /**. + * invoke after receiving reset request + * + * @param request request for resetting + */ + protected void afterReset(ConnectResetRequest request) { + // hook for GrpcClient + } + @Override public void shutdown() throws NacosException { LOGGER.info("Shutdown rpc client, set status to shutdown"); diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java index 73ae05692..0fe29f41c 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java @@ -22,12 +22,15 @@ import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.grpc.auto.BiRequestStreamGrpc; import com.alibaba.nacos.api.grpc.auto.Payload; import com.alibaba.nacos.api.grpc.auto.RequestGrpc; +import com.alibaba.nacos.api.remote.request.ConnectResetRequest; import com.alibaba.nacos.api.remote.request.ConnectionSetupRequest; import com.alibaba.nacos.api.remote.request.Request; import com.alibaba.nacos.api.remote.request.ServerCheckRequest; +import com.alibaba.nacos.api.remote.request.SetupAckRequest; import com.alibaba.nacos.api.remote.response.ErrorResponse; import com.alibaba.nacos.api.remote.response.Response; import com.alibaba.nacos.api.remote.response.ServerCheckResponse; +import com.alibaba.nacos.api.remote.response.SetupAckResponse; import com.alibaba.nacos.api.utils.AbilityTableUtils; import com.alibaba.nacos.common.ability.discover.NacosAbilityManagerHolder; import com.alibaba.nacos.common.remote.ConnectionType; @@ -48,6 +51,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -75,6 +81,11 @@ public abstract class GrpcClient extends RpcClient { private static final long DEFAULT_KEEP_ALIVE_TIME = 6 * 60 * 1000; + /**. + * Block to wait setup success response + */ + private final Map markForSetup = new ConcurrentHashMap<>(); + @Override public ConnectionType getConnectionType() { return ConnectionType.GRPC; @@ -85,6 +96,19 @@ public abstract class GrpcClient extends RpcClient { */ public GrpcClient(String name) { super(name); + + // register to handler setup request + registerServerRequestHandler((request) -> { + // if finish setup + if (request instanceof SetupAckRequest) { + SetupAckRequest setupAckRequest = (SetupAckRequest) request; + // remove and count down + Optional.ofNullable(markForSetup.remove((setupAckRequest.getConnectionId()))) + .orElse(new CountDownLatch(1)) + .countDown(); + } + return new SetupAckResponse(); + }); } /** @@ -247,6 +271,10 @@ public abstract class GrpcClient extends RpcClient { LoggerUtils.printIfErrorEnabled(LOGGER, "[{}]Error to process server push response: {}", grpcConn.getConnectionId(), payload.getBody().getValue().toStringUtf8()); + // remove and notify + Optional.ofNullable(markForSetup.remove(grpcConn.getConnectionId())) + .orElse(new CountDownLatch(1)) + .countDown(); } } @@ -299,6 +327,8 @@ public abstract class GrpcClient extends RpcClient { @Override public Connection connectToServer(ServerInfo serverInfo) { + // the newest connection id + String connectionId = ""; try { if (grpcExecutor == null) { this.grpcExecutor = createGrpcExecutor(serverInfo.getServerIp()); @@ -317,21 +347,25 @@ public abstract class GrpcClient extends RpcClient { // submit ability table as soon as possible // ability table will be null if server doesn't support ability table ServerCheckResponse serverCheckResponse = (ServerCheckResponse) response; + connectionId = serverCheckResponse.getConnectionId(); AbilityTable table = new AbilityTable(); table.setServer(true) - .setConnectionId(serverCheckResponse.getConnectionId()); + .setConnectionId(connectionId); + // if not supported, it will be null if (serverCheckResponse.getAbilities() != null) { Map abilityTable = AbilityTableUtils .getAbilityTableBy(serverCheckResponse.getAbilities(), AbilityKey.offset()); table.setAbility(abilityTable); + // mark + markForSetup.put(serverCheckResponse.getConnectionId(), new CountDownLatch(1)); } NacosAbilityManagerHolder.getInstance().addNewTable(table); BiRequestStreamGrpc.BiRequestStreamStub biRequestStreamStub = BiRequestStreamGrpc .newStub(newChannelStubTemp.getChannel()); GrpcConnection grpcConn = new GrpcConnection(serverInfo, grpcExecutor); - grpcConn.setConnectionId(((ServerCheckResponse) response).getConnectionId()); + grpcConn.setConnectionId(connectionId); //create stream request and bind connection event to this connection. StreamObserver payloadStreamObserver = bindRequestStream(biRequestStreamStub, grpcConn); @@ -351,6 +385,14 @@ public abstract class GrpcClient extends RpcClient { conSetupRequest.setServer(isServer()); conSetupRequest.setTenant(super.getTenant()); grpcConn.sendRequest(conSetupRequest); + // wait for response + CountDownLatch synResponse = markForSetup.get(connectionId); + if (synResponse != null) { + synResponse.await(2000L, TimeUnit.MICROSECONDS); + // ensure remove, it may being reset + markForSetup.remove(connectionId); + } + // leave for adapting old version server //wait to register connection setup Thread.sleep(100L); return grpcConn; @@ -358,10 +400,25 @@ public abstract class GrpcClient extends RpcClient { return null; } catch (Exception e) { LOGGER.error("[{}]Fail to connect to server!,error={}", GrpcClient.this.getName(), e); + // remove and notify + Optional.ofNullable(markForSetup.remove(connectionId)) + .orElse(new CountDownLatch(1)) + .countDown(); } return null; } + @Override + protected void afterReset(ConnectResetRequest request) { + String connectionId = request.getConnectionId(); + if (connectionId != null) { + // remove and notify + Optional.ofNullable(markForSetup.remove(connectionId)) + .orElse(new CountDownLatch(1)) + .countDown(); + } + } + /** * Return whether server environment * The same offset may refer to different functions in the client capability table and the server capability table. diff --git a/core/src/main/java/com/alibaba/nacos/core/ability/config/AbilityConfigs.java b/core/src/main/java/com/alibaba/nacos/core/ability/config/AbilityConfigs.java index 084dc7f6a..1b49e8e19 100644 --- a/core/src/main/java/com/alibaba/nacos/core/ability/config/AbilityConfigs.java +++ b/core/src/main/java/com/alibaba/nacos/core/ability/config/AbilityConfigs.java @@ -64,9 +64,11 @@ public class AbilityConfigs extends Subscriber { serverAbilityKeys.forEach(abilityKey -> { String key = PREFIX + abilityKey.getName(); try { - // default true - Boolean property = EnvUtil.getProperty(key, Boolean.class, true); - newValues.put(abilityKey, property); + // scan + Boolean property = EnvUtil.getProperty(key, Boolean.class); + if (property != null) { + newValues.put(abilityKey, property); + } } catch (Exception e) { LOGGER.warn("Update ability config from env failed, use old val, ability : {} , because : {}", key, e); } diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/ConnectionManager.java b/core/src/main/java/com/alibaba/nacos/core/remote/ConnectionManager.java index c3ae2393f..f51427ea8 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/ConnectionManager.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/ConnectionManager.java @@ -511,6 +511,7 @@ public class ConnectionManager extends Subscriber Date: Thu, 8 Sep 2022 18:34:03 +0800 Subject: [PATCH 29/55] Remove the unused filed. --- .../api/remote/request/ConnectionSetupRequest.java | 13 ------------- .../nacos/common/remote/client/grpc/GrpcClient.java | 9 --------- .../remote/client/grpc/GrpcClusterClient.java | 5 ----- .../common/remote/client/grpc/GrpcSdkClient.java | 5 ----- .../common/remote/client/grpc/GrpcClientTest.java | 5 ----- 5 files changed, 37 deletions(-) diff --git a/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequest.java b/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequest.java index 15b3c35d5..046a897a4 100644 --- a/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequest.java +++ b/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequest.java @@ -35,19 +35,6 @@ public class ConnectionSetupRequest extends InternalRequest { private byte[] abilityTable; - /**. - * server will resolve {@link ConnectionSetupRequest#abilityTable} to server abilities, or to client abilities - */ - private boolean isServer; - - public boolean isServer() { - return isServer; - } - - public void setServer(boolean server) { - isServer = server; - } - public ConnectionSetupRequest() { } diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java index 0fe29f41c..401254059 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java @@ -382,7 +382,6 @@ public abstract class GrpcClient extends RpcClient { byte[] bitTable = AbilityTableUtils.getAbilityBiTableBy(AbilityKey.values(), NacosAbilityManagerHolder.getInstance().getCurrentRunningAbility()); conSetupRequest.setAbilityTable(bitTable); - conSetupRequest.setServer(isServer()); conSetupRequest.setTenant(super.getTenant()); grpcConn.sendRequest(conSetupRequest); // wait for response @@ -419,14 +418,6 @@ public abstract class GrpcClient extends RpcClient { } } - /** - * Return whether server environment - * The same offset may refer to different functions in the client capability table and the server capability table. - * - * @return whether server environment - */ - protected abstract boolean isServer(); - } diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClusterClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClusterClient.java index 74919ba07..7b63653b6 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClusterClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClusterClient.java @@ -35,11 +35,6 @@ public class GrpcClusterClient extends GrpcClient { super(name); } - @Override - protected boolean isServer() { - return true; - } - @Override public int rpcPortOffset() { return Integer.parseInt(System.getProperty(NACOS_SERVER_GRPC_PORT_OFFSET_KEY, diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcSdkClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcSdkClient.java index 46cd691f6..34cf40824 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcSdkClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcSdkClient.java @@ -35,11 +35,6 @@ public class GrpcSdkClient extends GrpcClient { super(name); } - @Override - protected boolean isServer() { - return false; - } - @Override public int rpcPortOffset() { return Integer.parseInt(System.getProperty(NACOS_SERVER_GRPC_PORT_OFFSET_KEY, diff --git a/common/src/test/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClientTest.java b/common/src/test/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClientTest.java index af7104d13..9e3c17f7f 100644 --- a/common/src/test/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClientTest.java +++ b/common/src/test/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClientTest.java @@ -48,11 +48,6 @@ public class GrpcClientTest { public void setUp() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { grpcClient = spy(new GrpcClient("testClient") { - @Override - protected boolean isServer() { - return false; - } - @Override public int rpcPortOffset() { return 1000; From 02bd4872cac42756db7fd11ad5ea2d1360743909 Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Fri, 9 Sep 2022 18:41:04 +0800 Subject: [PATCH 30/55] Change the way to transport ability table. --- .../api/ability/constant/AbilityKey.java | 97 ++++++++++--- .../register/AbstractAbilityRegistry.java | 20 --- .../register/impl/ClientAbilities.java | 14 -- .../register/impl/ServerAbilities.java | 14 -- .../request/ConnectionSetupRequest.java | 6 +- .../remote/response/ServerCheckResponse.java | 10 +- .../nacos/api/utils/AbilityTableUtils.java | 132 ------------------ .../nacos/api/utils/AbilityKeyTest.java | 75 ++++++++++ .../api/utils/AbilityTableUtilsTest.java | 118 ---------------- .../common/remote/client/grpc/GrpcClient.java | 8 +- .../grpc/GrpcBiStreamRequestAcceptor.java | 5 +- .../core/remote/grpc/GrpcRequestAcceptor.java | 5 +- 12 files changed, 168 insertions(+), 336 deletions(-) delete mode 100644 api/src/main/java/com/alibaba/nacos/api/utils/AbilityTableUtils.java create mode 100644 api/src/test/java/com/alibaba/nacos/api/utils/AbilityKeyTest.java delete mode 100644 api/src/test/java/com/alibaba/nacos/api/utils/AbilityTableUtilsTest.java diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java index 11a26e54a..6857e73e4 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java @@ -17,6 +17,8 @@ package com.alibaba.nacos.api.ability.constant; import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; @@ -31,44 +33,101 @@ public enum AbilityKey { /**. * just for junit test */ - TEST_1("test_1", 1), + TEST_1("test_1"), /**. * just for junit test */ - TEST_2("test_2", 2); + TEST_2("test_2"); /**. * the name of a certain ability */ - private final String name; + private final String keyName; - /**. - * the offset in ability table - */ - private final int offset; - - AbilityKey(String name, int offset) { - this.name = name; - this.offset = offset; + AbilityKey(String name) { + this.keyName = name; } public String getName() { - return name; + return keyName; } - public int getOffset() { - return offset; + /**. + * All key set + */ + private static final Map ALL_ABILITIES; + + /**. + * Get all keys + * + * @return all keys + */ + public static Collection getAllValues() { + return Collections.unmodifiableCollection(ALL_ABILITIES.values()); } - private static final Map OFFSET_MAP; + /**. + * Get all names + * + * @return all names + */ + public static Collection getAllNames() { + return Collections.unmodifiableCollection(ALL_ABILITIES.keySet()); + } - public static Map offset() { - return OFFSET_MAP; + /**. + * Whether contains this name + * + * @param name key name + * @return whether contains + */ + public static boolean isLegalKey(String name) { + return ALL_ABILITIES.containsKey(name); + } + + /**. + * Map the string key to enum + * + * @param abilities map + * @return enum map + */ + public static Map mapEnum(Map abilities) { + if (abilities == null || abilities.isEmpty()) { + return Collections.emptyMap(); + } + return abilities.entrySet() + .stream() + .filter(entry -> isLegalKey(entry.getKey())) + .collect(Collectors.toMap((entry) -> getEnum(entry.getKey()), Map.Entry::getValue)); + } + + /**. + * Map the string key to enum + * + * @param abilities map + * @return enum map + */ + public static Map mapStr(Map abilities) { + if (abilities == null || abilities.isEmpty()) { + return Collections.emptyMap(); + } + return abilities.entrySet() + .stream() + .collect(Collectors.toMap((entry) -> entry.getKey().getName(), Map.Entry::getValue)); + } + + /** + * getter to obtain enum + * + * @param key string key + * @return enum + */ + public static AbilityKey getEnum(String key) { + return ALL_ABILITIES.get(key); } static { - OFFSET_MAP = Arrays.stream(AbilityKey.values()) - .collect(Collectors.toMap(Function.identity(), AbilityKey::getOffset)); + ALL_ABILITIES = Arrays.stream(AbilityKey.values()).collect(Collectors.toMap(AbilityKey::getName, Function.identity())); } } diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/register/AbstractAbilityRegistry.java b/api/src/main/java/com/alibaba/nacos/api/ability/register/AbstractAbilityRegistry.java index 60be843fa..40af9087c 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/register/AbstractAbilityRegistry.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/register/AbstractAbilityRegistry.java @@ -17,7 +17,6 @@ package com.alibaba.nacos.api.ability.register; import com.alibaba.nacos.api.ability.constant.AbilityKey; -import com.alibaba.nacos.api.utils.AbilityTableUtils; import java.util.Collections; import java.util.HashMap; @@ -31,25 +30,6 @@ import java.util.Map; public abstract class AbstractAbilityRegistry { protected final Map supportedAbilities = new HashMap<>(); - - private byte[] abilityBitFlag; - - /**. - * Return the static ability bit table - * - * @return ability bit table - */ - public byte[] getAbilityBitFlags() { - return abilityBitFlag.clone(); - } - - /**. - * put the bit offset to {@link AbstractAbilityRegistry#abilityBitFlag} - */ - protected void init() { - // init the bits table - abilityBitFlag = AbilityTableUtils.getAbilityBiTableBy(AbilityKey.values(), supportedAbilities); - } /**. * get static ability current server supports diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java index 39a4f7232..533f4ecdd 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java @@ -47,20 +47,6 @@ public class ClientAbilities extends AbstractAbilityRegistry { // put ability here, which you want current client supports } - private ClientAbilities() { - // put key to bit offset - init(); - } - - /**. - * get the ability offset for server - * - * @return ability offset - */ - public static byte[] getBitFlags() { - return INSTANCE.getAbilityBitFlags(); - } - /**. * get static ability current server supports * diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java index f3a098b4b..480861c0e 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java @@ -49,20 +49,6 @@ public class ServerAbilities extends AbstractAbilityRegistry { supportedAbilities.put(AbilityKey.TEST_2, true); } - private ServerAbilities() { - // put key to bit offset - init(); - } - - /**. - * get bit table - * - * @return ability offset - */ - public static byte[] getBitFlags() { - return INSTANCE.getAbilityBitFlags(); - } - /**. * get static ability current server supports * diff --git a/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequest.java b/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequest.java index 046a897a4..3409728f5 100644 --- a/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequest.java +++ b/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequest.java @@ -33,7 +33,7 @@ public class ConnectionSetupRequest extends InternalRequest { private Map labels = new HashMap<>(); - private byte[] abilityTable; + private Map abilityTable; public ConnectionSetupRequest() { } @@ -62,11 +62,11 @@ public class ConnectionSetupRequest extends InternalRequest { this.tenant = tenant; } - public byte[] getAbilityTable() { + public Map getAbilityTable() { return abilityTable; } - public void setAbilityTable(byte[] abilityTable) { + public void setAbilityTable(Map abilityTable) { this.abilityTable = abilityTable; } } diff --git a/api/src/main/java/com/alibaba/nacos/api/remote/response/ServerCheckResponse.java b/api/src/main/java/com/alibaba/nacos/api/remote/response/ServerCheckResponse.java index 4f5092fc0..d3c2ee449 100644 --- a/api/src/main/java/com/alibaba/nacos/api/remote/response/ServerCheckResponse.java +++ b/api/src/main/java/com/alibaba/nacos/api/remote/response/ServerCheckResponse.java @@ -16,6 +16,8 @@ package com.alibaba.nacos.api.remote.response; +import java.util.Map; + /** * response of server check. * @@ -26,13 +28,13 @@ public class ServerCheckResponse extends Response { private String connectionId; - private byte[] abilities; + private Map abilities; public ServerCheckResponse() { } - public ServerCheckResponse(String connectionId, byte[] abilities) { + public ServerCheckResponse(String connectionId, Map abilities) { this.connectionId = connectionId; this.abilities = abilities; } @@ -45,11 +47,11 @@ public class ServerCheckResponse extends Response { this.connectionId = connectionId; } - public byte[] getAbilities() { + public Map getAbilities() { return abilities; } - public void setAbilities(byte[] abilities) { + public void setAbilities(Map abilities) { this.abilities = abilities; } } diff --git a/api/src/main/java/com/alibaba/nacos/api/utils/AbilityTableUtils.java b/api/src/main/java/com/alibaba/nacos/api/utils/AbilityTableUtils.java deleted file mode 100644 index d99587075..000000000 --- a/api/src/main/java/com/alibaba/nacos/api/utils/AbilityTableUtils.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 1999-2022 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.nacos.api.utils; - -import com.alibaba.nacos.api.ability.constant.AbilityKey; -import com.alibaba.nacos.api.ability.register.AbstractAbilityRegistry; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -/**. - * @author Daydreamer - * @description It is used to operate ability table. - * @date 2022/7/12 19:23 - **/ -public class AbilityTableUtils { - - private static final int BASE = 128; - - private AbilityTableUtils() { - } - - /**. - * get ability bit table from Collection - * - * @param bitCollection bit offset - * @return bit table - */ - public static byte[] getAbilityBitBy(Collection bitCollection) { - if (bitCollection.size() == 0) { - return new byte[1]; - } - Integer max = Collections.max(bitCollection); - // calculate byte[] - int mark = max % 8; - int length = max / 8 + (mark == 0 ? 0 : 1); - byte[] res = new byte[length]; - bitCollection.forEach(offset -> { - int index = offset / 8 + (offset % 8 == 0 ? -1 : 0); - int flag = offset % 8; - if (flag == 0) { - flag = 8; - } - byte x = (byte) (BASE >>> (flag - 1)); - res[index] = (byte) (res[index] | x); - }); - return res; - } - - /**. - * get ability table by bits - * - * @param bits bit flag - * @param offsetMap offset from {@link AbstractAbilityRegistry} - * @return Return the Map containing AbilityTableKey and isRunning. - */ - public static Map getAbilityTableBy(byte[] bits, Map offsetMap) { - if (bits == null || offsetMap.size() == 0) { - return Collections.emptyMap(); - } - int length = bits.length; - Set> entries = offsetMap.entrySet(); - Map res = new HashMap<>(offsetMap.size()); - for (Map.Entry entry : entries) { - AbilityKey abilityKey = entry.getKey(); - Integer offset = entry.getValue(); - // if not exists - int index = offset / 8 + (offset % 8 == 0 ? -1 : 0); - if (index + 1 > length) { - res.put(abilityKey, Boolean.FALSE); - continue; - } - // find - int flag = offset % 8; - if (flag == 0) { - flag = 8; - } - byte x = (byte) (BASE >>> (flag - 1)); - byte tmp = (byte) (x & bits[index]); - res.put(abilityKey, x == tmp); - } - return res; - } - - /**. - * get ability bit table by existed ability table and offset map - * - * @param offsetMap offset from {@link AbstractAbilityRegistry} - * @return Return the Map containing AbilityTableKey and isRunning. - */ - public static byte[] getAbilityBiTableBy(Map offsetMap, Map abilityTable) { - // filter the element which abilityTable don't have or value is false - Map res = offsetMap.entrySet().stream() - .filter(item -> abilityTable.getOrDefault(item.getKey(), false)) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - return getAbilityBitBy(res.values()); - } - - /**. - * get ability bit table by existed ability table and abilityKeys array - * - * @param abilityKeys abilityKeys array - * @param abilityTable existed ability table - * @return filter ability which value is false in abilityTable - */ - public static byte[] getAbilityBiTableBy(AbilityKey[] abilityKeys, Map abilityTable) { - // filter the element which abilityTable don't have or value is false - List keyList = Arrays.stream(abilityKeys).collect(Collectors.toList()); - keyList.removeIf(key -> !abilityTable.getOrDefault(key, false)); - return getAbilityBitBy(keyList.stream().map(AbilityKey::getOffset).collect(Collectors.toList())); - } -} diff --git a/api/src/test/java/com/alibaba/nacos/api/utils/AbilityKeyTest.java b/api/src/test/java/com/alibaba/nacos/api/utils/AbilityKeyTest.java new file mode 100644 index 000000000..baf0d1c2d --- /dev/null +++ b/api/src/test/java/com/alibaba/nacos/api/utils/AbilityKeyTest.java @@ -0,0 +1,75 @@ +/* + * Copyright 1999-2022 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.nacos.api.utils; + +import com.alibaba.nacos.api.ability.constant.AbilityKey; +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +/**. + * @author Daydreamer + * @description Ability key test + * @date 2022/9/8 12:27 + **/ +public class AbilityKeyTest { + + @Test + public void testMapStr() { + Map enumMap = new HashMap<>(); + Map stringBooleanMap = AbilityKey.mapStr(enumMap); + Assert.assertEquals(0, stringBooleanMap.size()); + + enumMap.put(AbilityKey.TEST_1, true); + enumMap.put(AbilityKey.TEST_2, false); + stringBooleanMap = AbilityKey.mapStr(enumMap); + Assert.assertEquals(2, stringBooleanMap.size()); + Assert.assertTrue(stringBooleanMap.get(AbilityKey.TEST_1.getName())); + Assert.assertFalse(stringBooleanMap.get(AbilityKey.TEST_2.getName())); + + enumMap.put(AbilityKey.TEST_2, true); + stringBooleanMap = AbilityKey.mapStr(enumMap); + Assert.assertEquals(2, stringBooleanMap.size()); + Assert.assertTrue(stringBooleanMap.get(AbilityKey.TEST_1.getName())); + Assert.assertTrue(stringBooleanMap.get(AbilityKey.TEST_2.getName())); + } + + @Test + public void testMapEnum() { + Map mapStr = new HashMap<>(); + mapStr.put("test-no-existed", true); + Map enumMap = AbilityKey.mapEnum(mapStr); + Assert.assertEquals(0, enumMap.size()); + + mapStr.put(AbilityKey.TEST_2.getName(), false); + mapStr.put(AbilityKey.TEST_1.getName(), true); + enumMap = AbilityKey.mapEnum(mapStr); + Assert.assertFalse(enumMap.get(AbilityKey.TEST_2)); + Assert.assertTrue(enumMap.get(AbilityKey.TEST_1)); + + mapStr.clear(); + mapStr.put(AbilityKey.TEST_2.getName(), true); + mapStr.put(AbilityKey.TEST_1.getName(), true); + enumMap = AbilityKey.mapEnum(mapStr); + Assert.assertTrue(enumMap.get(AbilityKey.TEST_2)); + Assert.assertTrue(enumMap.get(AbilityKey.TEST_1)); + + } + +} diff --git a/api/src/test/java/com/alibaba/nacos/api/utils/AbilityTableUtilsTest.java b/api/src/test/java/com/alibaba/nacos/api/utils/AbilityTableUtilsTest.java deleted file mode 100644 index bbd2ce770..000000000 --- a/api/src/test/java/com/alibaba/nacos/api/utils/AbilityTableUtilsTest.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 1999-2022 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.nacos.api.utils; - -import com.alibaba.nacos.api.ability.constant.AbilityKey; -import org.junit.Assert; -import org.junit.Test; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -public class AbilityTableUtilsTest { - - @Test - public void testGetAbilityBitBy() { - byte[] abilityBitBy = AbilityTableUtils.getAbilityBitBy(Arrays.asList(1, 8, 9, 17)); - Assert.assertEquals(abilityBitBy[0], -127); - Assert.assertEquals(abilityBitBy[1], -128); - Assert.assertEquals(abilityBitBy[2], -128); - // clear - byte[] abilityBits = AbilityTableUtils.getAbilityBitBy(Collections.emptyList()); - Assert.assertEquals(abilityBits.length, 1); - Assert.assertEquals(abilityBits[0], 0); - } - - @Test - public void testGetAbilityTableBy() { - byte[] bytes = new byte[]{0}; - Map abilityTableBy = - AbilityTableUtils.getAbilityTableBy(bytes, AbilityKey.offset()); - Assert.assertEquals(abilityTableBy.getOrDefault(AbilityKey.TEST_1, false), false); - Assert.assertEquals(abilityTableBy.getOrDefault(AbilityKey.TEST_2, false), false); - - byte[] bytes1 = new byte[]{-64}; - Map abilityTableBy1 = - AbilityTableUtils.getAbilityTableBy(bytes1, AbilityKey.offset()); - Assert.assertEquals(abilityTableBy1.get(AbilityKey.TEST_1), true); - Assert.assertEquals(abilityTableBy1.get(AbilityKey.TEST_2), true); - - byte[] bytes2 = new byte[]{-128}; - Map abilityTableBy2 = - AbilityTableUtils.getAbilityTableBy(bytes2, AbilityKey.offset()); - Assert.assertEquals(abilityTableBy2.getOrDefault(AbilityKey.TEST_1, false), true); - Assert.assertEquals(abilityTableBy2.getOrDefault(AbilityKey.TEST_2, false), false); - - byte[] bytes3 = new byte[]{64}; - Map abilityTableBy3 = - AbilityTableUtils.getAbilityTableBy(bytes3, AbilityKey.offset()); - Assert.assertEquals(abilityTableBy3.getOrDefault(AbilityKey.TEST_1, false), false); - Assert.assertEquals(abilityTableBy3.getOrDefault(AbilityKey.TEST_2, false), true); - } - - @Test - public void testGetAbilityBiTableBy() { - Map map = new HashMap<>(); - byte[] bytes1 = AbilityTableUtils.getAbilityBiTableBy(AbilityKey.values(), map); - Assert.assertEquals(1, bytes1.length); - Assert.assertEquals(bytes1[0], 0); - - map.put(AbilityKey.TEST_1, true); - byte[] bytes2 = AbilityTableUtils.getAbilityBiTableBy(AbilityKey.values(), map); - Assert.assertEquals(1, bytes1.length); - Assert.assertEquals(bytes2[0], -128); - - map.put(AbilityKey.TEST_1, false); - map.put(AbilityKey.TEST_2, true); - byte[] bytes3 = AbilityTableUtils.getAbilityBiTableBy(AbilityKey.values(), map); - Assert.assertEquals(1, bytes3.length); - Assert.assertEquals(bytes3[0], 64); - - map.put(AbilityKey.TEST_1, true); - byte[] bytes4 = AbilityTableUtils.getAbilityBiTableBy(AbilityKey.values(), map); - Assert.assertEquals(1, bytes4.length); - Assert.assertEquals(bytes4[0], -64); - } - - @Test - public void testGetAbilityBiTable() { - Map offset = AbilityKey.offset(); - Map abilities = new HashMap<>(); - byte[] bytes1 = AbilityTableUtils.getAbilityBiTableBy(offset, abilities); - Assert.assertEquals(1, bytes1.length); - Assert.assertEquals(bytes1[0], 0); - - abilities.put(AbilityKey.TEST_1, true); - byte[] bytes2 = AbilityTableUtils.getAbilityBiTableBy(offset, abilities); - Assert.assertEquals(1, bytes2.length); - Assert.assertEquals(bytes2[0], -128); - - abilities.put(AbilityKey.TEST_2, true); - byte[] bytes3 = AbilityTableUtils.getAbilityBiTableBy(offset, abilities); - Assert.assertEquals(1, bytes3.length); - Assert.assertEquals(bytes3[0], -64); - - offset = new HashMap<>(); - offset.put(AbilityKey.TEST_1, 2); - byte[] bytes4 = AbilityTableUtils.getAbilityBiTableBy(offset, abilities); - Assert.assertEquals(1, bytes4.length); - Assert.assertEquals(bytes4[0], 64); - } - -} diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java index 401254059..308ead43b 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java @@ -31,7 +31,6 @@ import com.alibaba.nacos.api.remote.response.ErrorResponse; import com.alibaba.nacos.api.remote.response.Response; import com.alibaba.nacos.api.remote.response.ServerCheckResponse; import com.alibaba.nacos.api.remote.response.SetupAckResponse; -import com.alibaba.nacos.api.utils.AbilityTableUtils; import com.alibaba.nacos.common.ability.discover.NacosAbilityManagerHolder; import com.alibaba.nacos.common.remote.ConnectionType; import com.alibaba.nacos.common.remote.client.Connection; @@ -354,8 +353,7 @@ public abstract class GrpcClient extends RpcClient { // if not supported, it will be null if (serverCheckResponse.getAbilities() != null) { - Map abilityTable = AbilityTableUtils - .getAbilityTableBy(serverCheckResponse.getAbilities(), AbilityKey.offset()); + Map abilityTable = AbilityKey.mapEnum(serverCheckResponse.getAbilities()); table.setAbility(abilityTable); // mark markForSetup.put(serverCheckResponse.getConnectionId(), new CountDownLatch(1)); @@ -379,9 +377,7 @@ public abstract class GrpcClient extends RpcClient { conSetupRequest.setClientVersion(VersionUtils.getFullClientVersion()); conSetupRequest.setLabels(super.getLabels()); // set ability table - byte[] bitTable = AbilityTableUtils.getAbilityBiTableBy(AbilityKey.values(), - NacosAbilityManagerHolder.getInstance().getCurrentRunningAbility()); - conSetupRequest.setAbilityTable(bitTable); + conSetupRequest.setAbilityTable(AbilityKey.mapStr(NacosAbilityManagerHolder.getInstance().getCurrentRunningAbility())); conSetupRequest.setTenant(super.getTenant()); grpcConn.sendRequest(conSetupRequest); // wait for response diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java index 4dbb4d414..61f82ba64 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java @@ -24,7 +24,6 @@ import com.alibaba.nacos.api.remote.request.ConnectResetRequest; import com.alibaba.nacos.api.remote.request.ConnectionSetupRequest; import com.alibaba.nacos.api.remote.request.SetupAckRequest; import com.alibaba.nacos.api.remote.response.Response; -import com.alibaba.nacos.api.utils.AbilityTableUtils; import com.alibaba.nacos.common.remote.ConnectionType; import com.alibaba.nacos.common.remote.client.grpc.GrpcUtils; import com.alibaba.nacos.core.remote.Connection; @@ -125,8 +124,8 @@ public class GrpcBiStreamRequestAcceptor extends BiRequestStreamGrpc.BiRequestSt Connection connection = new GrpcConnection(metaInfo, responseObserver, CONTEXT_KEY_CHANNEL.get()); // null if supported if (setUpRequest.getAbilityTable() != null) { - connection.setAbilityTable(AbilityTableUtils.getAbilityTableBy(setUpRequest.getAbilityTable(), - AbilityKey.offset())); + // map to table + connection.setAbilityTable(AbilityKey.mapEnum(setUpRequest.getAbilityTable())); } boolean rejectSdkOnStarting = metaInfo.isSdkSource() && !ApplicationUtils.isStarted(); diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java index 261713558..fc9aff20b 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java @@ -26,7 +26,6 @@ import com.alibaba.nacos.api.remote.request.ServerCheckRequest; import com.alibaba.nacos.api.remote.response.ErrorResponse; import com.alibaba.nacos.api.remote.response.Response; import com.alibaba.nacos.api.remote.response.ServerCheckResponse; -import com.alibaba.nacos.api.utils.AbilityTableUtils; import com.alibaba.nacos.common.ability.discover.NacosAbilityManagerHolder; import com.alibaba.nacos.common.remote.client.grpc.GrpcUtils; import com.alibaba.nacos.core.remote.Connection; @@ -92,8 +91,8 @@ public class GrpcRequestAcceptor extends RequestGrpc.RequestImplBase { // server check. if (ServerCheckRequest.class.getSimpleName().equals(type)) { Payload serverCheckResponseP = GrpcUtils.convert(new ServerCheckResponse(CONTEXT_KEY_CONN_ID.get(), - AbilityTableUtils.getAbilityBiTableBy(AbilityKey.offset(), - NacosAbilityManagerHolder.getInstance().getCurrentRunningAbility()))); + // to str map + AbilityKey.mapStr(NacosAbilityManagerHolder.getInstance().getCurrentRunningAbility()))); traceIfNecessary(serverCheckResponseP, false); responseObserver.onNext(serverCheckResponseP); responseObserver.onCompleted(); From e3a3139c33bb9b3cc28e0645e0d64a8b1ad63994 Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Sat, 10 Sep 2022 13:53:48 +0800 Subject: [PATCH 31/55] Save the ability table to Connection. --- .../ability/ClientAbilityControlManager.java | 31 +- ...mon.ability.AbstractAbilityControlManager} | 0 .../ability/AbilityControlManagerTest.java | 45 +- .../AbstractAbilityControlManager.java | 543 +++++++++++------- .../ability/DefaultAbilityControlManager.java | 346 ----------- .../discover/NacosAbilityManagerHolder.java | 14 +- .../ability/inter/AbilityControlManager.java | 88 --- .../ability/inter/AbilityHandlerRegistry.java | 83 --- .../listener/ClientAbilityEventListener.java | 39 -- .../common/remote/client/Connection.java | 13 + .../nacos/common/remote/client/RpcClient.java | 8 - .../common/remote/client/grpc/GrpcClient.java | 23 +- .../core/ability/config/AbilityConfigs.java | 6 +- .../control/ServerAbilityControlManager.java | 188 +----- .../inte/ClusterAbilityControlSupport.java | 46 -- .../alibaba/nacos/core/remote/Connection.java | 4 + .../core/remote/grpc/GrpcRequestAcceptor.java | 2 +- .../ServerAbilityConnectionListener.java | 45 -- ...mon.ability.AbstractAbilityControlManager} | 0 .../ability/AbilityControlManagerTest.java | 130 +---- .../TestServerAbilityControlManager.java | 10 - .../ability/config/TestAbilityConfig.java | 5 - 22 files changed, 376 insertions(+), 1293 deletions(-) rename client/src/main/resources/META-INF/services/{com.alibaba.nacos.common.ability.DefaultAbilityControlManager => com.alibaba.nacos.common.ability.AbstractAbilityControlManager} (100%) delete mode 100644 common/src/main/java/com/alibaba/nacos/common/ability/DefaultAbilityControlManager.java delete mode 100644 common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityControlManager.java delete mode 100644 common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityHandlerRegistry.java delete mode 100644 common/src/main/java/com/alibaba/nacos/common/ability/listener/ClientAbilityEventListener.java delete mode 100644 core/src/main/java/com/alibaba/nacos/core/ability/inte/ClusterAbilityControlSupport.java delete mode 100644 core/src/main/java/com/alibaba/nacos/core/remote/listener/ServerAbilityConnectionListener.java rename core/src/main/resources/META-INF/services/{com.alibaba.nacos.common.ability.DefaultAbilityControlManager => com.alibaba.nacos.common.ability.AbstractAbilityControlManager} (100%) diff --git a/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java b/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java index cd3e38f66..f1cb6cf7d 100644 --- a/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java +++ b/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java @@ -17,53 +17,26 @@ package com.alibaba.nacos.client.ability; import com.alibaba.nacos.api.ability.constant.AbilityKey; -import com.alibaba.nacos.api.ability.constant.AbilityStatus; -import com.alibaba.nacos.api.ability.entity.AbilityTable; import com.alibaba.nacos.api.ability.register.impl.ClientAbilities; import com.alibaba.nacos.common.ability.AbstractAbilityControlManager; -import com.alibaba.nacos.common.ability.DefaultAbilityControlManager; -import java.util.Collections; import java.util.Map; -import java.util.Optional; /**. * @author Daydreamer * @description {@link AbstractAbilityControlManager} for nacos-client. * @date 2022/7/13 13:38 **/ -public class ClientAbilityControlManager extends DefaultAbilityControlManager { +public class ClientAbilityControlManager extends AbstractAbilityControlManager { public ClientAbilityControlManager() { } @Override - protected Map getCurrentNodeSupportAbility() { + protected Map initCurrentNodeAbilities() { return ClientAbilities.getStaticAbilities(); } - @Override - public AbilityStatus isSupport(String connectionId, AbilityKey abilityKey) { - AbilityTable abilityTable = nodeAbilityTable.get(connectionId); - if (abilityTable == null) { - return AbilityStatus.UNKNOWN; - } - Boolean isSupport = Optional.ofNullable(abilityTable.getAbility()) - .orElse(Collections.emptyMap()) - .getOrDefault(abilityKey, false); - return isSupport ? AbilityStatus.SUPPORTED : AbilityStatus.NOT_SUPPORTED; - } - - @Override - protected void add(AbilityTable table) { - // nothing to do - } - - @Override - protected void remove(String connectionId) { - // nothing to do - } - @Override public int getPriority() { // if server ability manager exist, you should choose the server one diff --git a/client/src/main/resources/META-INF/services/com.alibaba.nacos.common.ability.DefaultAbilityControlManager b/client/src/main/resources/META-INF/services/com.alibaba.nacos.common.ability.AbstractAbilityControlManager similarity index 100% rename from client/src/main/resources/META-INF/services/com.alibaba.nacos.common.ability.DefaultAbilityControlManager rename to client/src/main/resources/META-INF/services/com.alibaba.nacos.common.ability.AbstractAbilityControlManager diff --git a/client/src/test/java/com/alibaba/nacos/client/ability/AbilityControlManagerTest.java b/client/src/test/java/com/alibaba/nacos/client/ability/AbilityControlManagerTest.java index c18cbaf75..b0994fa59 100644 --- a/client/src/test/java/com/alibaba/nacos/client/ability/AbilityControlManagerTest.java +++ b/client/src/test/java/com/alibaba/nacos/client/ability/AbilityControlManagerTest.java @@ -17,8 +17,6 @@ package com.alibaba.nacos.client.ability; import com.alibaba.nacos.api.ability.constant.AbilityKey; -import com.alibaba.nacos.api.ability.constant.AbilityStatus; -import com.alibaba.nacos.api.ability.entity.AbilityTable; import com.alibaba.nacos.common.ability.handler.HandlerMapping; import org.junit.Assert; import org.junit.Before; @@ -43,35 +41,6 @@ public class AbilityControlManagerTest { clientAbilityControlManager.setCurrentSupportingAbility(newTable); } - @Test - public void testClientAdd() { - Map newTable = new HashMap<>(); - newTable.put(AbilityKey.TEST_2, true); - newTable.put(AbilityKey.TEST_1, true); - AbilityTable table = new AbilityTable(); - table.setConnectionId("test-00001"); - table.setAbility(newTable); - table.setServer(true); - clientAbilityControlManager.addNewTable(table); - Assert.assertEquals(AbilityStatus.NOT_SUPPORTED, clientAbilityControlManager.isSupport("test-00001", AbilityKey.TEST_2)); - Assert.assertEquals(AbilityStatus.SUPPORTED, clientAbilityControlManager.isSupport("test-00001", AbilityKey.TEST_1)); - } - - @Test - public void testClientRemove() { - Map clientTa = new HashMap<>(); - clientTa.put(AbilityKey.TEST_2, true); - clientTa.put(AbilityKey.TEST_1, false); - AbilityTable clientTable = new AbilityTable(); - clientTable.setConnectionId("test-01111"); - clientTable.setAbility(clientTa); - clientTable.setServer(true); - clientAbilityControlManager.addNewTable(clientTable); - Assert.assertTrue(clientAbilityControlManager.contains(clientTable.getConnectionId())); - clientAbilityControlManager.removeTable("test-01111"); - Assert.assertFalse(clientAbilityControlManager.contains(clientTable.getConnectionId())); - } - @Test public void testComponent() throws InterruptedException { enabled = 0; @@ -118,16 +87,16 @@ public class AbilityControlManagerTest { public void testPriority() throws InterruptedException { TestClientAbilityControlManager testClientAbilityControlManager = new TestClientAbilityControlManager(); AbilityKey key = AbilityKey.TEST_1; - TestPriority clusterHandlerMapping1 = new TestPriority("1"); - TestPriority clusterHandlerMapping2 = new TestPriority("2"); - TestPriority clusterHandlerMapping3 = new TestPriority("3"); + TestPriority handlerMapping1 = new TestPriority("1"); + TestPriority handlerMapping2 = new TestPriority("2"); + TestPriority handlerMapping3 = new TestPriority("3"); // first one, invoke enable() - testClientAbilityControlManager.registerComponent(key, clusterHandlerMapping2, 128); + testClientAbilityControlManager.registerComponent(key, handlerMapping2, 128); // last one, invoke enable() - testClientAbilityControlManager.registerComponent(key, clusterHandlerMapping3); + testClientAbilityControlManager.registerComponent(key, handlerMapping3); // second one, invoke enable() - testClientAbilityControlManager.registerComponent(key, clusterHandlerMapping1, 12); - // trigger cluster + testClientAbilityControlManager.registerComponent(key, handlerMapping1, 12); + // trigger testClientAbilityControlManager.trigger(key); Assert.assertEquals(3, testClientAbilityControlManager.getHandlerMapping(key).size()); // wait for invoking diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java index 469f1b99d..4b1271fc8 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java @@ -18,268 +18,381 @@ package com.alibaba.nacos.common.ability; import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.ability.register.AbstractAbilityRegistry; -import com.alibaba.nacos.api.ability.entity.AbilityTable; -import com.alibaba.nacos.common.ability.inter.AbilityControlManager; +import com.alibaba.nacos.common.JustForTest; +import com.alibaba.nacos.common.ability.handler.HandlerMapping; +import com.alibaba.nacos.common.executor.ExecutorFactory; import com.alibaba.nacos.common.notify.Event; import com.alibaba.nacos.common.notify.NotifyCenter; +import com.alibaba.nacos.common.utils.CollectionUtils; +import com.alibaba.nacos.common.utils.MapUtil; +import com.alibaba.nacos.common.utils.ThreadUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.HashMap; +import java.util.Collections; +import java.util.List; import java.util.Map; -import java.util.Set; +import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.Executor; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /**. * @author Daydreamer - * @description Base class for ability control. It can only be used internally by Nacos.It showld be sington. + * @description It is a capability control center, manager current node abilities or other control. * @date 2022/7/12 19:18 **/ -@SuppressWarnings("all") -public abstract class AbstractAbilityControlManager implements AbilityControlManager { - - +public abstract class AbstractAbilityControlManager { + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractAbilityControlManager.class); - - /** - * Abilities current supporting - *

- * key: ability key from {@link AbstractAbilityRegistry} - * value: whether to turn on + + /**. + * These handlers will be invoked when the flag of ability change key: + * ability key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey} value: + * components who want to be invoked if its interested ability turn on/off + */ + private final Map> handlerMappings = new ConcurrentHashMap<>(); + + /**. + * run for HandlerMapping + */ + private final Executor simpleThreadPool = ExecutorFactory.newSingleExecutorService(); + + /**. + * ability current node running */ protected final Map currentRunningAbility = new ConcurrentHashMap<>(); - - /** - * Ability table collections - *

- * key: connectionId - * value: AbilityTable - */ - protected final Map nodeAbilityTable = new ConcurrentHashMap<>(); - private final ReentrantLock lockForAbilityTable = new ReentrantLock(); + private final ReentrantLock lockForHandlerMappings = new ReentrantLock(); protected AbstractAbilityControlManager() { - // register events - registerAbilityEvent(); - // put abilities - currentRunningAbility.putAll(getCurrentNodeSupportAbility()); - // initialize - init(); + ThreadUtils.addShutdownHook(this::destroy); + NotifyCenter.registerToPublisher(AbilityUpdateEvent.class, 16384); + currentRunningAbility.putAll(initCurrentNodeAbilities()); } /** - * This is a hook for subclass to init current node ability - * - * @return current node ability - */ - protected abstract Map getCurrentNodeSupportAbility(); - - - private void registerAbilityEvent(){ - // register events - NotifyCenter.registerToPublisher(AbilityComeEvent.class, 16384); - NotifyCenter.registerToPublisher(AbilityExpiredEvent.class, 16384); - } - - /** - * Whether the ability current node supporting is running. Return false if current node doesn't support. + * . Turn on the ability whose key is

abilityKey

* * @param abilityKey ability key - * @return is running + * @return if turn success */ - @Override + public boolean enableCurrentNodeAbility(AbilityKey abilityKey) { + return doTurn(true, abilityKey); + } + + /** + * . Turn off the ability whose key is

abilityKey

+ * + * @param abilityKey ability key + * @return if turn success + */ + public boolean disableCurrentNodeAbility(AbilityKey abilityKey) { + return doTurn(false, abilityKey); + } + public boolean isCurrentNodeAbilityRunning(AbilityKey abilityKey) { return currentRunningAbility.getOrDefault(abilityKey, false); } - + /** - * Register a new ability table. + * Init current node abilities * - * @param table the ability table. + * @return current node abilities */ - @Override - public final void addNewTable(AbilityTable table) { - // id should not be null - String connectionId = table.getConnectionId(); - // if exists - if (contains(connectionId) || connectionId == null) { + protected abstract Map initCurrentNodeAbilities(); + + /** + * Return the abilities current node + * + * @return current abilities + */ + public Map getCurrentNodeAbilities() { + return Collections.unmodifiableMap(currentRunningAbility); + } + + /** + * . Turn on/off the ability of current node + * + * @param isOn is on + * @param abilityKey ability key from {@link AbilityKey} + * @return if turn success + */ + private boolean doTurn(boolean isOn, AbilityKey abilityKey) { + Boolean isEnabled = currentRunningAbility.get(abilityKey); + // if not supporting this key + if (isEnabled == null) { + LOGGER.warn("[AbilityControlManager] Attempt to turn on/off a not existed ability!"); + return false; + } else if (isOn == isEnabled) { + // if already turn on/off + return true; + } + // turn on/off + currentRunningAbility.put(abilityKey, isOn); + // handler mappings + triggerHandlerMappingAsyn(abilityKey, isOn, this.handlerMappings); + // notify event + AbilityUpdateEvent abilityUpdateEvent = new AbilityUpdateEvent(); + abilityUpdateEvent.setTable(Collections.unmodifiableMap(currentRunningAbility)); + abilityUpdateEvent.isOn = isOn; + abilityUpdateEvent.abilityKey = abilityKey; + NotifyCenter.publishEvent(abilityUpdateEvent); + return true; + } + + /** + * Register the component which is managed by {@link AbstractAbilityControlManager}. if you are hoping that a + * component will be invoked when turn on/off the ability whose key is

abilityKey

. + * + * @param abilityKey component key. + * @param priority the higher the priority is, the faster it will be called. + * @param handlerMapping component instance. + */ + public void registerComponent(AbilityKey abilityKey, HandlerMapping handlerMapping, int priority) { + doRegisterComponent(abilityKey, handlerMapping, this.handlerMappings, lockForHandlerMappings, priority, currentRunningAbility); + } + + /** + * Register component with the lowest priority + * + * @param abilityKey ability key + * @param handlerMapping handler + */ + public void registerComponent(AbilityKey abilityKey, HandlerMapping handlerMapping) { + registerComponent(abilityKey, handlerMapping, -1); + } + + /** + * Remove the specific type handler for a certain ability + * + * @param abilityKey ability key + * @param handlerMappingClazz type + * @return the count of handlers are removed + */ + public int removeComponent(AbilityKey abilityKey, Class handlerMappingClazz) { + return doRemove(abilityKey, handlerMappingClazz, lockForHandlerMappings, handlerMappings); + } + + public final void destroy() { + LOGGER.warn("[DefaultAbilityControlManager] - Start destroying..."); + ((ThreadPoolExecutor) simpleThreadPool).shutdown(); + if (MapUtil.isNotEmpty(handlerMappings)) { + handlerMappings.keySet().forEach(key -> doTriggerSyn(key, false, handlerMappings)); + } + // hook + doDestroy(); + LOGGER.warn("[DefaultAbilityControlManager] - Destruction of the end"); + } + + /**. + * hook for subclass + */ + protected void doDestroy() { + // for server ability manager + } + + /** + * Remove the component instance of

handlerMappingClazz

. + * + * @param abilityKey ability key from {@link AbstractAbilityRegistry} + * @param handlerMappingClazz implement of {@link HandlerMapping} + * @param lock lock for operation + * @param handlerMappingsMap handler collection map + * @return the count of components have removed + */ + protected int doRemove(AbilityKey abilityKey, Class handlerMappingClazz, Lock lock, + Map> handlerMappingsMap) { + List handlerMappings = handlerMappingsMap.get(abilityKey); + if (CollectionUtils.isEmpty(handlerMappings)) { + return 0; + } + lock.lock(); + try { + AtomicInteger count = new AtomicInteger(); + handlerMappings.removeIf(item -> { + if (item.handlerMapping.getClass().equals(handlerMappingClazz)) { + count.getAndIncrement(); + return true; + } + return false; + }); + return count.get(); + } finally { + lock.unlock(); + } + } + + public int removeAll(AbilityKey abilityKey) { + List remove = this.handlerMappings.remove(abilityKey); + return Optional.ofNullable(remove).orElse(Collections.emptyList()).size(); + } + + /**. + * Register the component into handlerMappings locking by lockForHandlerMappings to ensure concurrency security. + * + * @param abilityKey ability key + * @param handlerMapping component instance. + * @param handlerMappings container + * @param lockForHandlerMappings lock to ensure concurrency + * @param abilityTable behavioral basis of handler + */ + protected void doRegisterComponent(AbilityKey abilityKey, HandlerMapping handlerMapping, + Map> handlerMappings, Lock lockForHandlerMappings, + int priority, Map abilityTable) { + if (!currentRunningAbility.containsKey(abilityKey)) { + LOGGER.warn("[AbilityHandlePostProcessor] Failed to register processor: {}, because illegal key!", + handlerMapping.getClass().getSimpleName()); + } + + // legal key + lockForHandlerMappings.lock(); + try { + List handlers = handlerMappings.getOrDefault(abilityKey, new CopyOnWriteArrayList<>()); + HandlerWithPriority handlerWithPriority = new HandlerWithPriority(handlerMapping, priority); + handlers.add(handlerWithPriority); + handlerMappings.put(abilityKey, handlers); + // choose behavior + // enable default + if (abilityTable.getOrDefault(abilityKey, false)) { + handlerMapping.enable(); + } else { + handlerMapping.disable(); + } + } catch (Exception e) { + e.printStackTrace(); + LOGGER.error("[DefaultAbilityControlManager] Fail to register handler: {}", handlerMapping.getClass().getSimpleName()); + } finally { + lockForHandlerMappings.unlock(); + LOGGER.info("[DefaultAbilityControlManager] Successfully registered processor: {}", + handlerMapping.getClass().getSimpleName()); + } + } + + /** + * Invoke componments which linked to ability key asyn. + * + * @param key ability key from {@link AbstractAbilityRegistry} + * @param isEnabled turn on/off + * @param handlerMappingsMap handler collection + */ + protected void triggerHandlerMappingAsyn(AbilityKey key, boolean isEnabled, + Map> handlerMappingsMap) { + simpleThreadPool.execute(() -> doTriggerSyn(key, isEnabled, handlerMappingsMap)); + } + + /** + * Invoke componments which linked to ability key syn. + * + * @param key ability key from {@link AbstractAbilityRegistry} + * @param isEnabled turn on/off + * @param handlerMappingsMap handler collection + */ + protected void doTriggerSyn(AbilityKey key, boolean isEnabled, + Map> handlerMappingsMap) { + List handlerWithPriorities = handlerMappingsMap.get(key); + // return if empty + if (CollectionUtils.isEmpty(handlerWithPriorities)) { return; } - lockForAbilityTable.lock(); - try { - // check - if (contains(connectionId)) { - return; + Collections.sort(handlerWithPriorities); + // invoked all + handlerWithPriorities.forEach(handlerMappingWithPriorities -> { + // any error from current handler does not affect other handler + HandlerMapping handlerMapping = handlerMappingWithPriorities.handlerMapping; + try { + if (isEnabled) { + handlerMapping.enable(); + } else { + handlerMapping.disable(); + } + } catch (Throwable t) { + LOGGER.warn("[HandlerMapping] Failed to invoke {} :{}", handlerMapping.getClass().getSimpleName(), + t.getLocalizedMessage()); } - // hook method - add(table); - // null if not support ability table - Map clientAbilities = table.getAbility(); - if (clientAbilities != null) { - // add to nod - Set abilityKeys = table.getAbility().keySet(); - abilityKeys.forEach(abilityKey -> { - Boolean res = currentRunningAbility.getOrDefault(abilityKey, false); - Boolean coming = clientAbilities.getOrDefault(abilityKey, false); - clientAbilities.put(abilityKey, res && coming); - }); - nodeAbilityTable.put(connectionId, table); - } - } finally { - lockForAbilityTable.unlock(); - } - // publish event to subscriber - AbilityComeEvent updateEvent = new AbilityComeEvent(); - updateEvent.setConnectionId(table.getConnectionId()); - updateEvent.setTable(table); - NotifyCenter.publishEvent(updateEvent); - } - - /** - * Remove a ability table - * - * @param connectionId the ability table which is removing. - */ - @Override - public final void removeTable(String connectionId) { - AbilityTable removingTable = null; - lockForAbilityTable.lock(); - try { - // hook method - remove(connectionId); - // remove - removingTable = nodeAbilityTable.remove(connectionId); - } finally { - lockForAbilityTable.unlock(); - } - // publish event - if (removingTable != null) { - AbilityExpiredEvent expiredEvent = new AbilityExpiredEvent(); - expiredEvent.setTable(removingTable); - expiredEvent.setConnectionId(connectionId); - NotifyCenter.publishEvent(expiredEvent); - } - } - - /** - * Register a new ability table. This is a ThreadSafe method for {@link AbstractAbilityControlManager#remove(String)}. - * - * @param table the ability table. - */ - protected abstract void add(AbilityTable table); - - - /** - * Remove a ability table. This is a ThreadSafe method for {@link AbstractAbilityControlManager#add(AbilityTable)}. - * - * @param connectionId the ability table which is removing. - */ - protected abstract void remove(String connectionId); - - - /** - * wthether contains this ability table - * - * @return - */ - @Override - public boolean contains(String connectionId) { - return nodeAbilityTable.containsKey(connectionId); + }); } /** - * Initialize the manager - */ - @Override - public void init() { - // default init - // nothing to do - } - - /** - * It should be invoked before destroy - */ - @Override - public void destroy() { - // default destroy - // nothing to do - } - - /** - * A Nacos application can only have one {@link AbilityControlManager}. - * When multiple control centers exist, it is used to determine which one is preferred + * A legal nacos application has a ability control manager. + * If there are more than one, the one with higher priority is preferred * * @return priority */ public abstract int getPriority(); - - /** - * Return ability table of current node - * - * @return ability table - */ - @Override - public Map getCurrentRunningAbility() { - return new HashMap<>(this.currentRunningAbility); - } - - /** - * base class for ability - */ - public abstract class AbilityEvent extends Event { - - private static final long serialVersionUID = -123241121302761L; - - protected AbilityEvent(){} - - /** - * connection id. - */ - private String connectionId; - - /** - * ability table - */ - private AbilityTable table; - - - public String getConnectionId() { - return connectionId; - } - - public void setConnectionId(String connectionId) { - this.connectionId = connectionId; - } - - public AbilityTable getTable() { - return table; - } - - public void setTable(AbilityTable table) { - this.table = table; - } + + @JustForTest + protected Map> handlerMapping() { + return this.handlerMappings; } /** - * when a connection connected. + * Support priority handler. */ - public class AbilityComeEvent extends AbilityEvent { + protected class HandlerWithPriority implements Comparable { - private static final long serialVersionUID = -123241121302761L; - - private AbilityComeEvent(){} + /**. + * Decorated + */ + public HandlerMapping handlerMapping; + + /**. + * the higher the priority, the faster it will be called + */ + public int priority; + + public HandlerWithPriority(HandlerMapping handlerMapping, int priority) { + this.handlerMapping = handlerMapping; + this.priority = priority; + } + + @Override + public int compareTo(HandlerWithPriority o) { + return o.priority - this.priority; + } } - - /** - * when a connection disconnected. + + /**. + * notify when current node ability changing */ - public class AbilityExpiredEvent extends AbilityEvent { - - private static final long serialVersionUID = -123241121212127619L; - - private AbilityExpiredEvent(){} - + public class AbilityUpdateEvent extends Event { + + private static final long serialVersionUID = -1232411212311111L; + + private AbilityKey abilityKey; + + private boolean isOn; + + private Map table; + + private AbilityUpdateEvent(){} + + public Map getAbilityTable() { + return table; + } + + public void setTable(Map abilityTable) { + this.table = abilityTable; + } + + public AbilityKey getAbilityKey() { + return abilityKey; + } + + public void setAbilityKey(AbilityKey abilityKey) { + this.abilityKey = abilityKey; + } + + public boolean isOn() { + return isOn; + } + + public void setOn(boolean on) { + isOn = on; + } } } diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/DefaultAbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/DefaultAbilityControlManager.java deleted file mode 100644 index 01fc7a60b..000000000 --- a/common/src/main/java/com/alibaba/nacos/common/ability/DefaultAbilityControlManager.java +++ /dev/null @@ -1,346 +0,0 @@ -/* - * Copyright 1999-2022 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.nacos.common.ability; - -import com.alibaba.nacos.api.ability.constant.AbilityKey; -import com.alibaba.nacos.api.ability.register.AbstractAbilityRegistry; -import com.alibaba.nacos.api.ability.entity.AbilityTable; -import com.alibaba.nacos.common.JustForTest; -import com.alibaba.nacos.common.ability.handler.HandlerMapping; -import com.alibaba.nacos.common.ability.inter.AbilityHandlerRegistry; -import com.alibaba.nacos.common.executor.ExecutorFactory; -import com.alibaba.nacos.common.notify.NotifyCenter; -import com.alibaba.nacos.common.utils.CollectionUtils; -import com.alibaba.nacos.common.utils.MapUtil; -import com.alibaba.nacos.common.utils.ThreadUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.Executor; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -/**. - * @author Daydreamer - * @description It is a relatively complete capability control center implementation. - * @date 2022/7/12 19:18 - **/ -@SuppressWarnings("PMD.AbstractClassShouldStartWithAbstractNamingRule") -public abstract class DefaultAbilityControlManager extends AbstractAbilityControlManager - implements AbilityHandlerRegistry { - - private static final Logger LOGGER = LoggerFactory.getLogger(DefaultAbilityControlManager.class); - - /**. - * These handlers will be invoked when the flag of ability change key: - * ability key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey} value: - * components who want to be invoked if its interested ability turn on/off - */ - private final Map> handlerMappings = new ConcurrentHashMap<>(); - - /**. - * run for HandlerMapping - */ - private final Executor simpleThreadPool = ExecutorFactory.newSingleExecutorService(); - - private final ReentrantLock lockForHandlerMappings = new ReentrantLock(); - - protected DefaultAbilityControlManager() { - ThreadUtils.addShutdownHook(this::destroy); - NotifyCenter.registerToPublisher(AbilityUpdateEvent.class, 16384); - } - - /** - * . Turn on the ability whose key is

abilityKey

- * - * @param abilityKey ability key - * @return if turn success - */ - @Override - public boolean enableCurrentNodeAbility(AbilityKey abilityKey) { - return doTurn(true, abilityKey); - } - - /** - * . Turn off the ability whose key is

abilityKey

- * - * @param abilityKey ability key - * @return if turn success - */ - @Override - public boolean disableCurrentNodeAbility(AbilityKey abilityKey) { - return doTurn(false, abilityKey); - } - - /** - * . Turn on/off the ability of current node - * - * @param isOn is on - * @param abilityKey ability key from {@link AbilityKey} - * @return if turn success - */ - private boolean doTurn(boolean isOn, AbilityKey abilityKey) { - Boolean isEnabled = currentRunningAbility.get(abilityKey); - // if not supporting this key - if (isEnabled == null) { - LOGGER.warn("[AbilityControlManager] Attempt to turn on/off a not existed ability!"); - return false; - } else if (isOn == isEnabled) { - // if already turn on/off - return true; - } - // turn on/off - currentRunningAbility.put(abilityKey, isOn); - // handler mappings - triggerHandlerMappingAsyn(abilityKey, isOn, this.handlerMappings); - // notify event - AbilityUpdateEvent abilityUpdateEvent = new AbilityUpdateEvent(); - abilityUpdateEvent.setTable(new AbilityTable().setAbility(Collections.unmodifiableMap(currentRunningAbility))); - abilityUpdateEvent.isOn = isOn; - abilityUpdateEvent.abilityKey = abilityKey; - NotifyCenter.publishEvent(abilityUpdateEvent); - return true; - } - - /** - * Register the component which is managed by {@link AbstractAbilityControlManager}. if you are hoping that a - * component will be invoked when turn on/off the ability whose key is

abilityKey

. - * - * @param abilityKey component key. - * @param priority the higher the priority is, the faster it will be called. - * @param handlerMapping component instance. - */ - @Override - public void registerComponent(AbilityKey abilityKey, HandlerMapping handlerMapping, int priority) { - doRegisterComponent(abilityKey, handlerMapping, this.handlerMappings, lockForHandlerMappings, priority, currentRunningAbility); - } - - @Override - public int removeComponent(AbilityKey abilityKey, Class handlerMappingClazz) { - return doRemove(abilityKey, handlerMappingClazz, lockForHandlerMappings, handlerMappings); - } - - @Override - public final void destroy() { - LOGGER.warn("[DefaultAbilityControlManager] - Start destroying..."); - ((ThreadPoolExecutor) simpleThreadPool).shutdown(); - if (MapUtil.isNotEmpty(handlerMappings)) { - handlerMappings.keySet().forEach(key -> doTriggerSyn(key, false, handlerMappings)); - } - // hook - doDestroy(); - LOGGER.warn("[DefaultAbilityControlManager] - Destruction of the end"); - } - - /**. - * hook for subclass - */ - protected void doDestroy() { - // for server ability manager - } - - /** - * Remove the component instance of

handlerMappingClazz

. - * - * @param abilityKey ability key from {@link AbstractAbilityRegistry} - * @param handlerMappingClazz implement of {@link HandlerMapping} - * @param lock lock for operation - * @param handlerMappingsMap handler collection map - * @return the count of components have removed - */ - protected int doRemove(AbilityKey abilityKey, Class handlerMappingClazz, Lock lock, - Map> handlerMappingsMap) { - List handlerMappings = handlerMappingsMap.get(abilityKey); - if (CollectionUtils.isEmpty(handlerMappings)) { - return 0; - } - lock.lock(); - try { - AtomicInteger count = new AtomicInteger(); - handlerMappings.removeIf(item -> { - if (item.handlerMapping.getClass().equals(handlerMappingClazz)) { - count.getAndIncrement(); - return true; - } - return false; - }); - return count.get(); - } finally { - lock.unlock(); - } - } - - @Override - public int removeAll(AbilityKey abilityKey) { - List remove = this.handlerMappings.remove(abilityKey); - return Optional.ofNullable(remove).orElse(Collections.emptyList()).size(); - } - - /**. - * Register the component into handlerMappings locking by lockForHandlerMappings to ensure concurrency security. - * - * @param abilityKey ability key - * @param handlerMapping component instance. - * @param handlerMappings container - * @param lockForHandlerMappings lock to ensure concurrency - * @param abilityTable behavioral basis of handler - */ - protected void doRegisterComponent(AbilityKey abilityKey, HandlerMapping handlerMapping, - Map> handlerMappings, Lock lockForHandlerMappings, - int priority, Map abilityTable) { - if (!currentRunningAbility.containsKey(abilityKey)) { - LOGGER.warn("[AbilityHandlePostProcessor] Failed to register processor: {}, because illegal key!", - handlerMapping.getClass().getSimpleName()); - } - - // legal key - lockForHandlerMappings.lock(); - try { - List handlers = handlerMappings.getOrDefault(abilityKey, new CopyOnWriteArrayList<>()); - HandlerWithPriority handlerWithPriority = new HandlerWithPriority(handlerMapping, priority); - handlers.add(handlerWithPriority); - handlerMappings.put(abilityKey, handlers); - // choose behavior - // enable default - if (abilityTable.getOrDefault(abilityKey, false)) { - handlerMapping.enable(); - } else { - handlerMapping.disable(); - } - } catch (Exception e) { - e.printStackTrace(); - LOGGER.error("[DefaultAbilityControlManager] Fail to register handler: {}", handlerMapping.getClass().getSimpleName()); - } finally { - lockForHandlerMappings.unlock(); - LOGGER.info("[DefaultAbilityControlManager] Successfully registered processor: {}", - handlerMapping.getClass().getSimpleName()); - } - } - - /** - * Invoke componments which linked to ability key asyn. - * - * @param key ability key from {@link AbstractAbilityRegistry} - * @param isEnabled turn on/off - * @param handlerMappingsMap handler collection - */ - protected void triggerHandlerMappingAsyn(AbilityKey key, boolean isEnabled, - Map> handlerMappingsMap) { - simpleThreadPool.execute(() -> doTriggerSyn(key, isEnabled, handlerMappingsMap)); - } - - /** - * Invoke componments which linked to ability key syn. - * - * @param key ability key from {@link AbstractAbilityRegistry} - * @param isEnabled turn on/off - * @param handlerMappingsMap handler collection - */ - protected void doTriggerSyn(AbilityKey key, boolean isEnabled, - Map> handlerMappingsMap) { - List handlerWithPriorities = handlerMappingsMap.get(key); - // return if empty - if (CollectionUtils.isEmpty(handlerWithPriorities)) { - return; - } - Collections.sort(handlerWithPriorities); - // invoked all - handlerWithPriorities.forEach(handlerMappingWithPriorities -> { - // any error from current handler does not affect other handler - HandlerMapping handlerMapping = handlerMappingWithPriorities.handlerMapping; - try { - if (isEnabled) { - handlerMapping.enable(); - } else { - handlerMapping.disable(); - } - } catch (Throwable t) { - LOGGER.warn("[HandlerMapping] Failed to invoke {} :{}", handlerMapping.getClass().getSimpleName(), - t.getLocalizedMessage()); - } - }); - } - - @JustForTest - protected Map> handlerMapping() { - return this.handlerMappings; - } - - /** - * Support priority handler. - */ - protected class HandlerWithPriority implements Comparable { - - /**. - * Decorated - */ - public HandlerMapping handlerMapping; - - /**. - * the higher the priority, the faster it will be called - */ - public int priority; - - public HandlerWithPriority(HandlerMapping handlerMapping, int priority) { - this.handlerMapping = handlerMapping; - this.priority = priority; - } - - @Override - public int compareTo(HandlerWithPriority o) { - return o.priority - this.priority; - } - } - - /**. - * notify when current node ability changing - */ - public class AbilityUpdateEvent extends AbilityEvent { - - private static final long serialVersionUID = -1232411212311111L; - - private AbilityKey abilityKey; - - private boolean isOn; - - private AbilityUpdateEvent(){} - - public AbilityKey getAbilityKey() { - return abilityKey; - } - - public void setAbilityKey(AbilityKey abilityKey) { - this.abilityKey = abilityKey; - } - - public boolean isOn() { - return isOn; - } - - public void setOn(boolean on) { - isOn = on; - } - } -} diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/discover/NacosAbilityManagerHolder.java b/common/src/main/java/com/alibaba/nacos/common/ability/discover/NacosAbilityManagerHolder.java index 668e96b9d..3ca141718 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/discover/NacosAbilityManagerHolder.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/discover/NacosAbilityManagerHolder.java @@ -17,8 +17,6 @@ package com.alibaba.nacos.common.ability.discover; import com.alibaba.nacos.common.ability.AbstractAbilityControlManager; -import com.alibaba.nacos.common.ability.DefaultAbilityControlManager; -import com.alibaba.nacos.common.ability.inter.AbilityControlManager; import com.alibaba.nacos.common.spi.NacosServiceLoader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,19 +47,19 @@ public class NacosAbilityManagerHolder { /**. * singleton */ - private static DefaultAbilityControlManager abstractAbilityControlManager; + private static AbstractAbilityControlManager abstractAbilityControlManager; static { // spi discover implement - Collection load = null; + Collection load = null; try { // if server - load = NacosServiceLoader.load(DefaultAbilityControlManager.class); + load = NacosServiceLoader.load(AbstractAbilityControlManager.class); } catch (ServiceConfigurationError e) { throw new RuntimeException("[AbilityControlManager] Cannot find AbilityControlManger"); } // the priority of the server is higher - List collect = load.stream() + List collect = load.stream() .sorted(Comparator.comparingInt(AbstractAbilityControlManager::getPriority)) .collect(Collectors.toList()); // get the highest priority one @@ -76,7 +74,7 @@ public class NacosAbilityManagerHolder { * * @return BaseAbilityControlManager */ - public static DefaultAbilityControlManager getInstance() { + public static AbstractAbilityControlManager getInstance() { return abstractAbilityControlManager; } @@ -87,7 +85,7 @@ public class NacosAbilityManagerHolder { * @param target type * @return AbilityControlManager */ - public static T getInstance(Class clazz) { + public static T getInstance(Class clazz) { return clazz.cast(abstractAbilityControlManager); } } diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityControlManager.java deleted file mode 100644 index 304d673d4..000000000 --- a/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityControlManager.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 1999-2022 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.nacos.common.ability.inter; - -import com.alibaba.nacos.api.ability.constant.AbilityKey; -import com.alibaba.nacos.api.ability.constant.AbilityStatus; -import com.alibaba.nacos.api.ability.register.AbstractAbilityRegistry; -import com.alibaba.nacos.api.ability.entity.AbilityTable; - -import java.util.Map; - -/**. - * @author Daydreamer - * @description This is a base interface to manage ability table - * @date 2022/8/10 23:18 - **/ -public interface AbilityControlManager { - - /** - * Whether the ability is supported for Connection. If the ability of current node is closed, it will return false. - * - * @param connectionId the connection range of ability table. - * @param abilityKey key name which comes from {@link AbstractAbilityRegistry}. - * @return whether the ability is supported in certain connection. - */ - AbilityStatus isSupport(String connectionId, AbilityKey abilityKey); - - /** - * Whether the ability current node supporting is running. Return false if current node doesn't support. - * - * @param abilityKey ability key - * @return is running - */ - boolean isCurrentNodeAbilityRunning(AbilityKey abilityKey); - - /** - * Register a new ability table. - * - * @param table the ability table. - */ - void addNewTable(AbilityTable table); - - /**. - * Remove a ability table - * - * @param connectionId the ability table which is removing. - */ - void removeTable(String connectionId); - - /**. - * whether contains this ability table - * - * @param connectionId connection id - * @return whether contains - */ - boolean contains(String connectionId); - - /**. - * Return ability table of current node - * - * @return ability table - */ - Map getCurrentRunningAbility(); - - /**. - * Initialize the manager - */ - void init(); - - /**. - * It should be invoked before destroy - */ - void destroy(); -} diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityHandlerRegistry.java b/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityHandlerRegistry.java deleted file mode 100644 index 5cbc2a8a5..000000000 --- a/common/src/main/java/com/alibaba/nacos/common/ability/inter/AbilityHandlerRegistry.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 1999-2022 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.nacos.common.ability.inter; - -import com.alibaba.nacos.api.ability.constant.AbilityKey; -import com.alibaba.nacos.api.ability.register.AbstractAbilityRegistry; -import com.alibaba.nacos.common.ability.AbstractAbilityControlManager; -import com.alibaba.nacos.common.ability.handler.HandlerMapping; - -/**. - * @author Daydreamer - * @description It provides the capability to notify components which interested in one ability for the {@link AbilityControlManager} - * @date 2022/8/10 23:43 - **/ -public interface AbilityHandlerRegistry { - - /**. - * Turn on the ability whose key is

abilityKey

- * - * @param abilityKey ability key - * @return if turn success - */ - boolean enableCurrentNodeAbility(AbilityKey abilityKey); - - /**. - * Turn off the ability whose key is

abilityKey

- * - * @param abilityKey ability key - * @return if turn success - */ - boolean disableCurrentNodeAbility(AbilityKey abilityKey); - - /**. - * Register the component which is managed by {@link AbstractAbilityControlManager}. - * if you are hoping that a component will be invoked when turn on/off the ability whose key is

abilityKey

. - * - * @param abilityKey component key from {@link AbstractAbilityRegistry} - * @param priority a positive number, the higher the priority is, the faster it will be called. `1` is the lowest priority. - * @param handlerMapping component instance. - */ - void registerComponent(AbilityKey abilityKey, HandlerMapping handlerMapping, int priority); - - /**. - * Default method to register component with the lowest priority. - * - * @param abilityKey component key from {@link AbstractAbilityRegistry} - * @param handlerMapping component instance. - */ - default void registerComponent(AbilityKey abilityKey, HandlerMapping handlerMapping) { - registerComponent(abilityKey, handlerMapping, 1); - } - - /** - * Remove the component instance of

handlerMappingClazz

. - * - * @param abilityKey ability key from {@link AbstractAbilityRegistry} - * @param handlerMappingClazz implement of {@link HandlerMapping} - * @return the count of components have removed - */ - int removeComponent(AbilityKey abilityKey, Class handlerMappingClazz); - - /** - * Remove all {@link HandlerMapping} interested in the special ability. - * @param abilityKey abnility key from {@link AbstractAbilityRegistry} - * @return the count of components have removed - */ - int removeAll(AbilityKey abilityKey); - -} diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/listener/ClientAbilityEventListener.java b/common/src/main/java/com/alibaba/nacos/common/ability/listener/ClientAbilityEventListener.java deleted file mode 100644 index 0093709c5..000000000 --- a/common/src/main/java/com/alibaba/nacos/common/ability/listener/ClientAbilityEventListener.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 1999-2022 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.nacos.common.ability.listener; - -import com.alibaba.nacos.common.ability.discover.NacosAbilityManagerHolder; -import com.alibaba.nacos.common.remote.client.Connection; -import com.alibaba.nacos.common.remote.client.ConnectionEventListener; - -/**. - * @author Daydreamer - * @description This listener is used for remove ability table if disconnected. - * @date 2022/8/30 22:00 - **/ -public class ClientAbilityEventListener implements ConnectionEventListener { - - @Override - public void onConnected(Connection connection) { - // nothing to do - } - - @Override - public void onDisConnect(Connection connection) { - NacosAbilityManagerHolder.getInstance().removeTable(connection.getConnectionId()); - } -} diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/Connection.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/Connection.java index b56eaaa3b..51e81f448 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/Connection.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/Connection.java @@ -16,8 +16,11 @@ package com.alibaba.nacos.common.remote.client; +import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.remote.Requester; +import java.util.Map; + /** * connection on client side. * @@ -33,6 +36,8 @@ public abstract class Connection implements Requester { protected RpcClient.ServerInfo serverInfo; + protected Map abilityTable; + public Connection(RpcClient.ServerInfo serverInfo) { this.serverInfo = serverInfo; } @@ -45,6 +50,14 @@ public abstract class Connection implements Requester { this.connectionId = connectionId; } + public Map getAbilityTable() { + return abilityTable; + } + + public void setAbilityTable(Map abilityTable) { + this.abilityTable = abilityTable; + } + /** * Getter method for property abandon. * diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java index 6a65ae146..22e2e1e26 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java @@ -28,8 +28,6 @@ import com.alibaba.nacos.api.remote.response.ClientDetectionResponse; import com.alibaba.nacos.api.remote.response.ConnectResetResponse; import com.alibaba.nacos.api.remote.response.ErrorResponse; import com.alibaba.nacos.api.remote.response.Response; -import com.alibaba.nacos.common.ability.discover.NacosAbilityManagerHolder; -import com.alibaba.nacos.common.ability.listener.ClientAbilityEventListener; import com.alibaba.nacos.common.lifecycle.Closeable; import com.alibaba.nacos.common.remote.ConnectionType; import com.alibaba.nacos.common.remote.PayloadRegistry; @@ -272,9 +270,6 @@ public abstract class RpcClient implements Closeable { return; } - // add listener to remove expired ability table - registerConnectionListener(new ClientAbilityEventListener()); - clientEventExecutor = new ScheduledThreadPoolExecutor(2, r -> { Thread t = new Thread(r); t.setName("com.alibaba.nacos.client.remote.worker"); @@ -459,9 +454,6 @@ public abstract class RpcClient implements Closeable { LOGGER.info("Shutdown rpc client, set status to shutdown"); rpcClientStatus.set(RpcClientStatus.SHUTDOWN); LOGGER.info("Shutdown client event executor " + clientEventExecutor); - if (currentConnection != null) { - NacosAbilityManagerHolder.getInstance().removeTable(currentConnection.getConnectionId()); - } if (clientEventExecutor != null) { clientEventExecutor.shutdownNow(); } diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java index 308ead43b..4b37cbedf 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java @@ -17,7 +17,6 @@ package com.alibaba.nacos.common.remote.client.grpc; import com.alibaba.nacos.api.ability.constant.AbilityKey; -import com.alibaba.nacos.api.ability.entity.AbilityTable; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.grpc.auto.BiRequestStreamGrpc; import com.alibaba.nacos.api.grpc.auto.Payload; @@ -347,23 +346,19 @@ public abstract class GrpcClient extends RpcClient { // ability table will be null if server doesn't support ability table ServerCheckResponse serverCheckResponse = (ServerCheckResponse) response; connectionId = serverCheckResponse.getConnectionId(); - AbilityTable table = new AbilityTable(); - table.setServer(true) - .setConnectionId(connectionId); - - // if not supported, it will be null - if (serverCheckResponse.getAbilities() != null) { - Map abilityTable = AbilityKey.mapEnum(serverCheckResponse.getAbilities()); - table.setAbility(abilityTable); - // mark - markForSetup.put(serverCheckResponse.getConnectionId(), new CountDownLatch(1)); - } - NacosAbilityManagerHolder.getInstance().addNewTable(table); BiRequestStreamGrpc.BiRequestStreamStub biRequestStreamStub = BiRequestStreamGrpc .newStub(newChannelStubTemp.getChannel()); GrpcConnection grpcConn = new GrpcConnection(serverInfo, grpcExecutor); grpcConn.setConnectionId(connectionId); + // if not supported, it will be null + if (serverCheckResponse.getAbilities() != null) { + Map abilityTable = AbilityKey.mapEnum(serverCheckResponse.getAbilities()); + // mark + markForSetup.put(serverCheckResponse.getConnectionId(), new CountDownLatch(1)); + // set server abilities to connection + grpcConn.setAbilityTable(abilityTable); + } //create stream request and bind connection event to this connection. StreamObserver payloadStreamObserver = bindRequestStream(biRequestStreamStub, grpcConn); @@ -377,7 +372,7 @@ public abstract class GrpcClient extends RpcClient { conSetupRequest.setClientVersion(VersionUtils.getFullClientVersion()); conSetupRequest.setLabels(super.getLabels()); // set ability table - conSetupRequest.setAbilityTable(AbilityKey.mapStr(NacosAbilityManagerHolder.getInstance().getCurrentRunningAbility())); + conSetupRequest.setAbilityTable(AbilityKey.mapStr(NacosAbilityManagerHolder.getInstance().getCurrentNodeAbilities())); conSetupRequest.setTenant(super.getTenant()); grpcConn.sendRequest(conSetupRequest); // wait for response diff --git a/core/src/main/java/com/alibaba/nacos/core/ability/config/AbilityConfigs.java b/core/src/main/java/com/alibaba/nacos/core/ability/config/AbilityConfigs.java index 1b49e8e19..45b680b4b 100644 --- a/core/src/main/java/com/alibaba/nacos/core/ability/config/AbilityConfigs.java +++ b/core/src/main/java/com/alibaba/nacos/core/ability/config/AbilityConfigs.java @@ -19,8 +19,8 @@ package com.alibaba.nacos.core.ability.config; import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.ability.register.impl.ServerAbilities; import com.alibaba.nacos.common.JustForTest; +import com.alibaba.nacos.common.ability.AbstractAbilityControlManager; import com.alibaba.nacos.common.ability.discover.NacosAbilityManagerHolder; -import com.alibaba.nacos.common.ability.inter.AbilityHandlerRegistry; import com.alibaba.nacos.common.event.ServerConfigChangeEvent; import com.alibaba.nacos.common.notify.Event; import com.alibaba.nacos.common.notify.NotifyCenter; @@ -49,7 +49,7 @@ public class AbilityConfigs extends Subscriber { private final Set serverAbilityKeys = new ConcurrentHashSet<>(); - private AbilityHandlerRegistry abilityHandlerRegistry = NacosAbilityManagerHolder.getInstance(); + private AbstractAbilityControlManager abilityHandlerRegistry = NacosAbilityManagerHolder.getInstance(); public AbilityConfigs() { // load ability @@ -102,7 +102,7 @@ public class AbilityConfigs extends Subscriber { } @JustForTest - protected void setAbilityHandlerRegistry(AbilityHandlerRegistry abilityHandlerRegistry) { + protected void setAbilityHandlerRegistry(AbstractAbilityControlManager abilityHandlerRegistry) { this.abilityHandlerRegistry = abilityHandlerRegistry; } diff --git a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java index 61d32bc64..67845d821 100644 --- a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java +++ b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java @@ -17,61 +17,28 @@ package com.alibaba.nacos.core.ability.control; import com.alibaba.nacos.api.ability.constant.AbilityKey; -import com.alibaba.nacos.api.ability.constant.AbilityStatus; -import com.alibaba.nacos.api.ability.entity.AbilityTable; import com.alibaba.nacos.api.ability.register.impl.ServerAbilities; -import com.alibaba.nacos.common.JustForTest; import com.alibaba.nacos.common.ability.AbstractAbilityControlManager; -import com.alibaba.nacos.common.ability.DefaultAbilityControlManager; -import com.alibaba.nacos.common.notify.NotifyCenter; -import com.alibaba.nacos.common.utils.ConcurrentHashSet; -import com.alibaba.nacos.common.utils.MapUtil; import com.alibaba.nacos.core.ability.config.AbilityConfigs; -import com.alibaba.nacos.core.ability.inte.ClusterAbilityControlSupport; import com.alibaba.nacos.sys.env.EnvUtil; -import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; -import java.util.Optional; import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; /**. * @author Daydreamer * @description {@link AbstractAbilityControlManager} for nacos-server. * @date 2022/7/13 21:14 **/ -public class ServerAbilityControlManager extends DefaultAbilityControlManager implements ClusterAbilityControlSupport { - - /**. - * ability for cluster - */ - private final Map clusterAbilityTable = new ConcurrentHashMap<>(); - - /**. - * ability for server - */ - private final Map serversAbilityTable = new ConcurrentHashMap<>(); - - /**. - * Number of servers that do not support capability negotiation - */ - private final ConcurrentHashSet serverNoAbilityNegotiation = new ConcurrentHashSet<>(); +public class ServerAbilityControlManager extends AbstractAbilityControlManager { public ServerAbilityControlManager() { - // add current node into - AbilityTable currentNodeAbility = new AbilityTable(); - currentNodeAbility.setAbility(super.currentRunningAbility); - currentNodeAbility.setConnectionId("current-node"); - serversAbilityTable.put(currentNodeAbility.getConnectionId(), currentNodeAbility); - clusterAbilityTable.putAll(currentNodeAbility.getAbility()); - NotifyCenter.registerToPublisher(ClusterAbilityUpdateEvent.class, 16384); } @Override - protected Map getCurrentNodeSupportAbility() { + protected Map initCurrentNodeAbilities() { // static abilities Map staticAbilities = ServerAbilities.getStaticAbilities(); // all function server can support @@ -99,160 +66,9 @@ public class ServerAbilityControlManager extends DefaultAbilityControlManager im return abilityTable; } - @Override - public AbilityStatus isSupport(String connectionId, AbilityKey abilityKey) { - AbilityTable abilityTable = nodeAbilityTable.get(connectionId); - if (abilityTable == null) { - return AbilityStatus.UNKNOWN; - } - Boolean isSupport = Optional.ofNullable(abilityTable.getAbility()).orElse(Collections.emptyMap()) - .getOrDefault(abilityKey, false); - return isSupport ? AbilityStatus.SUPPORTED : AbilityStatus.NOT_SUPPORTED; - } - - /**. - * Whether all the servers currently connected support a certain capability - * - * @param abilityKey ability key - * @return whether it is turn on - */ - @Override - public AbilityStatus isClusterEnableAbilityNow(AbilityKey abilityKey) { - if (serverNoAbilityNegotiation.size() > 0) { - return AbilityStatus.UNKNOWN; - } - return clusterAbilityTable.getOrDefault(abilityKey, Boolean.FALSE) ? AbilityStatus.SUPPORTED : AbilityStatus.NOT_SUPPORTED; - } - - @Override - public Map getClusterAbility() { - return serverNoAbilityNegotiation.size() > 0 ? null : Collections.unmodifiableMap(clusterAbilityTable); - } - - @Override - protected void add(AbilityTable table) { - // from which env - boolean isServer = table.isServer(); - // if not null - if (table.getConnectionId() != null && table.getAbility() != null) { - if (isServer) { - serversAbilityTable.put(table.getConnectionId(), table); - // enter cluster - Map nodeAbility = table.getAbility(); - Set keySet = clusterAbilityTable.keySet(); - keySet.forEach(abilityKey -> { - Boolean isEnabled = clusterAbilityTable.get(abilityKey); - Boolean val = nodeAbility.getOrDefault(abilityKey, Boolean.FALSE); - // new res - Boolean newRes = val && isEnabled; - // if ability changes - if (!newRes.equals(isEnabled)) { - clusterAbilityTable.replace(abilityKey, false); - // notify - NotifyCenter.publishEvent(buildClusterEvent(abilityKey, false)); - } - }); - } - } else if (isServer && table.getAbility() == null) { - // add mark if server doesn't support ability table - serverNoAbilityNegotiation.add(table.getConnectionId()); - } - } - - private ClusterAbilityUpdateEvent buildClusterEvent(AbilityKey abilityKey, boolean isOn) { - // notify - ClusterAbilityUpdateEvent event = new ClusterAbilityUpdateEvent(); - event.setAbilityKey(abilityKey); - event.setOn(isOn); - event.setTable(new AbilityTable().setAbility(Collections.unmodifiableMap(clusterAbilityTable))); - return event; - } - - @Override - protected void remove(String connectionId) { - // from which - AbilityTable abilityTable = nodeAbilityTable.get(connectionId); - // if not support - serverNoAbilityNegotiation.remove(connectionId); - // return if null - if (abilityTable == null) { - return; - } - // from which env - if (abilityTable.isServer()) { - // remove from server ability collection if support - serversAbilityTable.remove(connectionId); - // remove from cluster - if (MapUtil.isNotEmpty(serversAbilityTable)) { - Set keySet = clusterAbilityTable.keySet(); - keySet.forEach(abilityKey -> { - Boolean isEnabled = clusterAbilityTable.getOrDefault(abilityKey, Boolean.FALSE); - // nothing to do if enabled - if (isEnabled) { - return; - } - // recalculate - Boolean newVal = serversAbilityTable.values() - .stream() - .map(AbilityTable::getAbility) - .map((map) -> map.getOrDefault(abilityKey, Boolean.FALSE)) - .reduce((a, b) -> a && b) - .orElse(Boolean.FALSE); - clusterAbilityTable.replace(abilityKey, newVal); - // if change - if (!isEnabled.equals(newVal)) { - // notify - NotifyCenter.publishEvent(buildClusterEvent(abilityKey, newVal)); - } - }); - } - } - } - @Override public int getPriority() { return 1; } - - /**. - * notify when current node ability changing - */ - public class ClusterAbilityUpdateEvent extends AbilityEvent { - - private static final long serialVersionUID = -122222411212200111L; - - private AbilityKey abilityKey; - - private boolean isOn; - - private ClusterAbilityUpdateEvent(){} - - public AbilityKey getAbilityKey() { - return abilityKey; - } - - public void setAbilityKey(AbilityKey abilityKey) { - this.abilityKey = abilityKey; - } - - public boolean isOn() { - return isOn; - } - - public void setOn(boolean on) { - isOn = on; - } - - } - - @JustForTest - protected void setClusterAbilityTable(Map map) { - clusterAbilityTable.putAll(map); - } - - @JustForTest - protected Set serverNotSupport() { - return serverNoAbilityNegotiation; - } } diff --git a/core/src/main/java/com/alibaba/nacos/core/ability/inte/ClusterAbilityControlSupport.java b/core/src/main/java/com/alibaba/nacos/core/ability/inte/ClusterAbilityControlSupport.java deleted file mode 100644 index 71f32488f..000000000 --- a/core/src/main/java/com/alibaba/nacos/core/ability/inte/ClusterAbilityControlSupport.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 1999-2022 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.nacos.core.ability.inte; - -import com.alibaba.nacos.api.ability.constant.AbilityKey; -import com.alibaba.nacos.api.ability.constant.AbilityStatus; -import com.alibaba.nacos.common.ability.inter.AbilityControlManager; - -import java.util.Map; - -/**. - * @author Daydreamer - * @description It provides the capability to manage the AbilityTable in cluster for the {@link AbilityControlManager} - * @date 2022/8/10 23:18 - **/ -public interface ClusterAbilityControlSupport { - - /**. - * Return the cluster abilities. - * - * @return the cluster abilities. - */ - Map getClusterAbility(); - - /**. - * Whether all the servers currently connected support a certain capability - * - * @param abilityKey ability key - * @return whether it is turn on - */ - AbilityStatus isClusterEnableAbilityNow(AbilityKey abilityKey); -} diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java b/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java index 2e159bce1..c5465fdd2 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java @@ -66,8 +66,10 @@ public abstract class Connection implements Requester { /** * get abilities. * + * @deprecated it is replaced by abilityTable field * @return */ + @Deprecated public ClientAbilities getAbilities() { return abilities; } @@ -75,8 +77,10 @@ public abstract class Connection implements Requester { /** * set abilities. * + * @deprecated it is replaced by abilityTable field * @param abilities abilities. */ + @Deprecated public void setAbilities(ClientAbilities abilities) { this.abilities = abilities; } diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java index fc9aff20b..bbee28629 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java @@ -92,7 +92,7 @@ public class GrpcRequestAcceptor extends RequestGrpc.RequestImplBase { if (ServerCheckRequest.class.getSimpleName().equals(type)) { Payload serverCheckResponseP = GrpcUtils.convert(new ServerCheckResponse(CONTEXT_KEY_CONN_ID.get(), // to str map - AbilityKey.mapStr(NacosAbilityManagerHolder.getInstance().getCurrentRunningAbility()))); + AbilityKey.mapStr(NacosAbilityManagerHolder.getInstance().getCurrentNodeAbilities()))); traceIfNecessary(serverCheckResponseP, false); responseObserver.onNext(serverCheckResponseP); responseObserver.onCompleted(); diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/listener/ServerAbilityConnectionListener.java b/core/src/main/java/com/alibaba/nacos/core/remote/listener/ServerAbilityConnectionListener.java deleted file mode 100644 index 7b5810592..000000000 --- a/core/src/main/java/com/alibaba/nacos/core/remote/listener/ServerAbilityConnectionListener.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 1999-2022 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.nacos.core.remote.listener; - -import com.alibaba.nacos.api.ability.entity.AbilityTable; -import com.alibaba.nacos.common.ability.discover.NacosAbilityManagerHolder; -import com.alibaba.nacos.core.remote.ClientConnectionEventListener; -import com.alibaba.nacos.core.remote.Connection; -import org.springframework.stereotype.Component; - -/**. - * @author Daydreamer - * @description This listener is used to register or remove ability table. - * @date 2022/7/17 19:18 - **/ -@Component -public class ServerAbilityConnectionListener extends ClientConnectionEventListener { - - @Override - public void clientConnected(Connection connect) { - // it will be thought from client all - AbilityTable abilityTable = new AbilityTable(connect.getMetaInfo().getConnectionId(), connect.getAbilityTable(), - false, connect.getMetaInfo().getVersion()); - NacosAbilityManagerHolder.getInstance().addNewTable(abilityTable); - } - - @Override - public void clientDisConnected(Connection connect) { - NacosAbilityManagerHolder.getInstance().removeTable(connect.getMetaInfo().getConnectionId()); - } -} diff --git a/core/src/main/resources/META-INF/services/com.alibaba.nacos.common.ability.DefaultAbilityControlManager b/core/src/main/resources/META-INF/services/com.alibaba.nacos.common.ability.AbstractAbilityControlManager similarity index 100% rename from core/src/main/resources/META-INF/services/com.alibaba.nacos.common.ability.DefaultAbilityControlManager rename to core/src/main/resources/META-INF/services/com.alibaba.nacos.common.ability.AbstractAbilityControlManager diff --git a/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java b/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java index 8a01dbc2d..dcaad35f5 100644 --- a/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java +++ b/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java @@ -17,8 +17,6 @@ package com.alibaba.nacos.core.ability; import com.alibaba.nacos.api.ability.constant.AbilityKey; -import com.alibaba.nacos.api.ability.constant.AbilityStatus; -import com.alibaba.nacos.api.ability.entity.AbilityTable; import com.alibaba.nacos.common.ability.handler.HandlerMapping; import org.junit.Assert; import org.junit.Before; @@ -40,99 +38,9 @@ public class AbilityControlManagerTest { public void inject() { Map newTable = new HashMap<>(); newTable.put(AbilityKey.TEST_1, true); - - Map cluster = new HashMap<>(); - cluster.put(AbilityKey.TEST_1, true); - serverAbilityControlManager.setClusterAbility(cluster); serverAbilityControlManager.setCurrentSupportingAbility(newTable); } - @Test - public void testClientAdd() { - Map newTable = new HashMap<>(); - newTable.put(AbilityKey.TEST_2, true); - newTable.put(AbilityKey.TEST_1, true); - AbilityTable table = new AbilityTable(); - table.setConnectionId("test-00001"); - table.setAbility(newTable); - table.setServer(true); - serverAbilityControlManager.addNewTable(table); - Assert.assertEquals(AbilityStatus.NOT_SUPPORTED, serverAbilityControlManager.isSupport("test-00001", AbilityKey.TEST_2)); - Assert.assertEquals(AbilityStatus.SUPPORTED, serverAbilityControlManager.isSupport("test-00001", AbilityKey.TEST_1)); - } - - @Test - public void testServerAdd() { - Map newTable = new HashMap<>(); - newTable.put(AbilityKey.TEST_2, true); - newTable.put(AbilityKey.TEST_1, true); - AbilityTable table = new AbilityTable(); - table.setConnectionId("test-00001"); - table.setAbility(newTable); - table.setServer(true); - serverAbilityControlManager.addNewTable(table); - Assert.assertEquals(AbilityStatus.NOT_SUPPORTED, serverAbilityControlManager.isSupport("test-00001", AbilityKey.TEST_2)); - Assert.assertEquals(AbilityStatus.SUPPORTED, serverAbilityControlManager.isSupport("test-00001", AbilityKey.TEST_1)); - - Map otherServer = new HashMap<>(); - otherServer.put(AbilityKey.TEST_2, true); - otherServer.put(AbilityKey.TEST_1, false); - AbilityTable otherServerTable = new AbilityTable(); - otherServerTable.setConnectionId("test-00000"); - otherServerTable.setAbility(otherServer); - otherServerTable.setServer(true); - serverAbilityControlManager.addNewTable(otherServerTable); - - Map clientTa = new HashMap<>(); - clientTa.put(AbilityKey.TEST_2, true); - clientTa.put(AbilityKey.TEST_1, false); - AbilityTable clientTable = new AbilityTable(); - clientTable.setConnectionId("test-00002"); - clientTable.setAbility(clientTa); - clientTable.setServer(false); - serverAbilityControlManager.addNewTable(clientTable); - - // if not support - AbilityTable serverTable = new AbilityTable(); - serverTable.setConnectionId("test-001231"); - serverTable.setServer(true); - serverAbilityControlManager.addNewTable(serverTable); - // unknown because not support - Assert.assertEquals(serverAbilityControlManager.isClusterEnableAbilityNow(AbilityKey.TEST_1), AbilityStatus.UNKNOWN); - Assert.assertEquals(serverAbilityControlManager.getServerNotSupportAbility().size(), 1); - Assert.assertTrue(serverAbilityControlManager.getServerNotSupportAbility().contains("test-001231")); - - AbilityTable serverTable1 = new AbilityTable(); - serverTable1.setConnectionId("test-001231231"); - serverTable1.setServer(true); - serverAbilityControlManager.addNewTable(serverTable1); - // unknown because not support - Assert.assertEquals(serverAbilityControlManager.isClusterEnableAbilityNow(AbilityKey.TEST_1), AbilityStatus.UNKNOWN); - Assert.assertEquals(serverAbilityControlManager.getServerNotSupportAbility().size(), 2); - Assert.assertTrue(serverAbilityControlManager.getServerNotSupportAbility().contains("test-001231231")); - - // remove then support - serverAbilityControlManager.removeTable("test-001231"); - Assert.assertEquals(serverAbilityControlManager.isClusterEnableAbilityNow(AbilityKey.TEST_1), AbilityStatus.UNKNOWN); - serverAbilityControlManager.removeTable("test-001231231"); - Assert.assertEquals(serverAbilityControlManager.isClusterEnableAbilityNow(AbilityKey.TEST_1), AbilityStatus.NOT_SUPPORTED); - } - - @Test - public void testClientRemove() { - Map clientTa = new HashMap<>(); - clientTa.put(AbilityKey.TEST_2, true); - clientTa.put(AbilityKey.TEST_1, false); - AbilityTable clientTable = new AbilityTable(); - clientTable.setConnectionId("test-01111"); - clientTable.setAbility(clientTa); - clientTable.setServer(true); - serverAbilityControlManager.addNewTable(clientTable); - Assert.assertTrue(serverAbilityControlManager.contains(clientTable.getConnectionId())); - serverAbilityControlManager.removeTable("test-01111"); - Assert.assertFalse(serverAbilityControlManager.contains(clientTable.getConnectionId())); - } - @Test public void testComponent() throws InterruptedException { enabled = 0; @@ -177,7 +85,7 @@ public class AbilityControlManagerTest { @Test public void testCurrentNodeAbility() { - Set keySet = serverAbilityControlManager.getCurrentRunningAbility().keySet(); + Set keySet = serverAbilityControlManager.getCurrentNodeAbilities().keySet(); // diable all keySet.forEach(key -> serverAbilityControlManager.disableCurrentNodeAbility(key)); // get all @@ -190,42 +98,6 @@ public class AbilityControlManagerTest { keySet.forEach(key -> { Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(key)); }); - - // add node doesn't support ability table - AbilityTable abilityTable = new AbilityTable(); - abilityTable.setServer(true); - abilityTable.setConnectionId("adsadsa1"); - serverAbilityControlManager.addNewTable(abilityTable); - // cluster abilities close - Assert.assertEquals(serverAbilityControlManager.isClusterEnableAbilityNow(AbilityKey.TEST_1), AbilityStatus.UNKNOWN); - - AbilityTable abilityTable1 = new AbilityTable(); - abilityTable1.setServer(true); - abilityTable1.setConnectionId("adsadsa2"); - serverAbilityControlManager.addNewTable(abilityTable1); - // cluster abilities still close - Assert.assertEquals(serverAbilityControlManager.isClusterEnableAbilityNow(AbilityKey.TEST_1), AbilityStatus.UNKNOWN); - Assert.assertNull(serverAbilityControlManager.getClusterAbility()); - - AbilityTable abilityTable2 = new AbilityTable(); - abilityTable2.setServer(true); - abilityTable2.setConnectionId("adsadsa3"); - Map clientTa = new HashMap<>(); - clientTa.put(AbilityKey.TEST_2, true); - clientTa.put(AbilityKey.TEST_1, false); - abilityTable2.setAbility(clientTa); - serverAbilityControlManager.addNewTable(abilityTable2); - // cluster abilities still close - Assert.assertEquals(serverAbilityControlManager.isClusterEnableAbilityNow(AbilityKey.TEST_1), AbilityStatus.UNKNOWN); - Assert.assertNull(serverAbilityControlManager.getClusterAbility()); - - // remove - serverAbilityControlManager.removeTable("adsadsa3"); - serverAbilityControlManager.removeTable("adsadsa2"); - serverAbilityControlManager.removeTable("adsadsa1"); - // cluster abilities open - Assert.assertEquals(serverAbilityControlManager.isClusterEnableAbilityNow(AbilityKey.TEST_1), AbilityStatus.SUPPORTED); - Assert.assertNotNull(serverAbilityControlManager.getClusterAbility()); } class TestHandlerMapping implements HandlerMapping { diff --git a/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java b/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java index 3953cf54e..d19fa2db6 100644 --- a/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java +++ b/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java @@ -31,19 +31,9 @@ public class TestServerAbilityControlManager extends ServerAbilityControlManager currentRunningAbility.putAll(ability); } - @JustForTest - public void setClusterAbility(Map ability) { - super.setClusterAbilityTable(ability); - } - @JustForTest public int handlerMappingCount() { return super.handlerMapping().size(); } - @JustForTest - public Set getServerNotSupportAbility() { - return super.serverNotSupport(); - } - } diff --git a/core/src/test/java/com/alibaba/nacos/core/ability/config/TestAbilityConfig.java b/core/src/test/java/com/alibaba/nacos/core/ability/config/TestAbilityConfig.java index d24b1677c..c0cbcea02 100644 --- a/core/src/test/java/com/alibaba/nacos/core/ability/config/TestAbilityConfig.java +++ b/core/src/test/java/com/alibaba/nacos/core/ability/config/TestAbilityConfig.java @@ -17,7 +17,6 @@ package com.alibaba.nacos.core.ability.config; import com.alibaba.nacos.api.ability.constant.AbilityKey; -import com.alibaba.nacos.common.ability.inter.AbilityHandlerRegistry; import java.util.Set; @@ -33,8 +32,4 @@ public class TestAbilityConfig extends AbilityConfigs { serverAbilityKeys.add(AbilityKey.TEST_1); serverAbilityKeys.add(AbilityKey.TEST_2); } - - public void setAbilityControlManager(AbilityHandlerRegistry abilityHandlerRegistry) { - super.setAbilityHandlerRegistry(abilityHandlerRegistry); - } } From 12e447e690ae300e1914079105aa4ebf917df7ad Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Sat, 10 Sep 2022 14:46:30 +0800 Subject: [PATCH 32/55] Add the connection arg to ServerRequestHandler in order to get ability easily. --- .../api/ability/constant/AbilityKey.java | 2 +- .../client/config/impl/ClientWorker.java | 4 +- .../remote/gprc/NamingPushRequestHandler.java | 3 +- .../gprc/NamingPushRequestHandlerTest.java | 4 +- .../AbstractAbilityControlManager.java | 15 ++++--- .../nacos/common/remote/client/RpcClient.java | 45 ++++++++++--------- .../remote/client/ServerRequestHandler.java | 2 +- .../common/remote/client/grpc/GrpcClient.java | 2 +- .../nacos/core/cluster/MemberUtil.java | 3 +- .../TestServerAbilityControlManager.java | 1 - 10 files changed, 45 insertions(+), 36 deletions(-) diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java index 6857e73e4..d2e71e126 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java @@ -117,7 +117,7 @@ public enum AbilityKey { .collect(Collectors.toMap((entry) -> entry.getKey().getName(), Map.Entry::getValue)); } - /** + /**. * getter to obtain enum * * @param key string key diff --git a/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java b/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java index a227d537e..4661c8d12 100644 --- a/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java +++ b/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java @@ -593,7 +593,7 @@ public class ClientWorker implements Closeable { /* * Register Config Change /Config ReSync Handler */ - rpcClientInner.registerServerRequestHandler((request) -> { + rpcClientInner.registerServerRequestHandler((request, connection) -> { if (request instanceof ConfigChangeNotifyRequest) { ConfigChangeNotifyRequest configChangeNotifyRequest = (ConfigChangeNotifyRequest) request; LOGGER.info("[{}] [server-push] config changed. dataId={}, group={},tenant={}", @@ -617,7 +617,7 @@ public class ClientWorker implements Closeable { return null; }); - rpcClientInner.registerServerRequestHandler((request) -> { + rpcClientInner.registerServerRequestHandler((request, connection) -> { if (request instanceof ClientConfigMetricRequest) { ClientConfigMetricResponse response = new ClientConfigMetricResponse(); response.setMetrics(getMetrics(((ClientConfigMetricRequest) request).getMetricsKeys())); diff --git a/client/src/main/java/com/alibaba/nacos/client/naming/remote/gprc/NamingPushRequestHandler.java b/client/src/main/java/com/alibaba/nacos/client/naming/remote/gprc/NamingPushRequestHandler.java index 5a5dbb6df..b0b4472af 100644 --- a/client/src/main/java/com/alibaba/nacos/client/naming/remote/gprc/NamingPushRequestHandler.java +++ b/client/src/main/java/com/alibaba/nacos/client/naming/remote/gprc/NamingPushRequestHandler.java @@ -21,6 +21,7 @@ import com.alibaba.nacos.api.naming.remote.response.NotifySubscriberResponse; import com.alibaba.nacos.api.remote.request.Request; import com.alibaba.nacos.api.remote.response.Response; import com.alibaba.nacos.client.naming.cache.ServiceInfoHolder; +import com.alibaba.nacos.common.remote.client.Connection; import com.alibaba.nacos.common.remote.client.ServerRequestHandler; /** @@ -37,7 +38,7 @@ public class NamingPushRequestHandler implements ServerRequestHandler { } @Override - public Response requestReply(Request request) { + public Response requestReply(Request request, Connection connection) { if (request instanceof NotifySubscriberRequest) { NotifySubscriberRequest notifyResponse = (NotifySubscriberRequest) request; serviceInfoHolder.processServiceInfo(notifyResponse.getServiceInfo()); diff --git a/client/src/test/java/com/alibaba/nacos/client/naming/remote/gprc/NamingPushRequestHandlerTest.java b/client/src/test/java/com/alibaba/nacos/client/naming/remote/gprc/NamingPushRequestHandlerTest.java index 2e70dd24c..22dc7fd64 100644 --- a/client/src/test/java/com/alibaba/nacos/client/naming/remote/gprc/NamingPushRequestHandlerTest.java +++ b/client/src/test/java/com/alibaba/nacos/client/naming/remote/gprc/NamingPushRequestHandlerTest.java @@ -24,6 +24,8 @@ import com.alibaba.nacos.api.naming.remote.response.NotifySubscriberResponse; import com.alibaba.nacos.api.remote.request.Request; import com.alibaba.nacos.api.remote.response.Response; import com.alibaba.nacos.client.naming.cache.ServiceInfoHolder; +import com.alibaba.nacos.client.naming.remote.TestConnection; +import com.alibaba.nacos.common.remote.client.RpcClient; import org.junit.Assert; import org.junit.Test; @@ -41,7 +43,7 @@ public class NamingPushRequestHandlerTest { ServiceInfo info = new ServiceInfo("name", "cluster1"); Request req = NotifySubscriberRequest.buildNotifySubscriberRequest(info); //when - Response response = handler.requestReply(req); + Response response = handler.requestReply(req, new TestConnection(new RpcClient.ServerInfo())); //then Assert.assertTrue(response instanceof NotifySubscriberResponse); verify(holder, times(1)).processServiceInfo(info); diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java index 4b1271fc8..085699136 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java @@ -99,14 +99,14 @@ public abstract class AbstractAbilityControlManager { return currentRunningAbility.getOrDefault(abilityKey, false); } - /** + /**. * Init current node abilities * * @return current node abilities */ protected abstract Map initCurrentNodeAbilities(); - /** + /**. * Return the abilities current node * * @return current abilities @@ -115,8 +115,8 @@ public abstract class AbstractAbilityControlManager { return Collections.unmodifiableMap(currentRunningAbility); } - /** - * . Turn on/off the ability of current node + /**. + * Turn on/off the ability of current node * * @param isOn is on * @param abilityKey ability key from {@link AbilityKey} @@ -157,7 +157,7 @@ public abstract class AbstractAbilityControlManager { doRegisterComponent(abilityKey, handlerMapping, this.handlerMappings, lockForHandlerMappings, priority, currentRunningAbility); } - /** + /**. * Register component with the lowest priority * * @param abilityKey ability key @@ -167,7 +167,7 @@ public abstract class AbstractAbilityControlManager { registerComponent(abilityKey, handlerMapping, -1); } - /** + /**. * Remove the specific type handler for a certain ability * * @param abilityKey ability key @@ -178,6 +178,9 @@ public abstract class AbstractAbilityControlManager { return doRemove(abilityKey, handlerMappingClazz, lockForHandlerMappings, handlerMappings); } + /**. + * Close + */ public final void destroy() { LOGGER.warn("[DefaultAbilityControlManager] - Start destroying..."); ((ThreadPoolExecutor) simpleThreadPool).shutdown(); diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java index 22e2e1e26..80cef72c6 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java @@ -16,6 +16,8 @@ package com.alibaba.nacos.common.remote.client; +import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.constant.AbilityStatus; import com.alibaba.nacos.api.common.Constants; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.remote.RequestCallBack; @@ -399,7 +401,7 @@ public abstract class RpcClient implements Closeable { registerServerRequestHandler(new ConnectResetRequestHandler()); // register client detection request. - registerServerRequestHandler(request -> { + registerServerRequestHandler((request, connection) -> { if (request instanceof ClientDetectionRequest) { return new ClientDetectionResponse(); } @@ -412,7 +414,7 @@ public abstract class RpcClient implements Closeable { class ConnectResetRequestHandler implements ServerRequestHandler { @Override - public Response requestReply(Request request) { + public Response requestReply(Request request, Connection connection) { if (request instanceof ConnectResetRequest) { @@ -831,7 +833,7 @@ public abstract class RpcClient implements Closeable { lastActiveTimeStamp = System.currentTimeMillis(); for (ServerRequestHandler serverRequestHandler : serverRequestHandlers) { try { - Response response = serverRequestHandler.requestReply(request); + Response response = serverRequestHandler.requestReply(request, currentConnection); if (response != null) { LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Ack server push request, request = {}, requestId = {}", name, @@ -1039,24 +1041,6 @@ public abstract class RpcClient implements Closeable { ServerInfo serverInfo; } - protected class RecServerAbilityContext { - - public RecServerAbilityContext(String connectionId, Map abilityTable, String version, String oldConnectionId) { - this.connectionId = connectionId; - this.abilityTable = abilityTable; - this.version = version; - this.oldConnectionId = oldConnectionId; - } - - String connectionId; - - Map abilityTable; - - String version; - - String oldConnectionId; - } - public String getTenant() { return tenant; } @@ -1064,4 +1048,23 @@ public abstract class RpcClient implements Closeable { public void setTenant(String tenant) { this.tenant = tenant; } + + /**. + * Return ability of current connection + * + * @param abilityKey ability key + * @return whether support, return null if connection is not ready + */ + public AbilityStatus getConnectionAbility(AbilityKey abilityKey) { + if (currentConnection != null) { + Map abilityTable = currentConnection.getAbilityTable(); + // if null, the server may not support ability table + if (abilityTable == null) { + return AbilityStatus.UNKNOWN; + } + return abilityTable.getOrDefault(abilityKey, false) ? AbilityStatus.SUPPORTED : AbilityStatus.NOT_SUPPORTED; + } + // return null if connection is not ready + return null; + } } diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/ServerRequestHandler.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/ServerRequestHandler.java index 19f97fde0..f4163249e 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/ServerRequestHandler.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/ServerRequestHandler.java @@ -33,6 +33,6 @@ public interface ServerRequestHandler { * @param request request * @return response. */ - Response requestReply(Request request); + Response requestReply(Request request, Connection connection); } diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java index 4b37cbedf..1467b3ddc 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java @@ -96,7 +96,7 @@ public abstract class GrpcClient extends RpcClient { super(name); // register to handler setup request - registerServerRequestHandler((request) -> { + registerServerRequestHandler((request, connection) -> { // if finish setup if (request instanceof SetupAckRequest) { SetupAckRequest setupAckRequest = (SetupAckRequest) request; diff --git a/core/src/main/java/com/alibaba/nacos/core/cluster/MemberUtil.java b/core/src/main/java/com/alibaba/nacos/core/cluster/MemberUtil.java index 07cf27b8a..6a664a30d 100644 --- a/core/src/main/java/com/alibaba/nacos/core/cluster/MemberUtil.java +++ b/core/src/main/java/com/alibaba/nacos/core/cluster/MemberUtil.java @@ -284,7 +284,8 @@ public class MemberUtil { return true; } - if (!(expected.isSupportRemoteConnection() && actual.isSupportRemoteConnection())) { + // if change + if (expected.isSupportRemoteConnection() ^ actual.isSupportRemoteConnection()) { return true; } diff --git a/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java b/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java index d19fa2db6..dea6bef4e 100644 --- a/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java +++ b/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java @@ -21,7 +21,6 @@ import com.alibaba.nacos.common.JustForTest; import com.alibaba.nacos.core.ability.control.ServerAbilityControlManager; import java.util.Map; -import java.util.Set; public class TestServerAbilityControlManager extends ServerAbilityControlManager { From 2571bb6ca7c9d35b23ac80ac6381331be21598ba Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Sat, 10 Sep 2022 15:03:02 +0800 Subject: [PATCH 33/55] Combine junit test --- .../ability/AbilityControlManagerTest.java | 157 ------------------ .../TestClientAbilityControlManager.java | 46 ----- .../ability/AbilityControlManagerTest.java | 58 +++++++ .../TestServerAbilityControlManager.java | 11 ++ 4 files changed, 69 insertions(+), 203 deletions(-) delete mode 100644 client/src/test/java/com/alibaba/nacos/client/ability/AbilityControlManagerTest.java delete mode 100644 client/src/test/java/com/alibaba/nacos/client/ability/TestClientAbilityControlManager.java diff --git a/client/src/test/java/com/alibaba/nacos/client/ability/AbilityControlManagerTest.java b/client/src/test/java/com/alibaba/nacos/client/ability/AbilityControlManagerTest.java deleted file mode 100644 index b0994fa59..000000000 --- a/client/src/test/java/com/alibaba/nacos/client/ability/AbilityControlManagerTest.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright 1999-2022 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.nacos.client.ability; - -import com.alibaba.nacos.api.ability.constant.AbilityKey; -import com.alibaba.nacos.common.ability.handler.HandlerMapping; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import java.util.HashMap; -import java.util.LinkedList; -import java.util.Map; - -public class AbilityControlManagerTest { - - private TestClientAbilityControlManager clientAbilityControlManager = new TestClientAbilityControlManager(); - - private volatile int enabled = 0; - - private volatile LinkedList testPriority = new LinkedList<>(); - - @Before - public void inject() { - Map newTable = new HashMap<>(); - newTable.put(AbilityKey.TEST_1, true); - clientAbilityControlManager.setCurrentSupportingAbility(newTable); - } - - @Test - public void testComponent() throws InterruptedException { - enabled = 0; - // invoke enable() or disable() when registering - clientAbilityControlManager.registerComponent(AbilityKey.TEST_1, new TestHandlerMapping(), -1); - Assert.assertEquals(1, clientAbilityControlManager.handlerMappingCount()); - - clientAbilityControlManager.enableCurrentNodeAbility(AbilityKey.TEST_1); - // wait for invoking handler asyn - Thread.sleep(200L); - // nothing happens if it has enabled - Assert.assertEquals(enabled, 1); - Assert.assertTrue(clientAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); - - // invoke disable() - clientAbilityControlManager.disableCurrentNodeAbility(AbilityKey.TEST_1); - // wait for invoking handler asyn - Thread.sleep(200L); - // disable will invoke handler - Assert.assertEquals(enabled, 0); - Assert.assertFalse(clientAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); - - clientAbilityControlManager.disableCurrentNodeAbility(AbilityKey.TEST_1); - // wait for invoking handler asyn - Thread.sleep(200L); - // nothing to do because it has disable - Assert.assertEquals(enabled, 0); - Assert.assertFalse(clientAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); - - clientAbilityControlManager.enableCurrentNodeAbility(AbilityKey.TEST_1); - // wait for invoking handler asyn - Thread.sleep(200L); - Assert.assertEquals(enabled, 1); - Assert.assertTrue(clientAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); - - clientAbilityControlManager.enableCurrentNodeAbility(AbilityKey.TEST_1); - // wait for invoking handler asyn - Thread.sleep(200L); - Assert.assertEquals(enabled, 1); - Assert.assertTrue(clientAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); - } - - @Test - public void testPriority() throws InterruptedException { - TestClientAbilityControlManager testClientAbilityControlManager = new TestClientAbilityControlManager(); - AbilityKey key = AbilityKey.TEST_1; - TestPriority handlerMapping1 = new TestPriority("1"); - TestPriority handlerMapping2 = new TestPriority("2"); - TestPriority handlerMapping3 = new TestPriority("3"); - // first one, invoke enable() - testClientAbilityControlManager.registerComponent(key, handlerMapping2, 128); - // last one, invoke enable() - testClientAbilityControlManager.registerComponent(key, handlerMapping3); - // second one, invoke enable() - testClientAbilityControlManager.registerComponent(key, handlerMapping1, 12); - // trigger - testClientAbilityControlManager.trigger(key); - Assert.assertEquals(3, testClientAbilityControlManager.getHandlerMapping(key).size()); - // wait for invoking - Thread.sleep(200L); - Assert.assertEquals("2", testPriority.poll()); - Assert.assertEquals("3", testPriority.poll()); - Assert.assertEquals("1", testPriority.poll()); - // here are priority - Assert.assertEquals("2", testPriority.poll()); - Assert.assertEquals("1", testPriority.poll()); - Assert.assertEquals("3", testPriority.poll()); - - // remove - testClientAbilityControlManager.registerComponent(key, new TestHandlerMapping(), -1); - Assert.assertEquals(4, testClientAbilityControlManager.getHandlerMapping(key).size()); - Assert.assertEquals(1, testClientAbilityControlManager.removeComponent(key, TestHandlerMapping.class)); - Assert.assertEquals(3, testClientAbilityControlManager.getHandlerMapping(key).size()); - testClientAbilityControlManager.removeAll(key); - Assert.assertNull(testClientAbilityControlManager.getHandlerMapping(key)); - } - - class TestPriority implements HandlerMapping { - - String mark; - - public TestPriority(String mark) { - // unique one - this.mark = mark.intern(); - } - - @Override - public void enable() { - testPriority.offer(mark); - } - - @Override - public void disable() { - testPriority.offer(mark); - } - } - - class TestHandlerMapping implements HandlerMapping { - - @Override - public void enable() { - enabled++; - } - - @Override - public void disable() { - enabled--; - } - - } - -} - - diff --git a/client/src/test/java/com/alibaba/nacos/client/ability/TestClientAbilityControlManager.java b/client/src/test/java/com/alibaba/nacos/client/ability/TestClientAbilityControlManager.java deleted file mode 100644 index df52b85f3..000000000 --- a/client/src/test/java/com/alibaba/nacos/client/ability/TestClientAbilityControlManager.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 1999-2022 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.nacos.client.ability; - -import com.alibaba.nacos.api.ability.constant.AbilityKey; -import com.alibaba.nacos.common.JustForTest; - -import java.util.List; -import java.util.Map; - -public class TestClientAbilityControlManager extends ClientAbilityControlManager { - - @JustForTest - public void setCurrentSupportingAbility(Map ability) { - currentRunningAbility.putAll(ability); - } - - @JustForTest - public int handlerMappingCount() { - return super.handlerMapping().size(); - } - - @JustForTest - public List getHandlerMapping(AbilityKey abilityKey) { - return super.handlerMapping().get(abilityKey); - } - - @JustForTest - public void trigger(AbilityKey abilityKey) { - triggerHandlerMappingAsyn(abilityKey, true, handlerMapping()); - } -} diff --git a/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java b/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java index dcaad35f5..26483920b 100644 --- a/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java +++ b/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java @@ -24,6 +24,7 @@ import org.junit.Test; import org.springframework.boot.test.context.SpringBootTest; import java.util.HashMap; +import java.util.LinkedList; import java.util.Map; import java.util.Set; @@ -33,6 +34,8 @@ public class AbilityControlManagerTest { private TestServerAbilityControlManager serverAbilityControlManager = new TestServerAbilityControlManager(); private volatile int enabled = 0; + + private volatile LinkedList testPriority = new LinkedList<>(); @Before public void inject() { @@ -100,6 +103,61 @@ public class AbilityControlManagerTest { }); } + @Test + public void testPriority() throws InterruptedException { + TestServerAbilityControlManager testClientAbilityControlManager = new TestServerAbilityControlManager(); + AbilityKey key = AbilityKey.TEST_1; + TestPriority handlerMapping1 = new TestPriority("1"); + TestPriority handlerMapping2 = new TestPriority("2"); + TestPriority handlerMapping3 = new TestPriority("3"); + // first one, invoke enable() + testClientAbilityControlManager.registerComponent(key, handlerMapping2, 128); + // last one, invoke enable() + testClientAbilityControlManager.registerComponent(key, handlerMapping3); + // second one, invoke enable() + testClientAbilityControlManager.registerComponent(key, handlerMapping1, 12); + // trigger + testClientAbilityControlManager.trigger(key); + Assert.assertEquals(3, testClientAbilityControlManager.getHandlerMapping(key).size()); + // wait for invoking + Thread.sleep(200L); + Assert.assertEquals("2", testPriority.poll()); + Assert.assertEquals("3", testPriority.poll()); + Assert.assertEquals("1", testPriority.poll()); + // here are priority + Assert.assertEquals("2", testPriority.poll()); + Assert.assertEquals("1", testPriority.poll()); + Assert.assertEquals("3", testPriority.poll()); + + // remove + testClientAbilityControlManager.registerComponent(key, new TestHandlerMapping(), -1); + Assert.assertEquals(4, testClientAbilityControlManager.getHandlerMapping(key).size()); + Assert.assertEquals(1, testClientAbilityControlManager.removeComponent(key, TestHandlerMapping.class)); + Assert.assertEquals(3, testClientAbilityControlManager.getHandlerMapping(key).size()); + testClientAbilityControlManager.removeAll(key); + Assert.assertNull(testClientAbilityControlManager.getHandlerMapping(key)); + } + + class TestPriority implements HandlerMapping { + + String mark; + + public TestPriority(String mark) { + // unique one + this.mark = mark.intern(); + } + + @Override + public void enable() { + testPriority.offer(mark); + } + + @Override + public void disable() { + testPriority.offer(mark); + } + } + class TestHandlerMapping implements HandlerMapping { @Override diff --git a/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java b/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java index dea6bef4e..e9bb30ff8 100644 --- a/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java +++ b/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java @@ -20,6 +20,7 @@ import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.common.JustForTest; import com.alibaba.nacos.core.ability.control.ServerAbilityControlManager; +import java.util.List; import java.util.Map; public class TestServerAbilityControlManager extends ServerAbilityControlManager { @@ -35,4 +36,14 @@ public class TestServerAbilityControlManager extends ServerAbilityControlManager return super.handlerMapping().size(); } + @JustForTest + public List getHandlerMapping(AbilityKey abilityKey) { + return super.handlerMapping().get(abilityKey); + } + + @JustForTest + public void trigger(AbilityKey abilityKey) { + triggerHandlerMappingAsyn(abilityKey, true, handlerMapping()); + } + } From a8c3b847c064f67b827b2a03df274eba53df07e3 Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Sat, 10 Sep 2022 20:08:15 +0800 Subject: [PATCH 34/55] Add the api to judge ability, add junit test. --- .../nacos/client/ability/AbilityTest.java | 137 ++++++++++++++++++ .../common/remote/client/Connection.java | 8 +- .../nacos/common/remote/client/RpcClient.java | 7 +- .../alibaba/nacos/core/remote/Connection.java | 8 +- 4 files changed, 150 insertions(+), 10 deletions(-) create mode 100644 client/src/test/java/com/alibaba/nacos/client/ability/AbilityTest.java diff --git a/client/src/test/java/com/alibaba/nacos/client/ability/AbilityTest.java b/client/src/test/java/com/alibaba/nacos/client/ability/AbilityTest.java new file mode 100644 index 000000000..f5f966f6e --- /dev/null +++ b/client/src/test/java/com/alibaba/nacos/client/ability/AbilityTest.java @@ -0,0 +1,137 @@ +/* + * Copyright 1999-2022 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.nacos.client.ability; + +import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.constant.AbilityStatus; +import com.alibaba.nacos.api.exception.NacosException; +import com.alibaba.nacos.api.remote.RequestCallBack; +import com.alibaba.nacos.api.remote.RequestFuture; +import com.alibaba.nacos.api.remote.request.Request; +import com.alibaba.nacos.api.remote.response.Response; +import com.alibaba.nacos.client.naming.remote.TestConnection; +import com.alibaba.nacos.common.remote.ConnectionType; +import com.alibaba.nacos.common.remote.client.Connection; +import com.alibaba.nacos.common.remote.client.RpcClient; +import com.alibaba.nacos.common.remote.client.ServerListFactory; +import com.alibaba.nacos.common.remote.client.ServerRequestHandler; +import org.junit.After; +import org.junit.Assert; +import org.junit.Test; +import java.util.HashMap; +import java.util.List; + +public class AbilityTest { + + private RpcClient rpcClient; + + private Connection connection; + + @Test + public void testReceive() throws Exception { + rpcClient = new RpcClient("name") { + + @Override + public ConnectionType getConnectionType() { + return null; + } + + @Override + public int rpcPortOffset() { + return 0; + } + + @Override + public Connection connectToServer(ServerInfo serverInfo) throws Exception { + connection = new Connection(new RpcClient.ServerInfo()) { + + { + super.abilityTable = new HashMap<>(); + super.abilityTable.put(AbilityKey.TEST_1, true); + super.abilityTable.put(AbilityKey.TEST_2, false); + } + + @Override + public Response request(Request request, long timeoutMills) throws NacosException { + return null; + } + + @Override + public RequestFuture requestFuture(Request request) throws NacosException { + return null; + } + + @Override + public void asyncRequest(Request request, RequestCallBack requestCallBack) throws NacosException { + + } + + @Override + public void close() { + + } + };; + return connection; + } + }; + rpcClient.start(); + // test not ready + Assert.assertNull(rpcClient.getConnectionAbility(AbilityKey.TEST_1)); + + // test ready + rpcClient.serverListFactory(new ServerListFactory() { + + @Override + public String genNextServer() { + return "localhost:8848"; + } + + @Override + public String getCurrentServer() { + return "localhost:8848"; + } + + @Override + public List getServerList() { + return null; + } + }); + rpcClient.start(); + // if connect successfully + Assert.assertEquals(rpcClient.getConnectionAbility(AbilityKey.TEST_1), AbilityStatus.SUPPORTED); + Assert.assertEquals(rpcClient.getConnectionAbility(AbilityKey.TEST_2), AbilityStatus.NOT_SUPPORTED); + } + + @After + public void testServerRequestAbility() { + //test support + ServerRequestHandler serverRequestHandler = (request, connection) -> { + Assert.assertEquals(connection.getConnectionAbility(AbilityKey.TEST_1), AbilityStatus.SUPPORTED); + Assert.assertEquals(connection.getConnectionAbility(AbilityKey.TEST_2), AbilityStatus.NOT_SUPPORTED); + return new Response() { }; + }; + serverRequestHandler.requestReply(null, connection); + + // test no ability table + serverRequestHandler = (request, connection) -> { + Assert.assertEquals(connection.getConnectionAbility(AbilityKey.TEST_1), AbilityStatus.UNKNOWN); + return new Response() { }; + }; + serverRequestHandler.requestReply(null, new TestConnection(new RpcClient.ServerInfo())); + } + +} diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/Connection.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/Connection.java index 51e81f448..a7e37199c 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/Connection.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/Connection.java @@ -17,6 +17,7 @@ package com.alibaba.nacos.common.remote.client; import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.constant.AbilityStatus; import com.alibaba.nacos.api.remote.Requester; import java.util.Map; @@ -50,8 +51,11 @@ public abstract class Connection implements Requester { this.connectionId = connectionId; } - public Map getAbilityTable() { - return abilityTable; + public AbilityStatus getConnectionAbility(AbilityKey abilityKey) { + if (abilityTable == null) { + return AbilityStatus.UNKNOWN; + } + return abilityTable.getOrDefault(abilityKey, false) ? AbilityStatus.SUPPORTED : AbilityStatus.NOT_SUPPORTED; } public void setAbilityTable(Map abilityTable) { diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java index 80cef72c6..f9f2143f4 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java @@ -1057,12 +1057,7 @@ public abstract class RpcClient implements Closeable { */ public AbilityStatus getConnectionAbility(AbilityKey abilityKey) { if (currentConnection != null) { - Map abilityTable = currentConnection.getAbilityTable(); - // if null, the server may not support ability table - if (abilityTable == null) { - return AbilityStatus.UNKNOWN; - } - return abilityTable.getOrDefault(abilityKey, false) ? AbilityStatus.SUPPORTED : AbilityStatus.NOT_SUPPORTED; + return currentConnection.getConnectionAbility(abilityKey); } // return null if connection is not ready return null; diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java b/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java index c5465fdd2..317fdf0ac 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java @@ -18,6 +18,7 @@ package com.alibaba.nacos.core.remote; import com.alibaba.nacos.api.ability.ClientAbilities; import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.constant.AbilityStatus; import com.alibaba.nacos.api.remote.Requester; import java.util.Map; @@ -55,8 +56,11 @@ public abstract class Connection implements Requester { this.traced = traced; } - public Map getAbilityTable() { - return abilityTable; + public AbilityStatus getConnectionAbility(AbilityKey abilityKey) { + if (abilityTable == null) { + return AbilityStatus.UNKNOWN; + } + return abilityTable.getOrDefault(abilityKey, false) ? AbilityStatus.SUPPORTED : AbilityStatus.NOT_SUPPORTED; } public void setAbilityTable(Map abilityTable) { From 8f14e63f0cb5ff3ff29d6ba22630bea168cd9de7 Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Sat, 10 Sep 2022 20:20:09 +0800 Subject: [PATCH 35/55] Combine with current node abilities. --- .../ability/AbstractAbilityControlManager.java | 14 ++++++++++++++ .../common/remote/client/grpc/GrpcClient.java | 3 +++ .../remote/grpc/GrpcBiStreamRequestAcceptor.java | 8 +++++++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java index 085699136..152946026 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java @@ -192,6 +192,20 @@ public abstract class AbstractAbilityControlManager { LOGGER.warn("[DefaultAbilityControlManager] - Destruction of the end"); } + /** + * Combine with current node abilities, in order to get abilities current node provides + * + * @param abilities combined ability table + */ + public void combine(Map abilities) { + currentRunningAbility.forEach((k, v) -> { + Boolean isCurrentSupport = currentRunningAbility.get(k); + if (isCurrentSupport != null) { + abilities.put(k, abilities.getOrDefault(k, false) && isCurrentSupport); + } + }); + } + /**. * hook for subclass */ diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java index 1467b3ddc..5221f3922 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java @@ -356,6 +356,9 @@ public abstract class GrpcClient extends RpcClient { Map abilityTable = AbilityKey.mapEnum(serverCheckResponse.getAbilities()); // mark markForSetup.put(serverCheckResponse.getConnectionId(), new CountDownLatch(1)); + // combine with current node abilities + // in order to get abilities current node provides + NacosAbilityManagerHolder.getInstance().combine(abilityTable); // set server abilities to connection grpcConn.setAbilityTable(abilityTable); } diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java index 61f82ba64..32cef2075 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java @@ -24,6 +24,7 @@ import com.alibaba.nacos.api.remote.request.ConnectResetRequest; import com.alibaba.nacos.api.remote.request.ConnectionSetupRequest; import com.alibaba.nacos.api.remote.request.SetupAckRequest; import com.alibaba.nacos.api.remote.response.Response; +import com.alibaba.nacos.common.ability.discover.NacosAbilityManagerHolder; import com.alibaba.nacos.common.remote.ConnectionType; import com.alibaba.nacos.common.remote.client.grpc.GrpcUtils; import com.alibaba.nacos.core.remote.Connection; @@ -125,7 +126,12 @@ public class GrpcBiStreamRequestAcceptor extends BiRequestStreamGrpc.BiRequestSt // null if supported if (setUpRequest.getAbilityTable() != null) { // map to table - connection.setAbilityTable(AbilityKey.mapEnum(setUpRequest.getAbilityTable())); + Map clientAbilities = AbilityKey + .mapEnum(setUpRequest.getAbilityTable()); + // combine with current node abilities + // in order to get abilities current node provides + NacosAbilityManagerHolder.getInstance().combine(clientAbilities); + connection.setAbilityTable(clientAbilities); } boolean rejectSdkOnStarting = metaInfo.isSdkSource() && !ApplicationUtils.isStarted(); From c97aca392339aae80b0657033f06a443b41c7847 Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Sat, 10 Sep 2022 20:31:14 +0800 Subject: [PATCH 36/55] Remove unused code --- .../api/ability/entity/AbilityTable.java | 103 ------------------ .../register/impl/ServerAbilities.java | 2 - .../AbstractAbilityControlManager.java | 2 +- 3 files changed, 1 insertion(+), 106 deletions(-) delete mode 100644 api/src/main/java/com/alibaba/nacos/api/ability/entity/AbilityTable.java diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/entity/AbilityTable.java b/api/src/main/java/com/alibaba/nacos/api/ability/entity/AbilityTable.java deleted file mode 100644 index 63fda78da..000000000 --- a/api/src/main/java/com/alibaba/nacos/api/ability/entity/AbilityTable.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 1999-2022 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.nacos.api.ability.entity; - -import com.alibaba.nacos.api.ability.constant.AbilityKey; - -import java.util.Map; - -/**. - * @author Daydreamer - * @description This table is linked to a server node or client node. - * @date 2022/7/12 19:25 - **/ -public class AbilityTable implements Cloneable { - - /**. - * id in connection instance - */ - private String connectionId; - - /**. - * ability table - * key: name from {@link com.alibaba.nacos.api.ability.constant.AbilityKey} - * value: whether to turn on - */ - private Map ability; - - /**. - * whether it from a server node - */ - private boolean isServer; - - /**. - * version of the client corresponding to the connection - */ - private String version; - - public AbilityTable() { - } - - public boolean isServer() { - return isServer; - } - - public AbilityTable setServer(boolean server) { - isServer = server; - return this; - } - - public String getVersion() { - return version; - } - - public AbilityTable setVersion(String version) { - this.version = version; - return this; - } - - public AbilityTable(String connectionId, Map ability, boolean isServer, String version) { - this.connectionId = connectionId; - this.ability = ability; - this.isServer = isServer; - this.version = version; - } - - public String getConnectionId() { - return connectionId; - } - - public AbilityTable setConnectionId(String connectionId) { - this.connectionId = connectionId; - return this; - } - - public Map getAbility() { - return ability; - } - - public AbilityTable setAbility(Map ability) { - this.ability = ability; - return this; - } - - @Override - public String toString() { - return "AbilityTable{" + "connectionId='" + connectionId + '\'' + ", ability=" + ability + ", isServer=" - + isServer + ", version='" + version + '\'' + '}'; - } -} diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java index 480861c0e..ca4597a4f 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java @@ -45,8 +45,6 @@ public class ServerAbilities extends AbstractAbilityRegistry { * */ // put ability here, which you want current server supports - supportedAbilities.put(AbilityKey.TEST_1, true); - supportedAbilities.put(AbilityKey.TEST_2, true); } /**. diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java index 152946026..ca8c028d2 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java @@ -192,7 +192,7 @@ public abstract class AbstractAbilityControlManager { LOGGER.warn("[DefaultAbilityControlManager] - Destruction of the end"); } - /** + /**. * Combine with current node abilities, in order to get abilities current node provides * * @param abilities combined ability table From 4cff58da13a5e962b0360d13071bdaeafaa961ee Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Sat, 10 Sep 2022 21:32:42 +0800 Subject: [PATCH 37/55] Add capability table to RequestMeta. --- .../nacos/api/remote/request/RequestMeta.java | 23 ++++++++++++++++++- .../alibaba/nacos/core/remote/Connection.java | 12 ++++------ .../core/remote/grpc/GrpcRequestAcceptor.java | 1 + 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/api/src/main/java/com/alibaba/nacos/api/remote/request/RequestMeta.java b/api/src/main/java/com/alibaba/nacos/api/remote/request/RequestMeta.java index 82eba58db..c212ebe33 100644 --- a/api/src/main/java/com/alibaba/nacos/api/remote/request/RequestMeta.java +++ b/api/src/main/java/com/alibaba/nacos/api/remote/request/RequestMeta.java @@ -16,6 +16,9 @@ package com.alibaba.nacos.api.remote.request; +import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.constant.AbilityStatus; + import java.util.HashMap; import java.util.Map; @@ -34,7 +37,25 @@ public class RequestMeta { private String clientVersion = ""; private Map labels = new HashMap<>(); - + + private Map abilityTable; + + public AbilityStatus getConnectionAbility(AbilityKey abilityKey) { + if (abilityTable == null) { + return AbilityStatus.UNKNOWN; + } + return abilityTable.getOrDefault(abilityKey, false) ? AbilityStatus.SUPPORTED : AbilityStatus.NOT_SUPPORTED; + } + + /** + * Setter method for property abilityTable. + * + * @param abilityTable property value of clientVersion + */ + public void setAbilityTable(Map abilityTable) { + this.abilityTable = abilityTable; + } + /** * Getter method for property clientVersion. * diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java b/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java index 317fdf0ac..6f49a3ca7 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java @@ -18,7 +18,6 @@ package com.alibaba.nacos.core.remote; import com.alibaba.nacos.api.ability.ClientAbilities; import com.alibaba.nacos.api.ability.constant.AbilityKey; -import com.alibaba.nacos.api.ability.constant.AbilityStatus; import com.alibaba.nacos.api.remote.Requester; import java.util.Map; @@ -56,17 +55,14 @@ public abstract class Connection implements Requester { this.traced = traced; } - public AbilityStatus getConnectionAbility(AbilityKey abilityKey) { - if (abilityTable == null) { - return AbilityStatus.UNKNOWN; - } - return abilityTable.getOrDefault(abilityKey, false) ? AbilityStatus.SUPPORTED : AbilityStatus.NOT_SUPPORTED; - } - public void setAbilityTable(Map abilityTable) { this.abilityTable = abilityTable; } + public Map getAbilityTable() { + return this.abilityTable; + } + /** * get abilities. * diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java index bbee28629..eb69ab86f 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java @@ -168,6 +168,7 @@ public class GrpcRequestAcceptor extends RequestGrpc.RequestImplBase { requestMeta.setConnectionId(CONTEXT_KEY_CONN_ID.get()); requestMeta.setClientVersion(connection.getMetaInfo().getVersion()); requestMeta.setLabels(connection.getMetaInfo().getLabels()); + requestMeta.setAbilityTable(connection.getAbilityTable()); connectionManager.refreshActiveTime(requestMeta.getConnectionId()); Response response = requestHandler.handleRequest(request, requestMeta); Payload payloadResponse = GrpcUtils.convert(response); From 5cbfc524a99edde94a90f6481d7662e57140017f Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Mon, 19 Sep 2022 21:44:22 +0800 Subject: [PATCH 38/55] Client combine ability then return to server. --- .../common/remote/client/grpc/GrpcClient.java | 33 +++++++++++++++++-- .../grpc/GrpcBiStreamRequestAcceptor.java | 3 -- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java index 5221f3922..5026d858d 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java @@ -30,6 +30,7 @@ import com.alibaba.nacos.api.remote.response.ErrorResponse; import com.alibaba.nacos.api.remote.response.Response; import com.alibaba.nacos.api.remote.response.ServerCheckResponse; import com.alibaba.nacos.api.remote.response.SetupAckResponse; +import com.alibaba.nacos.common.ability.AbstractAbilityControlManager; import com.alibaba.nacos.common.ability.discover.NacosAbilityManagerHolder; import com.alibaba.nacos.common.remote.ConnectionType; import com.alibaba.nacos.common.remote.client.Connection; @@ -48,6 +49,8 @@ import io.grpc.stub.StreamObserver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.HashMap; +import java.util.Iterator; import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; @@ -353,7 +356,7 @@ public abstract class GrpcClient extends RpcClient { grpcConn.setConnectionId(connectionId); // if not supported, it will be null if (serverCheckResponse.getAbilities() != null) { - Map abilityTable = AbilityKey.mapEnum(serverCheckResponse.getAbilities()); + Map abilityTable = mapAndFilter(serverCheckResponse.getAbilities()); // mark markForSetup.put(serverCheckResponse.getConnectionId(), new CountDownLatch(1)); // combine with current node abilities @@ -375,7 +378,7 @@ public abstract class GrpcClient extends RpcClient { conSetupRequest.setClientVersion(VersionUtils.getFullClientVersion()); conSetupRequest.setLabels(super.getLabels()); // set ability table - conSetupRequest.setAbilityTable(AbilityKey.mapStr(NacosAbilityManagerHolder.getInstance().getCurrentNodeAbilities())); + conSetupRequest.setAbilityTable(serverCheckResponse.getAbilities()); conSetupRequest.setTenant(super.getTenant()); grpcConn.sendRequest(conSetupRequest); // wait for response @@ -401,6 +404,32 @@ public abstract class GrpcClient extends RpcClient { return null; } + /**. + * filter the ability current node not support, map to enum + * + * @param originClientAbilities origin client abilities + * @return enum map + */ + private Map mapAndFilter(Map originClientAbilities) { + Map res = new HashMap<>(originClientAbilities.size()); + Iterator> iterator = originClientAbilities.entrySet().iterator(); + + // filter ability current node not support + AbstractAbilityControlManager instance = NacosAbilityManagerHolder.getInstance(); + while (iterator.hasNext()) { + Map.Entry next = iterator.next(); + AbilityKey anEnum = AbilityKey.getEnum(next.getKey()); + if (anEnum != null) { + // whether support + boolean isRunning = instance.isCurrentNodeAbilityRunning(anEnum) && next.getValue(); + res.put(anEnum, isRunning); + // if not support + originClientAbilities.replace(next.getKey(), isRunning); + } + } + return res; + } + @Override protected void afterReset(ConnectResetRequest request) { String connectionId = request.getConnectionId(); diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java index 32cef2075..dcb01113d 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java @@ -128,9 +128,6 @@ public class GrpcBiStreamRequestAcceptor extends BiRequestStreamGrpc.BiRequestSt // map to table Map clientAbilities = AbilityKey .mapEnum(setUpRequest.getAbilityTable()); - // combine with current node abilities - // in order to get abilities current node provides - NacosAbilityManagerHolder.getInstance().combine(clientAbilities); connection.setAbilityTable(clientAbilities); } boolean rejectSdkOnStarting = metaInfo.isSdkSource() && !ApplicationUtils.isStarted(); From 5ec1d1f8b59727f350e0fa069220a190cd07d43e Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Tue, 20 Sep 2022 15:24:46 +0800 Subject: [PATCH 39/55] Change the format of ability table key to string, less time for format conversion when saving. --- .../api/ability/constant/AbilityKey.java | 2 +- .../nacos/api/remote/request/RequestMeta.java | 8 +-- .../ability/ClientAbilityControlManager.java | 4 +- .../nacos/client/ability/AbilityTest.java | 4 +- .../AbstractAbilityControlManager.java | 54 ++++++++----------- .../common/remote/client/Connection.java | 8 +-- .../common/remote/client/grpc/GrpcClient.java | 34 +----------- .../control/ServerAbilityControlManager.java | 12 ++--- .../alibaba/nacos/core/remote/Connection.java | 7 ++- .../grpc/GrpcBiStreamRequestAcceptor.java | 4 +- .../core/remote/grpc/GrpcRequestAcceptor.java | 5 +- .../ability/AbilityControlManagerTest.java | 14 ++--- .../TestServerAbilityControlManager.java | 2 +- .../ability/config/AbilityConfigsTest.java | 6 +-- 14 files changed, 61 insertions(+), 103 deletions(-) diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java index d2e71e126..d78de35d3 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java @@ -25,7 +25,7 @@ import java.util.stream.Collectors; /**. * @author Daydreamer - * @description Ability key constant. + * @description Ability key constant. It is used to constrain the ability key. * @date 2022/8/31 12:27 **/ public enum AbilityKey { diff --git a/api/src/main/java/com/alibaba/nacos/api/remote/request/RequestMeta.java b/api/src/main/java/com/alibaba/nacos/api/remote/request/RequestMeta.java index c212ebe33..c633f8934 100644 --- a/api/src/main/java/com/alibaba/nacos/api/remote/request/RequestMeta.java +++ b/api/src/main/java/com/alibaba/nacos/api/remote/request/RequestMeta.java @@ -38,13 +38,13 @@ public class RequestMeta { private Map labels = new HashMap<>(); - private Map abilityTable; + private Map abilityTable; public AbilityStatus getConnectionAbility(AbilityKey abilityKey) { - if (abilityTable == null) { + if (abilityTable == null || !abilityTable.containsKey(abilityKey.getName())) { return AbilityStatus.UNKNOWN; } - return abilityTable.getOrDefault(abilityKey, false) ? AbilityStatus.SUPPORTED : AbilityStatus.NOT_SUPPORTED; + return abilityTable.get(abilityKey.getName()) ? AbilityStatus.SUPPORTED : AbilityStatus.NOT_SUPPORTED; } /** @@ -52,7 +52,7 @@ public class RequestMeta { * * @param abilityTable property value of clientVersion */ - public void setAbilityTable(Map abilityTable) { + public void setAbilityTable(Map abilityTable) { this.abilityTable = abilityTable; } diff --git a/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java b/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java index f1cb6cf7d..af537a60b 100644 --- a/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java +++ b/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java @@ -33,8 +33,8 @@ public class ClientAbilityControlManager extends AbstractAbilityControlManager { } @Override - protected Map initCurrentNodeAbilities() { - return ClientAbilities.getStaticAbilities(); + protected Map initCurrentNodeAbilities() { + return AbilityKey.mapStr(ClientAbilities.getStaticAbilities()); } @Override diff --git a/client/src/test/java/com/alibaba/nacos/client/ability/AbilityTest.java b/client/src/test/java/com/alibaba/nacos/client/ability/AbilityTest.java index f5f966f6e..a11850a27 100644 --- a/client/src/test/java/com/alibaba/nacos/client/ability/AbilityTest.java +++ b/client/src/test/java/com/alibaba/nacos/client/ability/AbilityTest.java @@ -61,8 +61,8 @@ public class AbilityTest { { super.abilityTable = new HashMap<>(); - super.abilityTable.put(AbilityKey.TEST_1, true); - super.abilityTable.put(AbilityKey.TEST_2, false); + super.abilityTable.put(AbilityKey.TEST_1.getName(), true); + super.abilityTable.put(AbilityKey.TEST_2.getName(), false); } @Override diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java index ca8c028d2..a501145cb 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java @@ -65,7 +65,7 @@ public abstract class AbstractAbilityControlManager { /**. * ability current node running */ - protected final Map currentRunningAbility = new ConcurrentHashMap<>(); + protected final Map currentRunningAbility = new ConcurrentHashMap<>(); private final ReentrantLock lockForHandlerMappings = new ReentrantLock(); @@ -75,18 +75,18 @@ public abstract class AbstractAbilityControlManager { currentRunningAbility.putAll(initCurrentNodeAbilities()); } - /** - * . Turn on the ability whose key is

abilityKey

+ /**. + * Turn on the ability whose key is

abilityKey

* - * @param abilityKey ability key + * @param abilityKey ability key{@link AbilityKey} * @return if turn success */ public boolean enableCurrentNodeAbility(AbilityKey abilityKey) { return doTurn(true, abilityKey); } - /** - * . Turn off the ability whose key is

abilityKey

+ /**. + * Turn off the ability whose key is

abilityKey

{@link AbilityKey} * * @param abilityKey ability key * @return if turn success @@ -95,8 +95,14 @@ public abstract class AbstractAbilityControlManager { return doTurn(false, abilityKey); } + /**. + * Whether current node support + * + * @param abilityKey ability key from {@link AbilityKey} + * @return whether support + */ public boolean isCurrentNodeAbilityRunning(AbilityKey abilityKey) { - return currentRunningAbility.getOrDefault(abilityKey, false); + return currentRunningAbility.getOrDefault(abilityKey.getName(), false); } /**. @@ -104,14 +110,14 @@ public abstract class AbstractAbilityControlManager { * * @return current node abilities */ - protected abstract Map initCurrentNodeAbilities(); + protected abstract Map initCurrentNodeAbilities(); /**. * Return the abilities current node * * @return current abilities */ - public Map getCurrentNodeAbilities() { + public Map getCurrentNodeAbilities() { return Collections.unmodifiableMap(currentRunningAbility); } @@ -123,7 +129,7 @@ public abstract class AbstractAbilityControlManager { * @return if turn success */ private boolean doTurn(boolean isOn, AbilityKey abilityKey) { - Boolean isEnabled = currentRunningAbility.get(abilityKey); + Boolean isEnabled = currentRunningAbility.get(abilityKey.getName()); // if not supporting this key if (isEnabled == null) { LOGGER.warn("[AbilityControlManager] Attempt to turn on/off a not existed ability!"); @@ -133,7 +139,7 @@ public abstract class AbstractAbilityControlManager { return true; } // turn on/off - currentRunningAbility.put(abilityKey, isOn); + currentRunningAbility.put(abilityKey.getName(), isOn); // handler mappings triggerHandlerMappingAsyn(abilityKey, isOn, this.handlerMappings); // notify event @@ -192,20 +198,6 @@ public abstract class AbstractAbilityControlManager { LOGGER.warn("[DefaultAbilityControlManager] - Destruction of the end"); } - /**. - * Combine with current node abilities, in order to get abilities current node provides - * - * @param abilities combined ability table - */ - public void combine(Map abilities) { - currentRunningAbility.forEach((k, v) -> { - Boolean isCurrentSupport = currentRunningAbility.get(k); - if (isCurrentSupport != null) { - abilities.put(k, abilities.getOrDefault(k, false) && isCurrentSupport); - } - }); - } - /**. * hook for subclass */ @@ -260,8 +252,8 @@ public abstract class AbstractAbilityControlManager { */ protected void doRegisterComponent(AbilityKey abilityKey, HandlerMapping handlerMapping, Map> handlerMappings, Lock lockForHandlerMappings, - int priority, Map abilityTable) { - if (!currentRunningAbility.containsKey(abilityKey)) { + int priority, Map abilityTable) { + if (!currentRunningAbility.containsKey(abilityKey.getName())) { LOGGER.warn("[AbilityHandlePostProcessor] Failed to register processor: {}, because illegal key!", handlerMapping.getClass().getSimpleName()); } @@ -275,7 +267,7 @@ public abstract class AbstractAbilityControlManager { handlerMappings.put(abilityKey, handlers); // choose behavior // enable default - if (abilityTable.getOrDefault(abilityKey, false)) { + if (abilityTable.getOrDefault(abilityKey.getName(), false)) { handlerMapping.enable(); } else { handlerMapping.disable(); @@ -384,15 +376,15 @@ public abstract class AbstractAbilityControlManager { private boolean isOn; - private Map table; + private Map table; private AbilityUpdateEvent(){} - public Map getAbilityTable() { + public Map getAbilityTable() { return table; } - public void setTable(Map abilityTable) { + public void setTable(Map abilityTable) { this.table = abilityTable; } diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/Connection.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/Connection.java index a7e37199c..b8ea5a836 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/Connection.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/Connection.java @@ -37,7 +37,7 @@ public abstract class Connection implements Requester { protected RpcClient.ServerInfo serverInfo; - protected Map abilityTable; + protected Map abilityTable; public Connection(RpcClient.ServerInfo serverInfo) { this.serverInfo = serverInfo; @@ -52,13 +52,13 @@ public abstract class Connection implements Requester { } public AbilityStatus getConnectionAbility(AbilityKey abilityKey) { - if (abilityTable == null) { + if (abilityTable == null || !abilityTable.containsKey(abilityKey.getName())) { return AbilityStatus.UNKNOWN; } - return abilityTable.getOrDefault(abilityKey, false) ? AbilityStatus.SUPPORTED : AbilityStatus.NOT_SUPPORTED; + return abilityTable.get(abilityKey.getName()) ? AbilityStatus.SUPPORTED : AbilityStatus.NOT_SUPPORTED; } - public void setAbilityTable(Map abilityTable) { + public void setAbilityTable(Map abilityTable) { this.abilityTable = abilityTable; } diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java index 5026d858d..4c8f94e3e 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java @@ -356,14 +356,10 @@ public abstract class GrpcClient extends RpcClient { grpcConn.setConnectionId(connectionId); // if not supported, it will be null if (serverCheckResponse.getAbilities() != null) { - Map abilityTable = mapAndFilter(serverCheckResponse.getAbilities()); // mark markForSetup.put(serverCheckResponse.getConnectionId(), new CountDownLatch(1)); - // combine with current node abilities - // in order to get abilities current node provides - NacosAbilityManagerHolder.getInstance().combine(abilityTable); // set server abilities to connection - grpcConn.setAbilityTable(abilityTable); + grpcConn.setAbilityTable(serverCheckResponse.getAbilities()); } //create stream request and bind connection event to this connection. @@ -378,7 +374,7 @@ public abstract class GrpcClient extends RpcClient { conSetupRequest.setClientVersion(VersionUtils.getFullClientVersion()); conSetupRequest.setLabels(super.getLabels()); // set ability table - conSetupRequest.setAbilityTable(serverCheckResponse.getAbilities()); + conSetupRequest.setAbilityTable(NacosAbilityManagerHolder.getInstance().getCurrentNodeAbilities()); conSetupRequest.setTenant(super.getTenant()); grpcConn.sendRequest(conSetupRequest); // wait for response @@ -404,32 +400,6 @@ public abstract class GrpcClient extends RpcClient { return null; } - /**. - * filter the ability current node not support, map to enum - * - * @param originClientAbilities origin client abilities - * @return enum map - */ - private Map mapAndFilter(Map originClientAbilities) { - Map res = new HashMap<>(originClientAbilities.size()); - Iterator> iterator = originClientAbilities.entrySet().iterator(); - - // filter ability current node not support - AbstractAbilityControlManager instance = NacosAbilityManagerHolder.getInstance(); - while (iterator.hasNext()) { - Map.Entry next = iterator.next(); - AbilityKey anEnum = AbilityKey.getEnum(next.getKey()); - if (anEnum != null) { - // whether support - boolean isRunning = instance.isCurrentNodeAbilityRunning(anEnum) && next.getValue(); - res.put(anEnum, isRunning); - // if not support - originClientAbilities.replace(next.getKey(), isRunning); - } - } - return res; - } - @Override protected void afterReset(ConnectResetRequest request) { String connectionId = request.getConnectionId(); diff --git a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java index 67845d821..b42eaf9c8 100644 --- a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java +++ b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java @@ -38,16 +38,16 @@ public class ServerAbilityControlManager extends AbstractAbilityControlManager { } @Override - protected Map initCurrentNodeAbilities() { + protected Map initCurrentNodeAbilities() { // static abilities - Map staticAbilities = ServerAbilities.getStaticAbilities(); + Map staticAbilities = AbilityKey.mapStr(ServerAbilities.getStaticAbilities()); // all function server can support - Set abilityKeys = staticAbilities.keySet(); - Map abilityTable = new HashMap<>(abilityKeys.size()); + Set abilityKeys = staticAbilities.keySet(); + Map abilityTable = new HashMap<>(abilityKeys.size()); // if not define in config, then load from ServerAbilities - Set unIncludedInConfig = new HashSet<>(); + Set unIncludedInConfig = new HashSet<>(); abilityKeys.forEach(abilityKey -> { - String key = AbilityConfigs.PREFIX + abilityKey.getName(); + String key = AbilityConfigs.PREFIX + abilityKey; try { Boolean property = EnvUtil.getProperty(key, Boolean.class); // if not null diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java b/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java index 6f49a3ca7..ad1e4254e 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java @@ -17,7 +17,6 @@ package com.alibaba.nacos.core.remote; import com.alibaba.nacos.api.ability.ClientAbilities; -import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.remote.Requester; import java.util.Map; @@ -33,7 +32,7 @@ public abstract class Connection implements Requester { private boolean traced = false; - private Map abilityTable; + private Map abilityTable; private ClientAbilities abilities; @@ -55,11 +54,11 @@ public abstract class Connection implements Requester { this.traced = traced; } - public void setAbilityTable(Map abilityTable) { + public void setAbilityTable(Map abilityTable) { this.abilityTable = abilityTable; } - public Map getAbilityTable() { + public Map getAbilityTable() { return this.abilityTable; } diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java index dcb01113d..12440975d 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java @@ -126,9 +126,7 @@ public class GrpcBiStreamRequestAcceptor extends BiRequestStreamGrpc.BiRequestSt // null if supported if (setUpRequest.getAbilityTable() != null) { // map to table - Map clientAbilities = AbilityKey - .mapEnum(setUpRequest.getAbilityTable()); - connection.setAbilityTable(clientAbilities); + connection.setAbilityTable(setUpRequest.getAbilityTable()); } boolean rejectSdkOnStarting = metaInfo.isSdkSource() && !ApplicationUtils.isStarted(); diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java index eb69ab86f..8fd7e1b58 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java @@ -16,7 +16,6 @@ package com.alibaba.nacos.core.remote.grpc; -import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.grpc.auto.Payload; import com.alibaba.nacos.api.grpc.auto.RequestGrpc; @@ -91,8 +90,8 @@ public class GrpcRequestAcceptor extends RequestGrpc.RequestImplBase { // server check. if (ServerCheckRequest.class.getSimpleName().equals(type)) { Payload serverCheckResponseP = GrpcUtils.convert(new ServerCheckResponse(CONTEXT_KEY_CONN_ID.get(), - // to str map - AbilityKey.mapStr(NacosAbilityManagerHolder.getInstance().getCurrentNodeAbilities()))); + // abilities current node supporting + NacosAbilityManagerHolder.getInstance().getCurrentNodeAbilities())); traceIfNecessary(serverCheckResponseP, false); responseObserver.onNext(serverCheckResponseP); responseObserver.onCompleted(); diff --git a/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java b/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java index 26483920b..44180a7aa 100644 --- a/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java +++ b/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java @@ -39,8 +39,8 @@ public class AbilityControlManagerTest { @Before public void inject() { - Map newTable = new HashMap<>(); - newTable.put(AbilityKey.TEST_1, true); + Map newTable = new HashMap<>(); + newTable.put(AbilityKey.TEST_1.getName(), true); serverAbilityControlManager.setCurrentSupportingAbility(newTable); } @@ -88,18 +88,18 @@ public class AbilityControlManagerTest { @Test public void testCurrentNodeAbility() { - Set keySet = serverAbilityControlManager.getCurrentNodeAbilities().keySet(); + Set keySet = serverAbilityControlManager.getCurrentNodeAbilities().keySet(); // diable all - keySet.forEach(key -> serverAbilityControlManager.disableCurrentNodeAbility(key)); + keySet.forEach(key -> serverAbilityControlManager.disableCurrentNodeAbility(AbilityKey.getEnum(key))); // get all keySet.forEach(key -> { - Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning(key)); + Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.getEnum(key))); }); // enable all - keySet.forEach(key -> serverAbilityControlManager.enableCurrentNodeAbility(key)); + keySet.forEach(key -> serverAbilityControlManager.enableCurrentNodeAbility(AbilityKey.getEnum(key))); // get all keySet.forEach(key -> { - Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(key)); + Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.getEnum(key))); }); } diff --git a/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java b/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java index e9bb30ff8..a3685bd79 100644 --- a/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java +++ b/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java @@ -26,7 +26,7 @@ import java.util.Map; public class TestServerAbilityControlManager extends ServerAbilityControlManager { @JustForTest - public void setCurrentSupportingAbility(Map ability) { + public void setCurrentSupportingAbility(Map ability) { currentRunningAbility.clear(); currentRunningAbility.putAll(ability); } diff --git a/core/src/test/java/com/alibaba/nacos/core/ability/config/AbilityConfigsTest.java b/core/src/test/java/com/alibaba/nacos/core/ability/config/AbilityConfigsTest.java index 3a5ba7d6c..86e081f44 100644 --- a/core/src/test/java/com/alibaba/nacos/core/ability/config/AbilityConfigsTest.java +++ b/core/src/test/java/com/alibaba/nacos/core/ability/config/AbilityConfigsTest.java @@ -60,9 +60,9 @@ public class AbilityConfigsTest { void inject(AbilityConfigs abilityConfigs) { TestServerAbilityControlManager serverAbilityControlManager = new TestServerAbilityControlManager(); - Map newTable = new HashMap<>(); - newTable.put(AbilityKey.TEST_1, true); - newTable.put(AbilityKey.TEST_2, true); + Map newTable = new HashMap<>(); + newTable.put(AbilityKey.TEST_1.getName(), true); + newTable.put(AbilityKey.TEST_2.getName(), true); serverAbilityControlManager.setCurrentSupportingAbility(newTable); abilityConfigs.setAbilityHandlerRegistry(serverAbilityControlManager); this.serverAbilityControlManager = serverAbilityControlManager; From 677c50e2f69197fdbaf8672876a5398b2cb9d7cb Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Tue, 20 Sep 2022 16:22:15 +0800 Subject: [PATCH 40/55] Notify server ability by ServerRequest. --- .../api/remote/request/SetupAckRequest.java | 15 ++- .../remote/response/ServerCheckResponse.java | 16 ++-- .../common/remote/client/grpc/GrpcClient.java | 92 ++++++++++++++----- .../grpc/GrpcBiStreamRequestAcceptor.java | 2 +- .../core/remote/grpc/GrpcRequestAcceptor.java | 4 +- 5 files changed, 90 insertions(+), 39 deletions(-) diff --git a/api/src/main/java/com/alibaba/nacos/api/remote/request/SetupAckRequest.java b/api/src/main/java/com/alibaba/nacos/api/remote/request/SetupAckRequest.java index 66f6eb238..8c37bf842 100644 --- a/api/src/main/java/com/alibaba/nacos/api/remote/request/SetupAckRequest.java +++ b/api/src/main/java/com/alibaba/nacos/api/remote/request/SetupAckRequest.java @@ -16,6 +16,8 @@ package com.alibaba.nacos.api.remote.request; +import java.util.Map; + import static com.alibaba.nacos.api.common.Constants.Remote.INTERNAL_MODULE; /**. @@ -27,11 +29,22 @@ public class SetupAckRequest extends ServerRequest { private String connectionId; + private Map abilityTable; + public SetupAckRequest() { } - public SetupAckRequest(String connectionId) { + public SetupAckRequest(String connectionId, Map abilityTable) { this.connectionId = connectionId; + this.abilityTable = abilityTable; + } + + public Map getAbilityTable() { + return abilityTable; + } + + public void setAbilityTable(Map abilityTable) { + this.abilityTable = abilityTable; } public String getConnectionId() { diff --git a/api/src/main/java/com/alibaba/nacos/api/remote/response/ServerCheckResponse.java b/api/src/main/java/com/alibaba/nacos/api/remote/response/ServerCheckResponse.java index d3c2ee449..2b8e9fea8 100644 --- a/api/src/main/java/com/alibaba/nacos/api/remote/response/ServerCheckResponse.java +++ b/api/src/main/java/com/alibaba/nacos/api/remote/response/ServerCheckResponse.java @@ -16,8 +16,6 @@ package com.alibaba.nacos.api.remote.response; -import java.util.Map; - /** * response of server check. * @@ -28,15 +26,15 @@ public class ServerCheckResponse extends Response { private String connectionId; - private Map abilities; + private boolean supportAbilityNegotiation; public ServerCheckResponse() { } - public ServerCheckResponse(String connectionId, Map abilities) { + public ServerCheckResponse(String connectionId, boolean supportAbilityNegotiation) { this.connectionId = connectionId; - this.abilities = abilities; + this.supportAbilityNegotiation = supportAbilityNegotiation; } public String getConnectionId() { @@ -47,11 +45,11 @@ public class ServerCheckResponse extends Response { this.connectionId = connectionId; } - public Map getAbilities() { - return abilities; + public boolean isSupportAbilityNegotiation() { + return supportAbilityNegotiation; } - public void setAbilities(Map abilities) { - this.abilities = abilities; + public void setSupportAbilityNegotiation(boolean supportAbilityNegotiation) { + this.supportAbilityNegotiation = supportAbilityNegotiation; } } diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java index 4c8f94e3e..60da9be2e 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java @@ -16,7 +16,6 @@ package com.alibaba.nacos.common.remote.client.grpc; -import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.grpc.auto.BiRequestStreamGrpc; import com.alibaba.nacos.api.grpc.auto.Payload; @@ -30,7 +29,6 @@ import com.alibaba.nacos.api.remote.response.ErrorResponse; import com.alibaba.nacos.api.remote.response.Response; import com.alibaba.nacos.api.remote.response.ServerCheckResponse; import com.alibaba.nacos.api.remote.response.SetupAckResponse; -import com.alibaba.nacos.common.ability.AbstractAbilityControlManager; import com.alibaba.nacos.common.ability.discover.NacosAbilityManagerHolder; import com.alibaba.nacos.common.remote.ConnectionType; import com.alibaba.nacos.common.remote.client.Connection; @@ -49,8 +47,6 @@ import io.grpc.stub.StreamObserver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.HashMap; -import java.util.Iterator; import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; @@ -85,7 +81,7 @@ public abstract class GrpcClient extends RpcClient { /**. * Block to wait setup success response */ - private final Map markForSetup = new ConcurrentHashMap<>(); + private final Map markForSetup = new ConcurrentHashMap<>(); @Override public ConnectionType getConnectionType() { @@ -104,9 +100,15 @@ public abstract class GrpcClient extends RpcClient { if (request instanceof SetupAckRequest) { SetupAckRequest setupAckRequest = (SetupAckRequest) request; // remove and count down - Optional.ofNullable(markForSetup.remove((setupAckRequest.getConnectionId()))) + RecAbilityContext context = markForSetup.remove(setupAckRequest.getConnectionId()); + if (context != null) { + // set server abilities + context.connection.setAbilityTable(setupAckRequest.getAbilityTable()); + // notify + Optional.ofNullable(context.blocker) .orElse(new CountDownLatch(1)) - .countDown(); + .countDown(); + } } return new SetupAckResponse(); }); @@ -273,9 +275,12 @@ public abstract class GrpcClient extends RpcClient { LoggerUtils.printIfErrorEnabled(LOGGER, "[{}]Error to process server push response: {}", grpcConn.getConnectionId(), payload.getBody().getValue().toStringUtf8()); // remove and notify - Optional.ofNullable(markForSetup.remove(grpcConn.getConnectionId())) - .orElse(new CountDownLatch(1)) - .countDown(); + RecAbilityContext context = markForSetup.remove(grpcConn.getConnectionId()); + if (context != null) { + Optional.ofNullable(context.blocker) + .orElse(new CountDownLatch(1)) + .countDown(); + } } } @@ -354,12 +359,10 @@ public abstract class GrpcClient extends RpcClient { .newStub(newChannelStubTemp.getChannel()); GrpcConnection grpcConn = new GrpcConnection(serverInfo, grpcExecutor); grpcConn.setConnectionId(connectionId); - // if not supported, it will be null - if (serverCheckResponse.getAbilities() != null) { + // if not supported, it will be false + if (serverCheckResponse.isSupportAbilityNegotiation()) { // mark - markForSetup.put(serverCheckResponse.getConnectionId(), new CountDownLatch(1)); - // set server abilities to connection - grpcConn.setAbilityTable(serverCheckResponse.getAbilities()); + markForSetup.put(serverCheckResponse.getConnectionId(), new RecAbilityContext(grpcConn, new CountDownLatch(1))); } //create stream request and bind connection event to this connection. @@ -378,11 +381,10 @@ public abstract class GrpcClient extends RpcClient { conSetupRequest.setTenant(super.getTenant()); grpcConn.sendRequest(conSetupRequest); // wait for response - CountDownLatch synResponse = markForSetup.get(connectionId); + RecAbilityContext synResponse = markForSetup.get(connectionId); if (synResponse != null) { - synResponse.await(2000L, TimeUnit.MICROSECONDS); - // ensure remove, it may being reset - markForSetup.remove(connectionId); + // try to wait for notify response + synResponse.blocker.await(5000L, TimeUnit.MICROSECONDS); } // leave for adapting old version server //wait to register connection setup @@ -393,24 +395,64 @@ public abstract class GrpcClient extends RpcClient { } catch (Exception e) { LOGGER.error("[{}]Fail to connect to server!,error={}", GrpcClient.this.getName(), e); // remove and notify - Optional.ofNullable(markForSetup.remove(connectionId)) - .orElse(new CountDownLatch(1)) - .countDown(); + RecAbilityContext context = markForSetup.remove(connectionId); + if (context != null) { + Optional.ofNullable(context.blocker) + .orElse(new CountDownLatch(1)) + .countDown(); + } } return null; } @Override protected void afterReset(ConnectResetRequest request) { - String connectionId = request.getConnectionId(); - if (connectionId != null) { + RecAbilityContext context = markForSetup.remove(request.getConnectionId()); + if (context != null) { // remove and notify - Optional.ofNullable(markForSetup.remove(connectionId)) + Optional.ofNullable(context.blocker) .orElse(new CountDownLatch(1)) .countDown(); } } + /**. + * This is for receiving server abilities + */ + class RecAbilityContext { + + /**. + * connection waiting for server abilities + */ + private Connection connection; + + /**. + * way to block client + */ + private CountDownLatch blocker; + + public RecAbilityContext(Connection connection, CountDownLatch blocker) { + this.connection = connection; + this.blocker = blocker; + } + + public Connection getConnection() { + return connection; + } + + public void setConnection(Connection connection) { + this.connection = connection; + } + + public CountDownLatch getBlocker() { + return blocker; + } + + public void setBlocker(CountDownLatch blocker) { + this.blocker = blocker; + } + } + } diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java index 12440975d..08c033dfe 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java @@ -149,7 +149,7 @@ public class GrpcBiStreamRequestAcceptor extends BiRequestStreamGrpc.BiRequestSt } else { try { // finish register, tell client has set up successfully - connection.request(new SetupAckRequest(connectionId), 3000L); + connection.request(new SetupAckRequest(connectionId, NacosAbilityManagerHolder.getInstance().getCurrentNodeAbilities()), 3000L); } catch (Exception e) { // nothing to do diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java index 8fd7e1b58..27c731ae2 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java @@ -89,9 +89,7 @@ public class GrpcRequestAcceptor extends RequestGrpc.RequestImplBase { // server check. if (ServerCheckRequest.class.getSimpleName().equals(type)) { - Payload serverCheckResponseP = GrpcUtils.convert(new ServerCheckResponse(CONTEXT_KEY_CONN_ID.get(), - // abilities current node supporting - NacosAbilityManagerHolder.getInstance().getCurrentNodeAbilities())); + Payload serverCheckResponseP = GrpcUtils.convert(new ServerCheckResponse(CONTEXT_KEY_CONN_ID.get(), true)); traceIfNecessary(serverCheckResponseP, false); responseObserver.onNext(serverCheckResponseP); responseObserver.onCompleted(); From a159e1261cce448aba2348523ef7657270fb5483 Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Tue, 20 Sep 2022 20:36:34 +0800 Subject: [PATCH 41/55] Add integration test. --- .../remote/client/ServerRequestHandler.java | 1 + .../grpc/GrpcBiStreamRequestAcceptor.java | 4 +- .../core/remote/grpc/GrpcRequestAcceptor.java | 1 - .../nacos/test/ability/AbilityDiscovery.java | 209 ++++++++++++++++++ .../TestServerAbilityControlManager.java | 18 ++ 5 files changed, 230 insertions(+), 3 deletions(-) create mode 100644 test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityDiscovery.java create mode 100644 test/core-test/src/test/java/com/alibaba/nacos/test/ability/component/TestServerAbilityControlManager.java diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/ServerRequestHandler.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/ServerRequestHandler.java index f4163249e..09ad1002e 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/ServerRequestHandler.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/ServerRequestHandler.java @@ -31,6 +31,7 @@ public interface ServerRequestHandler { * Handle request from server. * * @param request request + * @param connection current connection, it can be used to know server ability * @return response. */ Response requestReply(Request request, Connection connection); diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java index 08c033dfe..71cf8ffa8 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java @@ -16,7 +16,6 @@ package com.alibaba.nacos.core.remote.grpc; -import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.common.Constants; import com.alibaba.nacos.api.grpc.auto.BiRequestStreamGrpc; import com.alibaba.nacos.api.grpc.auto.Payload; @@ -149,7 +148,8 @@ public class GrpcBiStreamRequestAcceptor extends BiRequestStreamGrpc.BiRequestSt } else { try { // finish register, tell client has set up successfully - connection.request(new SetupAckRequest(connectionId, NacosAbilityManagerHolder.getInstance().getCurrentNodeAbilities()), 3000L); + connection.request(new SetupAckRequest(connectionId, + NacosAbilityManagerHolder.getInstance().getCurrentNodeAbilities()), 3000L); } catch (Exception e) { // nothing to do diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java index 27c731ae2..824b159a4 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.java @@ -25,7 +25,6 @@ import com.alibaba.nacos.api.remote.request.ServerCheckRequest; import com.alibaba.nacos.api.remote.response.ErrorResponse; import com.alibaba.nacos.api.remote.response.Response; import com.alibaba.nacos.api.remote.response.ServerCheckResponse; -import com.alibaba.nacos.common.ability.discover.NacosAbilityManagerHolder; import com.alibaba.nacos.common.remote.client.grpc.GrpcUtils; import com.alibaba.nacos.core.remote.Connection; import com.alibaba.nacos.core.remote.ConnectionManager; diff --git a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityDiscovery.java b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityDiscovery.java new file mode 100644 index 000000000..7dd60999e --- /dev/null +++ b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityDiscovery.java @@ -0,0 +1,209 @@ +package com.alibaba.nacos.test.ability; + +import com.alibaba.nacos.Nacos; +import com.alibaba.nacos.api.NacosFactory; +import com.alibaba.nacos.api.PropertyKeyConst; +import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.constant.AbilityStatus; +import com.alibaba.nacos.api.config.ConfigService; +import com.alibaba.nacos.api.config.remote.request.ConfigQueryRequest; +import com.alibaba.nacos.api.config.remote.response.ConfigQueryResponse; +import com.alibaba.nacos.api.exception.NacosException; +import com.alibaba.nacos.api.remote.request.Request; +import com.alibaba.nacos.api.remote.request.RequestMeta; +import com.alibaba.nacos.api.remote.request.SetupAckRequest; +import com.alibaba.nacos.api.remote.response.Response; +import com.alibaba.nacos.common.ability.AbstractAbilityControlManager; +import com.alibaba.nacos.common.ability.discover.NacosAbilityManagerHolder; +import com.alibaba.nacos.common.remote.ConnectionType; +import com.alibaba.nacos.common.remote.client.Connection; +import com.alibaba.nacos.common.remote.client.RpcClient; +import com.alibaba.nacos.common.remote.client.RpcClientFactory; +import com.alibaba.nacos.common.remote.client.ServerListFactory; +import com.alibaba.nacos.common.remote.client.ServerRequestHandler; +import com.alibaba.nacos.core.remote.ConnectionManager; +import com.alibaba.nacos.core.remote.RequestFilters; +import com.alibaba.nacos.core.remote.RequestHandler; +import com.alibaba.nacos.core.remote.RequestHandlerRegistry; +import com.alibaba.nacos.test.ability.component.TestServerAbilityControlManager; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.annotation.Resource; +import java.lang.reflect.Field; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.UUID; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Nacos.class, properties = { + "server.servlet.context-path=/nacos"}, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +@SuppressWarnings("all") +public class AbilityDiscovery { + + @LocalServerPort + private int port; + + @Resource + private RequestHandlerRegistry requestHandlerRegistry; + + @Resource + private RequestFilters filters; + + @Resource + private ConnectionManager connectionManager; + + private RpcClient client; + + private ConfigService configService; + + private AbstractAbilityControlManager oldInstance; + + /** + * test server judge client abilities + */ + private volatile boolean serverSuccess = false; + + private volatile boolean clientSuccess = false; + + private Field abstractAbilityControlManager; + + private Field registryHandlerFields; + + private Field currentConnField; + + @Before + public void setup() throws NoSuchFieldException, IllegalAccessException, NacosException { + // load class + oldInstance = NacosAbilityManagerHolder.getInstance(); + + // replace + abstractAbilityControlManager = NacosAbilityManagerHolder.class + .getDeclaredField("abstractAbilityControlManager"); + abstractAbilityControlManager.setAccessible(true); + abstractAbilityControlManager.set(NacosAbilityManagerHolder.class, new TestServerAbilityControlManager()); + + // get registry field + registryHandlerFields = RequestHandlerRegistry.class.getDeclaredField("registryHandlers"); + registryHandlerFields.setAccessible(true); + + // currentConn + currentConnField = RpcClient.class.getDeclaredField("currentConnection"); + currentConnField.setAccessible(true); + + // init config service + Properties properties = new Properties(); + properties.put(PropertyKeyConst.SERVER_ADDR, "127.0.0.1:" + port); + configService = NacosFactory.createConfigService(properties); + + // init client + client = RpcClientFactory.createClient(UUID.randomUUID().toString(), ConnectionType.GRPC, new HashMap<>()); + client.serverListFactory(new ServerListFactory() { + @Override + public String genNextServer() { + return "127.0.0.1:" + port; + } + + @Override + public String getCurrentServer() { + return "127.0.0.1:" + port; + } + + @Override + public List getServerList() { + return Collections.singletonList("127.0.0.1:" + port); + } + }); + // connect to server + client.start(); + } + + @Test + public void testClientDiscovery() throws NacosException { + // client judge ability + Assert.assertEquals(client.getConnectionAbility(AbilityKey.TEST_1), AbilityStatus.SUPPORTED); + Assert.assertEquals(client.getConnectionAbility(AbilityKey.TEST_2), AbilityStatus.NOT_SUPPORTED); + } + + @Test + public void testServerDiscoveryAndJudge() throws Exception { + Map handlers = (Map) registryHandlerFields + .get(requestHandlerRegistry); + + // set handler + RequestHandler oldRequestHandler = handlers.remove(ConfigQueryRequest.class.getSimpleName()); + handlers.put(ConfigQueryRequest.class.getSimpleName(), new ClientRequestHandler(filters)); + configService.getConfig("test", "DEFAULT_GROUP", 2000); + // wait server invoke + Thread.sleep(3000); + Assert.assertTrue(serverSuccess); + // recover + handlers.remove(ConfigQueryRequest.class.getSimpleName()); + handlers.put(ConfigQueryRequest.class.getSimpleName(), oldRequestHandler); + } + + @Test + public void testClientJudge() throws Exception { + // register + client.registerServerRequestHandler(new ServerRequestHandler() { + @Override + public Response requestReply(Request request, Connection connection) { + if (connection.getConnectionAbility(AbilityKey.TEST_1).equals(AbilityStatus.SUPPORTED) && connection + .getConnectionAbility(AbilityKey.TEST_2).equals(AbilityStatus.NOT_SUPPORTED)) { + clientSuccess = true; + } + return new Response(){}; + } + }); + + // get id + Connection conn = (Connection) currentConnField.get(client); + + com.alibaba.nacos.core.remote.Connection connection = connectionManager.getConnection(conn.getConnectionId()); + try { + connection.request(new SetupAckRequest(), 2000L); + } catch (NacosException e) { + // nothing to do + } + + // wait client react + Thread.sleep(4000); + Assert.assertTrue(clientSuccess); + } + + @After + public void recover() throws IllegalAccessException, NacosException { + abstractAbilityControlManager.set(NacosAbilityManagerHolder.class, oldInstance); + client.shutdown(); + } + + /** + * just to test ability + */ + class ClientRequestHandler extends RequestHandler { + + public ClientRequestHandler(RequestFilters requestFilters) throws NoSuchFieldException, IllegalAccessException { + Field declaredField = RequestHandler.class.getDeclaredField("requestFilters"); + declaredField.setAccessible(true); + declaredField.set(this, requestFilters); + } + + @Override + public ConfigQueryResponse handle(ConfigQueryRequest request, RequestMeta meta) throws NacosException { + if (meta.getConnectionAbility(AbilityKey.TEST_1).equals(AbilityStatus.SUPPORTED) && meta + .getConnectionAbility(AbilityKey.TEST_2).equals(AbilityStatus.NOT_SUPPORTED)) { + serverSuccess = true; + } + return new ConfigQueryResponse(); + } + } +} diff --git a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/component/TestServerAbilityControlManager.java b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/component/TestServerAbilityControlManager.java new file mode 100644 index 000000000..4620977fa --- /dev/null +++ b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/component/TestServerAbilityControlManager.java @@ -0,0 +1,18 @@ +package com.alibaba.nacos.test.ability.component; + +import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.core.ability.control.ServerAbilityControlManager; + +import java.util.HashMap; +import java.util.Map; + +public class TestServerAbilityControlManager extends ServerAbilityControlManager { + + @Override + protected Map initCurrentNodeAbilities() { + Map map = new HashMap<>(); + map.put(AbilityKey.TEST_1.getName(), true); + map.put(AbilityKey.TEST_2.getName(), false); + return map; + } +} From d42ce9bc8f8747555f3fc0dd3613e04ebc69e7bd Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Wed, 28 Sep 2022 15:38:20 +0800 Subject: [PATCH 42/55] Add test for sever abilities initializing in manager. --- .../ability/config/AbilityConfigsTest.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/core/src/test/java/com/alibaba/nacos/core/ability/config/AbilityConfigsTest.java b/core/src/test/java/com/alibaba/nacos/core/ability/config/AbilityConfigsTest.java index 86e081f44..8ae52fd6d 100644 --- a/core/src/test/java/com/alibaba/nacos/core/ability/config/AbilityConfigsTest.java +++ b/core/src/test/java/com/alibaba/nacos/core/ability/config/AbilityConfigsTest.java @@ -17,6 +17,8 @@ package com.alibaba.nacos.core.ability.config; import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.register.AbstractAbilityRegistry; +import com.alibaba.nacos.api.ability.register.impl.ServerAbilities; import com.alibaba.nacos.common.ability.handler.HandlerMapping; import com.alibaba.nacos.common.event.ServerConfigChangeEvent; import com.alibaba.nacos.core.ability.TestServerAbilityControlManager; @@ -27,6 +29,7 @@ import org.junit.Before; import org.junit.Test; import org.springframework.mock.env.MockEnvironment; +import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; @@ -45,6 +48,8 @@ public class AbilityConfigsTest { private ServerAbilityControlManager serverAbilityControlManager; + private Map currentAbilities; + @Before public void setUp() throws Exception { environment = new MockEnvironment(); @@ -68,6 +73,32 @@ public class AbilityConfigsTest { this.serverAbilityControlManager = serverAbilityControlManager; } + + public void fill() throws NoSuchFieldException, IllegalAccessException { + Field instanceField = ServerAbilities.class.getDeclaredField("INSTANCE"); + Field abilitiesField = AbstractAbilityRegistry.class.getDeclaredField("supportedAbilities"); + abilitiesField.setAccessible(true); + instanceField.setAccessible(true); + ServerAbilities serverAbilities = (ServerAbilities) instanceField.get(ServerAbilities.class); + currentAbilities = (Map) abilitiesField.get(serverAbilities); + currentAbilities.put(AbilityKey.TEST_1, true); + currentAbilities.put(AbilityKey.TEST_2, true); + } + + @Test + public void testLoadAbilities() throws NoSuchFieldException, IllegalAccessException, InterruptedException { + environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.TEST_1.getName(), Boolean.TRUE.toString()); + environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.TEST_2.getName(), Boolean.FALSE.toString()); + // test load + fill(); + ServerAbilityControlManager manager = new ServerAbilityControlManager(); + // config has higher priority + Assert.assertTrue(manager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); + Assert.assertFalse(manager.isCurrentNodeAbilityRunning(AbilityKey.TEST_2)); + // clear + currentAbilities.clear(); + } + @Test public void testInit() { Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); From bb92da0661156d6012009a3522c63623c4991051 Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Tue, 25 Oct 2022 14:18:17 +0800 Subject: [PATCH 43/55] Remove unused wait in GrpcClient and field in ClientAbilities, change ^ to != in MemeberUtil. --- .../common/remote/client/grpc/GrpcClient.java | 6 +++-- .../nacos/core/cluster/MemberUtil.java | 2 +- .../alibaba/nacos/core/remote/Connection.java | 24 ------------------- 3 files changed, 5 insertions(+), 27 deletions(-) diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java index 60da9be2e..3f1f7ee2c 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java @@ -387,8 +387,10 @@ public abstract class GrpcClient extends RpcClient { synResponse.blocker.await(5000L, TimeUnit.MICROSECONDS); } // leave for adapting old version server - //wait to register connection setup - Thread.sleep(100L); + else { + //wait to register connection setup + Thread.sleep(100L); + } return grpcConn; } return null; diff --git a/core/src/main/java/com/alibaba/nacos/core/cluster/MemberUtil.java b/core/src/main/java/com/alibaba/nacos/core/cluster/MemberUtil.java index 6a664a30d..d0f6dac5a 100644 --- a/core/src/main/java/com/alibaba/nacos/core/cluster/MemberUtil.java +++ b/core/src/main/java/com/alibaba/nacos/core/cluster/MemberUtil.java @@ -285,7 +285,7 @@ public class MemberUtil { } // if change - if (expected.isSupportRemoteConnection() ^ actual.isSupportRemoteConnection()) { + if (expected.isSupportRemoteConnection() != actual.isSupportRemoteConnection()) { return true; } diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java b/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java index ad1e4254e..b010e2a84 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java @@ -34,8 +34,6 @@ public abstract class Connection implements Requester { private Map abilityTable; - private ClientAbilities abilities; - private final ConnectionMeta metaInfo; public Connection(ConnectionMeta metaInfo) { @@ -62,28 +60,6 @@ public abstract class Connection implements Requester { return this.abilityTable; } - /** - * get abilities. - * - * @deprecated it is replaced by abilityTable field - * @return - */ - @Deprecated - public ClientAbilities getAbilities() { - return abilities; - } - - /** - * set abilities. - * - * @deprecated it is replaced by abilityTable field - * @param abilities abilities. - */ - @Deprecated - public void setAbilities(ClientAbilities abilities) { - this.abilities = abilities; - } - /** * check is connected. * From d4e9b836d2cf16014cc1907d027b335e26ad0f90 Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Thu, 22 Jun 2023 17:08:04 +0800 Subject: [PATCH 44/55] fix checkstyle and fix bug --- .../request/ConnectionSetupRequestTest.java | 6 +-- .../response/ServerCheckResponseTest.java | 2 +- .../client/config/impl/ClientWorker.java | 1 - .../config/impl/ConfigTransportClient.java | 2 +- .../client/config/impl/ServerListManager.java | 2 +- .../nacos/client/ability/AbilityTest.java | 41 ++++++++++++++++++- .../common/remote/client/grpc/GrpcClient.java | 9 ++-- .../src/main/resources/application.properties | 18 ++++---- .../alibaba/nacos/core/cluster/Member.java | 10 ++--- .../nacos/core/cluster/MemberUtil.java | 8 ++-- .../core/cluster/ServerMemberManager.java | 17 ++++++-- .../alibaba/nacos/core/remote/Connection.java | 1 - .../ability/config/AbilityConfigsTest.java | 17 +++++--- .../nacos/core/cluster/MemberUtilTest.java | 2 +- 14 files changed, 93 insertions(+), 43 deletions(-) diff --git a/api/src/test/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequestTest.java b/api/src/test/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequestTest.java index e05860af9..03424d50a 100644 --- a/api/src/test/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequestTest.java +++ b/api/src/test/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequestTest.java @@ -16,11 +16,11 @@ package com.alibaba.nacos.api.remote.request; -import com.alibaba.nacos.api.ability.ClientAbilities; import org.junit.Assert; import org.junit.Test; import java.util.Collections; +import java.util.HashMap; public class ConnectionSetupRequestTest extends BasicRequestTest { @@ -28,7 +28,7 @@ public class ConnectionSetupRequestTest extends BasicRequestTest { public void testSerialize() throws Exception { ConnectionSetupRequest request = new ConnectionSetupRequest(); request.setClientVersion("2.2.2"); - request.setAbilities(new ClientAbilities()); + request.setAbilityTable(new HashMap<>()); request.setTenant("testNamespaceId"); request.setLabels(Collections.singletonMap("labelKey", "labelValue")); request.setRequestId("1"); @@ -37,7 +37,7 @@ public class ConnectionSetupRequestTest extends BasicRequestTest { Assert.assertTrue(json.contains("\"clientVersion\":\"2.2.2\"")); Assert.assertTrue(json.contains("\"tenant\":\"testNamespaceId\"")); Assert.assertTrue(json.contains("\"labels\":{\"labelKey\":\"labelValue\"}")); - Assert.assertTrue(json.contains("\"abilities\":{")); + Assert.assertTrue(json.contains("\"abilityTable\":{")); Assert.assertTrue(json.contains("\"module\":\"internal\"")); Assert.assertTrue(json.contains("\"requestId\":\"1\"")); } diff --git a/api/src/test/java/com/alibaba/nacos/api/remote/response/ServerCheckResponseTest.java b/api/src/test/java/com/alibaba/nacos/api/remote/response/ServerCheckResponseTest.java index 80c2ac9ea..c010f0d99 100644 --- a/api/src/test/java/com/alibaba/nacos/api/remote/response/ServerCheckResponseTest.java +++ b/api/src/test/java/com/alibaba/nacos/api/remote/response/ServerCheckResponseTest.java @@ -38,7 +38,7 @@ public class ServerCheckResponseTest { @Test public void testSerialization() throws JsonProcessingException { - ServerCheckResponse response = new ServerCheckResponse("35643245_1.1.1.1_3306"); + ServerCheckResponse response = new ServerCheckResponse("35643245_1.1.1.1_3306", false); String actual = mapper.writeValueAsString(response); assertTrue(actual.contains("\"connectionId\":\"35643245_1.1.1.1_3306\"")); } diff --git a/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java b/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java index 77c7fc2fa..1d11dac76 100644 --- a/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java +++ b/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java @@ -66,7 +66,6 @@ import com.alibaba.nacos.common.utils.MD5Utils; import com.alibaba.nacos.common.utils.StringUtils; import com.alibaba.nacos.common.utils.ThreadUtils; import com.alibaba.nacos.common.utils.VersionUtils; -import com.alibaba.nacos.plugin.auth.api.RequestResource; import com.google.gson.Gson; import com.google.gson.JsonObject; import org.slf4j.Logger; diff --git a/client/src/main/java/com/alibaba/nacos/client/config/impl/ConfigTransportClient.java b/client/src/main/java/com/alibaba/nacos/client/config/impl/ConfigTransportClient.java index 596c99784..12e7f9903 100644 --- a/client/src/main/java/com/alibaba/nacos/client/config/impl/ConfigTransportClient.java +++ b/client/src/main/java/com/alibaba/nacos/client/config/impl/ConfigTransportClient.java @@ -23,10 +23,10 @@ import com.alibaba.nacos.client.env.NacosClientProperties; import com.alibaba.nacos.plugin.auth.api.RequestResource; import com.alibaba.nacos.client.config.filter.impl.ConfigResponse; import com.alibaba.nacos.client.security.SecurityProxy; -import com.alibaba.nacos.client.utils.ParamUtil; import com.alibaba.nacos.common.utils.ConvertUtils; import com.alibaba.nacos.common.utils.MD5Utils; import com.alibaba.nacos.common.utils.StringUtils; +import com.alibaba.nacos.client.utils.ParamUtil; import java.util.HashMap; import java.util.Map; diff --git a/client/src/main/java/com/alibaba/nacos/client/config/impl/ServerListManager.java b/client/src/main/java/com/alibaba/nacos/client/config/impl/ServerListManager.java index 4977a9e3f..3210a5003 100644 --- a/client/src/main/java/com/alibaba/nacos/client/config/impl/ServerListManager.java +++ b/client/src/main/java/com/alibaba/nacos/client/config/impl/ServerListManager.java @@ -23,7 +23,6 @@ import com.alibaba.nacos.client.env.NacosClientProperties; import com.alibaba.nacos.client.utils.ContextPathUtil; import com.alibaba.nacos.client.utils.EnvUtil; import com.alibaba.nacos.client.utils.LogUtils; -import com.alibaba.nacos.client.utils.ParamUtil; import com.alibaba.nacos.client.utils.TemplateUtils; import com.alibaba.nacos.common.http.HttpRestResult; import com.alibaba.nacos.common.http.client.NacosRestTemplate; @@ -48,6 +47,7 @@ import java.util.StringTokenizer; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import com.alibaba.nacos.client.utils.ParamUtil; import static com.alibaba.nacos.common.constant.RequestUrlConstants.HTTPS_PREFIX; import static com.alibaba.nacos.common.constant.RequestUrlConstants.HTTP_PREFIX; diff --git a/client/src/test/java/com/alibaba/nacos/client/ability/AbilityTest.java b/client/src/test/java/com/alibaba/nacos/client/ability/AbilityTest.java index a11850a27..75ca686d4 100644 --- a/client/src/test/java/com/alibaba/nacos/client/ability/AbilityTest.java +++ b/client/src/test/java/com/alibaba/nacos/client/ability/AbilityTest.java @@ -25,8 +25,9 @@ import com.alibaba.nacos.api.remote.request.Request; import com.alibaba.nacos.api.remote.response.Response; import com.alibaba.nacos.client.naming.remote.TestConnection; import com.alibaba.nacos.common.remote.ConnectionType; -import com.alibaba.nacos.common.remote.client.Connection; import com.alibaba.nacos.common.remote.client.RpcClient; +import com.alibaba.nacos.common.remote.client.Connection; +import com.alibaba.nacos.common.remote.client.RpcClientConfig; import com.alibaba.nacos.common.remote.client.ServerListFactory; import com.alibaba.nacos.common.remote.client.ServerRequestHandler; import org.junit.After; @@ -34,6 +35,7 @@ import org.junit.Assert; import org.junit.Test; import java.util.HashMap; import java.util.List; +import java.util.Map; public class AbilityTest { @@ -43,7 +45,42 @@ public class AbilityTest { @Test public void testReceive() throws Exception { - rpcClient = new RpcClient("name") { + rpcClient = new RpcClient(new RpcClientConfig() { + @Override + public String name() { + return "test"; + } + + @Override + public int retryTimes() { + return 1; + } + + @Override + public long timeOutMills() { + return 3000L; + } + + @Override + public long connectionKeepAlive() { + return 5000L; + } + + @Override + public int healthCheckRetryTimes() { + return 1; + } + + @Override + public long healthCheckTimeOut() { + return 3000L; + } + + @Override + public Map labels() { + return new HashMap<>(); + } + }) { @Override public ConnectionType getConnectionType() { diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java index f83e349ff..121fd96d2 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java @@ -43,7 +43,6 @@ import com.alibaba.nacos.common.utils.StringUtils; import com.alibaba.nacos.common.utils.VersionUtils; import com.alibaba.nacos.common.utils.TlsTypeResolve; import com.alibaba.nacos.common.utils.ThreadFactoryBuilder; -import com.google.common.base.Optional; import com.google.common.util.concurrent.ListenableFuture; import io.grpc.CompressorRegistry; import io.grpc.DecompressorRegistry; @@ -65,7 +64,6 @@ import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; import java.util.Arrays; -import java.util.Map; import java.util.Properties; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; @@ -421,9 +419,8 @@ public abstract class GrpcClient extends RpcClient { if (synResponse != null) { // try to wait for notify response synResponse.blocker.await(5000L, TimeUnit.MICROSECONDS); - } - // leave for adapting old version server - else { + } else { + // leave for adapting old version server //wait to register connection setup Thread.sleep(100L); } @@ -505,7 +502,7 @@ public abstract class GrpcClient extends RpcClient { RpcClientTlsConfig tlsConfig = clientConfig.tlsConfig(); if (!tlsConfig.getEnableTls()) { - return Optional.absent(); + return Optional.empty(); } try { SslContextBuilder builder = GrpcSslContexts.forClient(); diff --git a/console/src/main/resources/application.properties b/console/src/main/resources/application.properties index 66081292d..e9796c457 100644 --- a/console/src/main/resources/application.properties +++ b/console/src/main/resources/application.properties @@ -31,16 +31,16 @@ server.port=8848 #*************** Config Module Related Configurations ***************# ### Deprecated configuration property, it is recommended to use `spring.sql.init.platform` replaced. -# spring.datasource.platform=mysql -# nacos.plugin.datasource.log.enabled=true -#spring.sql.init.platform=mysql -### Count of DB: -# db.num=1 +spring.datasource.platform=mysql +nacos.plugin.datasource.log.enabled=true +spring.sql.init.platform=mysql +## Count of DB: +db.num=1 -### Connect URL of DB: -# db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC -# db.user=nacos -# db.password=nacos +## Connect URL of DB: +db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC +db.user=root +db.password=123456 #*************** Naming Module Related Configurations ***************# ### Data dispatch task execution period in milliseconds: diff --git a/core/src/main/java/com/alibaba/nacos/core/cluster/Member.java b/core/src/main/java/com/alibaba/nacos/core/cluster/Member.java index 69b0cafd6..7f5377629 100644 --- a/core/src/main/java/com/alibaba/nacos/core/cluster/Member.java +++ b/core/src/main/java/com/alibaba/nacos/core/cluster/Member.java @@ -56,7 +56,7 @@ public class Member implements Comparable, Cloneable, Serializable { @Deprecated private ServerAbilities abilities = new ServerAbilities(); - private boolean supportRemoteConnection; + private boolean grpcReportEnabled; public Member() { String prefix = "nacos.core.member.meta."; @@ -68,12 +68,12 @@ public class Member implements Comparable, Cloneable, Serializable { .put(MemberMetaDataConstants.WEIGHT, EnvUtil.getProperty(prefix + MemberMetaDataConstants.WEIGHT, "1")); } - public boolean isSupportRemoteConnection() { - return supportRemoteConnection; + public boolean isGrpcReportEnabled() { + return grpcReportEnabled; } - public void setSupportRemoteConnection(boolean supportRemoteConnection) { - this.supportRemoteConnection = supportRemoteConnection; + public void setGrpcReportEnabled(boolean grpcReportEnabled) { + this.grpcReportEnabled = grpcReportEnabled; } @Deprecated diff --git a/core/src/main/java/com/alibaba/nacos/core/cluster/MemberUtil.java b/core/src/main/java/com/alibaba/nacos/core/cluster/MemberUtil.java index 727155505..97f8afcd0 100644 --- a/core/src/main/java/com/alibaba/nacos/core/cluster/MemberUtil.java +++ b/core/src/main/java/com/alibaba/nacos/core/cluster/MemberUtil.java @@ -66,7 +66,7 @@ public class MemberUtil { oldMember.setExtendInfo(newMember.getExtendInfo()); oldMember.setAddress(newMember.getAddress()); oldMember.setAbilities(newMember.getAbilities()); - oldMember.setSupportRemoteConnection(newMember.isSupportRemoteConnection()); + oldMember.setGrpcReportEnabled(newMember.isGrpcReportEnabled()); } /** @@ -95,6 +95,8 @@ public class MemberUtil { extendInfo.put(MemberMetaDataConstants.RAFT_PORT, String.valueOf(calculateRaftPort(target))); extendInfo.put(MemberMetaDataConstants.READY_TO_UPGRADE, true); target.setExtendInfo(extendInfo); + // use grpc to report default + target.setGrpcReportEnabled(true); return target; } @@ -111,7 +113,7 @@ public class MemberUtil { boolean oldVerJudge = member.getAbilities().getRemoteAbility().isSupportRemoteConnection(); - return member.isSupportRemoteConnection() || oldVerJudge; + return member.isGrpcReportEnabled() || oldVerJudge; } public static int calculateRaftPort(Member member) { @@ -281,7 +283,7 @@ public class MemberUtil { } // if change - if (expected.isSupportRemoteConnection() != actual.isSupportRemoteConnection()) { + if (expected.isGrpcReportEnabled() != actual.isGrpcReportEnabled()) { return true; } diff --git a/core/src/main/java/com/alibaba/nacos/core/cluster/ServerMemberManager.java b/core/src/main/java/com/alibaba/nacos/core/cluster/ServerMemberManager.java index a8436bfc1..eeee8855c 100644 --- a/core/src/main/java/com/alibaba/nacos/core/cluster/ServerMemberManager.java +++ b/core/src/main/java/com/alibaba/nacos/core/cluster/ServerMemberManager.java @@ -164,7 +164,7 @@ public class ServerMemberManager implements ApplicationListener Date: Mon, 10 Jul 2023 22:38:56 +0800 Subject: [PATCH 45/55] correct the comments --- .../nacos/api/ability/register/impl/ClientAbilities.java | 4 ++-- .../nacos/api/ability/register/impl/ServerAbilities.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java index 533f4ecdd..3a5a796ce 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java @@ -40,8 +40,8 @@ public class ClientAbilities extends AbstractAbilityRegistry { * DATA_COMPRESSION("compression", 1) * This field can be used outside, and the offset should be unique. * - * And then you need to declare the offset of the flag bit of this ability in the ability table, you can: - * supportedAbilities.put(AbilityKey.DATA_COMPRESSION, true); means that is the first bit from left to right in the table. + * And then you need to declare whether turn on in the ability table, you can: + * supportedAbilities.put(AbilityKey.DATA_COMPRESSION, true); means that current client support AbilityKey.DATA_COMPRESSION. * */ // put ability here, which you want current client supports diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java index ca4597a4f..66a6fbfa0 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java @@ -40,8 +40,8 @@ public class ServerAbilities extends AbstractAbilityRegistry { * DATA_COMPRESSION("compression", 1) * This field can be used outside, and the offset should be unique. * - * And then you need to declare the offset of the flag bit of this ability in the ability table, you can: - * supportedAbilities.put(AbilityKey.DATA_COMPRESSION, true); means that is the first bit from left to right in the table. + * And then you need to declare whether turn on in the ability table, you can: + * supportedAbilities.put(AbilityKey.DATA_COMPRESSION, true); means that current client support AbilityKey.DATA_COMPRESSION. * */ // put ability here, which you want current server supports From ae148b86be716d04fc55793b18ed1a7f02715924 Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Mon, 10 Jul 2023 22:44:52 +0800 Subject: [PATCH 46/55] correct the comments and add description field for AbilityKey. --- .../api/ability/constant/AbilityKey.java | 28 +++++++++++-------- .../register/impl/ClientAbilities.java | 5 ++-- .../register/impl/ServerAbilities.java | 5 ++-- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java index d78de35d3..a6d3d691a 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java @@ -29,29 +29,33 @@ import java.util.stream.Collectors; * @date 2022/8/31 12:27 **/ public enum AbilityKey { - - /**. - * just for junit test - */ - TEST_1("test_1"), - - /**. - * just for junit test - */ - TEST_2("test_2"); + + TEST_1("test_1", "just for junit test"), + + TEST_2("test_2", "just for junit test"); /**. * the name of a certain ability */ private final String keyName; - - AbilityKey(String name) { + + /** + * description or comment about this ability. + */ + private final String description; + + AbilityKey(String name, String description) { this.keyName = name; + this.description = description; } public String getName() { return keyName; } + + public String getDescription() { + return description; + } /**. * All key set diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java index 3a5a796ce..669bd2ab3 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java @@ -37,11 +37,10 @@ public class ClientAbilities extends AbstractAbilityRegistry { * The key is from

AbilityKey

, the value is whether turn on. * * You can add a new public field in

AbilityKey

like: - * DATA_COMPRESSION("compression", 1) - * This field can be used outside, and the offset should be unique. + * DATA_COMPRESSION("compression", "description about this ability") * * And then you need to declare whether turn on in the ability table, you can: - * supportedAbilities.put(AbilityKey.DATA_COMPRESSION, true); means that current client support AbilityKey.DATA_COMPRESSION. + * supportedAbilities.put(AbilityKey.DATA_COMPRESSION, true); means that current client support compression. * */ // put ability here, which you want current client supports diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java index 66a6fbfa0..456b9f906 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java @@ -37,11 +37,10 @@ public class ServerAbilities extends AbstractAbilityRegistry { * The key is from

AbilityKey

, the value is whether turn on. * * You can add a new public field in

AbilityKey

like: - * DATA_COMPRESSION("compression", 1) - * This field can be used outside, and the offset should be unique. + * DATA_COMPRESSION("compression", "description about this ability") * * And then you need to declare whether turn on in the ability table, you can: - * supportedAbilities.put(AbilityKey.DATA_COMPRESSION, true); means that current client support AbilityKey.DATA_COMPRESSION. + * supportedAbilities.put(AbilityKey.DATA_COMPRESSION, true); means that current client support compression. * */ // put ability here, which you want current server supports From d6958ab27c48017e5b4a6fced8bb218aff4f31d0 Mon Sep 17 00:00:00 2001 From: chenyiqin <83362909+Daydreamer-ia@users.noreply.github.com> Date: Tue, 11 Jul 2023 17:15:52 +0800 Subject: [PATCH 47/55] Correct comment and add description for AbilityKey (#10760) * correct the comments * correct the comments and add description field for AbilityKey. --- .../api/ability/constant/AbilityKey.java | 28 +++++++++++-------- .../register/impl/ClientAbilities.java | 7 ++--- .../register/impl/ServerAbilities.java | 7 ++--- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java index d78de35d3..a6d3d691a 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java @@ -29,29 +29,33 @@ import java.util.stream.Collectors; * @date 2022/8/31 12:27 **/ public enum AbilityKey { - - /**. - * just for junit test - */ - TEST_1("test_1"), - - /**. - * just for junit test - */ - TEST_2("test_2"); + + TEST_1("test_1", "just for junit test"), + + TEST_2("test_2", "just for junit test"); /**. * the name of a certain ability */ private final String keyName; - - AbilityKey(String name) { + + /** + * description or comment about this ability. + */ + private final String description; + + AbilityKey(String name, String description) { this.keyName = name; + this.description = description; } public String getName() { return keyName; } + + public String getDescription() { + return description; + } /**. * All key set diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java index 533f4ecdd..669bd2ab3 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java @@ -37,11 +37,10 @@ public class ClientAbilities extends AbstractAbilityRegistry { * The key is from

AbilityKey

, the value is whether turn on. * * You can add a new public field in

AbilityKey

like: - * DATA_COMPRESSION("compression", 1) - * This field can be used outside, and the offset should be unique. + * DATA_COMPRESSION("compression", "description about this ability") * - * And then you need to declare the offset of the flag bit of this ability in the ability table, you can: - * supportedAbilities.put(AbilityKey.DATA_COMPRESSION, true); means that is the first bit from left to right in the table. + * And then you need to declare whether turn on in the ability table, you can: + * supportedAbilities.put(AbilityKey.DATA_COMPRESSION, true); means that current client support compression. * */ // put ability here, which you want current client supports diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java index ca4597a4f..456b9f906 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java @@ -37,11 +37,10 @@ public class ServerAbilities extends AbstractAbilityRegistry { * The key is from

AbilityKey

, the value is whether turn on. * * You can add a new public field in

AbilityKey

like: - * DATA_COMPRESSION("compression", 1) - * This field can be used outside, and the offset should be unique. + * DATA_COMPRESSION("compression", "description about this ability") * - * And then you need to declare the offset of the flag bit of this ability in the ability table, you can: - * supportedAbilities.put(AbilityKey.DATA_COMPRESSION, true); means that is the first bit from left to right in the table. + * And then you need to declare whether turn on in the ability table, you can: + * supportedAbilities.put(AbilityKey.DATA_COMPRESSION, true); means that current client support compression. * */ // put ability here, which you want current server supports From e5f54badb3f4aad3500e78a41c5c00bfbd00848f Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Sun, 24 Sep 2023 22:14:06 +0800 Subject: [PATCH 48/55] remove connectionId in SetupAckRequest, expose timeout param for capability negotiation, add uncommitted file --- .../api/remote/request/SetupAckRequest.java | 20 +-- .../com.alibaba.nacos.api.remote.Payload | 2 + .../client/grpc/DefaultGrpcClientConfig.java | 20 ++- .../common/remote/client/grpc/GrpcClient.java | 141 +++++++++++------- .../remote/client/grpc/GrpcClientConfig.java | 7 + .../remote/client/grpc/GrpcConstants.java | 3 + .../common/remote/client/RpcClientTest.java | 2 +- .../grpc/GrpcBiStreamRequestAcceptor.java | 3 +- 8 files changed, 122 insertions(+), 76 deletions(-) diff --git a/api/src/main/java/com/alibaba/nacos/api/remote/request/SetupAckRequest.java b/api/src/main/java/com/alibaba/nacos/api/remote/request/SetupAckRequest.java index 8c37bf842..cecdaa825 100644 --- a/api/src/main/java/com/alibaba/nacos/api/remote/request/SetupAckRequest.java +++ b/api/src/main/java/com/alibaba/nacos/api/remote/request/SetupAckRequest.java @@ -20,22 +20,20 @@ import java.util.Map; import static com.alibaba.nacos.api.common.Constants.Remote.INTERNAL_MODULE; -/**. - * @author Daydreamer - * @description Server tells the client that the connection is established +/** + * Server tells the client that the connection is established. + * + * @author Daydreamer. * @date 2022/7/12 19:21 **/ public class SetupAckRequest extends ServerRequest { - private String connectionId; - private Map abilityTable; public SetupAckRequest() { } - public SetupAckRequest(String connectionId, Map abilityTable) { - this.connectionId = connectionId; + public SetupAckRequest(Map abilityTable) { this.abilityTable = abilityTable; } @@ -47,14 +45,6 @@ public class SetupAckRequest extends ServerRequest { this.abilityTable = abilityTable; } - public String getConnectionId() { - return connectionId; - } - - public void setConnectionId(String connectionId) { - this.connectionId = connectionId; - } - @Override public String getModule() { return INTERNAL_MODULE; diff --git a/api/src/main/resources/META-INF/services/com.alibaba.nacos.api.remote.Payload b/api/src/main/resources/META-INF/services/com.alibaba.nacos.api.remote.Payload index d838e65ea..5e9552afd 100644 --- a/api/src/main/resources/META-INF/services/com.alibaba.nacos.api.remote.Payload +++ b/api/src/main/resources/META-INF/services/com.alibaba.nacos.api.remote.Payload @@ -22,6 +22,8 @@ com.alibaba.nacos.api.remote.request.PushAckRequest com.alibaba.nacos.api.remote.request.ServerCheckRequest com.alibaba.nacos.api.remote.request.ServerLoaderInfoRequest com.alibaba.nacos.api.remote.request.ServerReloadRequest +com.alibaba.nacos.api.remote.request.SetupAckRequest +com.alibaba.nacos.api.remote.response.SetupAckResponse com.alibaba.nacos.api.remote.response.ClientDetectionResponse com.alibaba.nacos.api.remote.response.ConnectResetResponse com.alibaba.nacos.api.remote.response.ErrorResponse diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/DefaultGrpcClientConfig.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/DefaultGrpcClientConfig.java index 685405022..a191081f9 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/DefaultGrpcClientConfig.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/DefaultGrpcClientConfig.java @@ -59,6 +59,8 @@ public class DefaultGrpcClientConfig implements GrpcClientConfig { private int healthCheckRetryTimes; private long healthCheckTimeOut; + + private long capabilityNegotiationTimeout; private Map labels; @@ -90,6 +92,7 @@ public class DefaultGrpcClientConfig implements GrpcClientConfig { this.healthCheckTimeOut = loadLongConfig(GrpcConstants.GRPC_HEALTHCHECK_TIMEOUT, builder.healthCheckTimeOut); this.channelKeepAliveTimeout = loadLongConfig(GrpcConstants.GRPC_CHANNEL_KEEP_ALIVE_TIMEOUT, builder.channelKeepAliveTimeout); + this.capabilityNegotiationTimeout = loadLongConfig(GrpcConstants.GRPC_CHANNEL_CAPABILITY_NEGOTIATION_TIMEOUT, builder.capabilityNegotiationTimeout); this.labels = builder.labels; this.labels.put("tls.enable", "false"); if (Objects.nonNull(builder.tlsConfig)) { @@ -177,6 +180,11 @@ public class DefaultGrpcClientConfig implements GrpcClientConfig { this.tlsConfig = tlsConfig; } + @Override + public long capabilityNegotiationTimeout() { + return this.capabilityNegotiationTimeout; + } + @Override public int healthCheckRetryTimes() { return healthCheckRetryTimes; @@ -225,6 +233,8 @@ public class DefaultGrpcClientConfig implements GrpcClientConfig { private int healthCheckRetryTimes = 3; private long healthCheckTimeOut = 3000L; + + private long capabilityNegotiationTimeout = 5000L; private Map labels = new HashMap<>(); @@ -280,6 +290,10 @@ public class DefaultGrpcClientConfig implements GrpcClientConfig { this.channelKeepAlive = Integer.parseInt( properties.getProperty(GrpcConstants.GRPC_CHANNEL_KEEP_ALIVE_TIME)); } + if (properties.contains(GrpcConstants.GRPC_CHANNEL_CAPABILITY_NEGOTIATION_TIMEOUT)) { + this.capabilityNegotiationTimeout = Integer.parseInt( + properties.getProperty(GrpcConstants.GRPC_CHANNEL_CAPABILITY_NEGOTIATION_TIMEOUT)); + } if (properties.contains(GrpcConstants.GRPC_HEALTHCHECK_RETRY_TIMES)) { this.healthCheckRetryTimes = Integer.parseInt( properties.getProperty(GrpcConstants.GRPC_HEALTHCHECK_RETRY_TIMES)); @@ -398,7 +412,11 @@ public class DefaultGrpcClientConfig implements GrpcClientConfig { this.channelKeepAliveTimeout = channelKeepAliveTimeout; return this; } - + + public void setCapabilityNegotiationTimeout(long capabilityNegotiationTimeout) { + this.capabilityNegotiationTimeout = capabilityNegotiationTimeout; + } + /** * set healthCheckRetryTimes. */ diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java index 121fd96d2..c4a96fccd 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java @@ -32,11 +32,12 @@ import com.alibaba.nacos.api.remote.response.SetupAckResponse; import com.alibaba.nacos.common.ability.discover.NacosAbilityManagerHolder; import com.alibaba.nacos.common.packagescan.resource.Resource; import com.alibaba.nacos.common.remote.ConnectionType; -import com.alibaba.nacos.common.remote.client.RpcClient; -import com.alibaba.nacos.common.remote.client.RpcClientStatus; -import com.alibaba.nacos.common.remote.client.Connection; import com.alibaba.nacos.common.remote.client.RpcClientTlsConfig; +import com.alibaba.nacos.common.remote.client.RpcClientStatus; +import com.alibaba.nacos.common.remote.client.RpcClient; import com.alibaba.nacos.common.remote.client.ServerListFactory; +import com.alibaba.nacos.common.remote.client.Connection; +import com.alibaba.nacos.common.remote.client.ServerRequestHandler; import com.alibaba.nacos.common.utils.JacksonUtils; import com.alibaba.nacos.common.utils.LoggerUtils; import com.alibaba.nacos.common.utils.StringUtils; @@ -61,7 +62,6 @@ import org.slf4j.LoggerFactory; import java.util.Map; import java.util.Optional; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; import java.util.Arrays; import java.util.Properties; @@ -87,7 +87,7 @@ public abstract class GrpcClient extends RpcClient { /** * Block to wait setup success response. */ - private final Map markForSetup = new ConcurrentHashMap<>(); + private final RecAbilityContext recAbilityContext = new RecAbilityContext(null); @Override public ConnectionType getConnectionType() { @@ -140,23 +140,7 @@ public abstract class GrpcClient extends RpcClient { */ private void initSetupHandler() { // register to handler setup request - registerServerRequestHandler((request, connection) -> { - // if finish setup - if (request instanceof SetupAckRequest) { - SetupAckRequest setupAckRequest = (SetupAckRequest) request; - // remove and count down - RecAbilityContext context = markForSetup.remove(setupAckRequest.getConnectionId()); - if (context != null) { - // set server abilities - context.connection.setAbilityTable(setupAckRequest.getAbilityTable()); - // notify - java.util.Optional.ofNullable(context.blocker) - .orElse(new CountDownLatch(1)) - .countDown(); - } - } - return new SetupAckResponse(); - }); + registerServerRequestHandler(new SetupRequestHandler(this.recAbilityContext)); } /** @@ -309,12 +293,7 @@ public abstract class GrpcClient extends RpcClient { LoggerUtils.printIfErrorEnabled(LOGGER, "[{}]Error to process server push response: {}", grpcConn.getConnectionId(), payload.getBody().getValue().toStringUtf8()); // remove and notify - RecAbilityContext context = markForSetup.remove(grpcConn.getConnectionId()); - if (context != null) { - Optional.ofNullable(context.blocker) - .orElse(new CountDownLatch(1)) - .countDown(); - } + recAbilityContext.release(null); } } @@ -396,7 +375,7 @@ public abstract class GrpcClient extends RpcClient { // if not supported, it will be false if (serverCheckResponse.isSupportAbilityNegotiation()) { // mark - markForSetup.put(serverCheckResponse.getConnectionId(), new RecAbilityContext(grpcConn, new CountDownLatch(1))); + this.recAbilityContext.reset(grpcConn); } //create stream request and bind connection event to this connection. @@ -415,13 +394,12 @@ public abstract class GrpcClient extends RpcClient { conSetupRequest.setTenant(super.getTenant()); grpcConn.sendRequest(conSetupRequest); // wait for response - RecAbilityContext synResponse = markForSetup.get(connectionId); - if (synResponse != null) { + if (recAbilityContext.isNeedToSync()) { // try to wait for notify response - synResponse.blocker.await(5000L, TimeUnit.MICROSECONDS); + recAbilityContext.await(this.clientConfig.capabilityNegotiationTimeout(), TimeUnit.MILLISECONDS); } else { // leave for adapting old version server - //wait to register connection setup + // wait to register connection setup Thread.sleep(100L); } return grpcConn; @@ -430,25 +408,14 @@ public abstract class GrpcClient extends RpcClient { } catch (Exception e) { LOGGER.error("[{}]Fail to connect to server!,error={}", GrpcClient.this.getName(), e); // remove and notify - RecAbilityContext context = markForSetup.remove(connectionId); - if (context != null) { - Optional.ofNullable(context.blocker) - .orElse(new CountDownLatch(1)) - .countDown(); - } + recAbilityContext.release(null); } return null; } @Override protected void afterReset(ConnectResetRequest request) { - RecAbilityContext context = markForSetup.remove(request.getConnectionId()); - if (context != null) { - // remove and notify - java.util.Optional.ofNullable(context.blocker) - .orElse(new CountDownLatch(1)) - .countDown(); - } + recAbilityContext.release(null); } /** @@ -459,32 +426,92 @@ public abstract class GrpcClient extends RpcClient { /** * connection waiting for server abilities. */ - private Connection connection; + private volatile Connection connection; /** * way to block client. */ - private CountDownLatch blocker; + private volatile CountDownLatch blocker; - public RecAbilityContext(Connection connection, CountDownLatch blocker) { + private volatile boolean needToSync = false; + + public RecAbilityContext(Connection connection) { this.connection = connection; - this.blocker = blocker; + this.blocker = new CountDownLatch(1); } - public Connection getConnection() { - return connection; + /** + * whether to sync for ability table. + * + * @return whether to sync for ability table. + */ + public boolean isNeedToSync() { + return this.needToSync; } - public void setConnection(Connection connection) { + /** + * reset with new connection which is waiting for ability table. + * + * @param connection new connection which is waiting for ability table. + */ + public void reset(Connection connection) { this.connection = connection; + this.blocker = new CountDownLatch(1); + this.needToSync = true; } - public CountDownLatch getBlocker() { - return blocker; + /** + * notify sync by abilities. + * + * @param abilities abilities. + */ + public void release(Map abilities) { + if (this.connection != null) { + this.connection.setAbilityTable(abilities); + // avoid repeat setting + this.connection = null; + } + if (this.blocker != null) { + blocker.countDown(); + } + this.needToSync = false; } - public void setBlocker(CountDownLatch blocker) { - this.blocker = blocker; + /** + * await for abilities. + * + * @param timeout timeout. + * @param unit unit. + * @throws InterruptedException by blocker. + */ + public void await(long timeout, TimeUnit unit) throws InterruptedException { + if (this.blocker != null) { + this.blocker.await(timeout, unit); + } + this.needToSync = false; + } + } + + /** + * Setup response handler. + */ + class SetupRequestHandler implements ServerRequestHandler { + + private final RecAbilityContext abilityContext; + + public SetupRequestHandler(RecAbilityContext abilityContext) { + this.abilityContext = abilityContext; + } + + @Override + public Response requestReply(Request request, Connection connection) { + // if finish setup + if (request instanceof SetupAckRequest) { + SetupAckRequest setupAckRequest = (SetupAckRequest) request; + // remove and count down + recAbilityContext.release(setupAckRequest.getAbilityTable()); + } + return new SetupAckResponse(); } } diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClientConfig.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClientConfig.java index 776072830..1c1b4003b 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClientConfig.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClientConfig.java @@ -96,4 +96,11 @@ public interface GrpcClientConfig extends RpcClientConfig { */ void setTlsConfig(RpcClientTlsConfig tlsConfig); + /** + * get timeout of connection setup(TimeUnit.MILLISECONDS). + * + * @return timeout of connection setup + */ + long capabilityNegotiationTimeout(); + } diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcConstants.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcConstants.java index c1afa0744..908997def 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcConstants.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcConstants.java @@ -79,6 +79,9 @@ public class GrpcConstants { @GRpcConfigLabel public static final String GRPC_CHANNEL_KEEP_ALIVE_TIMEOUT = NACOS_CLIENT_GRPC + ".channel.keep.alive.timeout"; + @GRpcConfigLabel + public static final String GRPC_CHANNEL_CAPABILITY_NEGOTIATION_TIMEOUT = NACOS_CLIENT_GRPC + ".channel.capability.negotiation.timeout"; + private static final Set CONFIG_NAMES = new HashSet<>(); @Documented diff --git a/common/src/test/java/com/alibaba/nacos/common/remote/client/RpcClientTest.java b/common/src/test/java/com/alibaba/nacos/common/remote/client/RpcClientTest.java index 796e2c6d0..281d0ebb2 100644 --- a/common/src/test/java/com/alibaba/nacos/common/remote/client/RpcClientTest.java +++ b/common/src/test/java/com/alibaba/nacos/common/remote/client/RpcClientTest.java @@ -642,7 +642,7 @@ public class RpcClientTest { return null; } }; - rpcClient.serverRequestHandlers.add(req -> { + rpcClient.serverRequestHandlers.add((req, conn) -> { throw new RuntimeException(); }); rpcClient.handleServerRequest(request); diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java index fbadeab25..d01420b62 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java @@ -138,8 +138,7 @@ public class GrpcBiStreamRequestAcceptor extends BiRequestStreamGrpc.BiRequestSt } else { try { // finish register, tell client has set up successfully - connection.request(new SetupAckRequest(connectionId, - NacosAbilityManagerHolder.getInstance().getCurrentNodeAbilities()), 3000L); + connection.request(new SetupAckRequest(NacosAbilityManagerHolder.getInstance().getCurrentNodeAbilities()), 3000L); } catch (Exception e) { // nothing to do From c565a2bdd59626fb807d3484e4310055df6dbaec Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Mon, 25 Sep 2023 14:17:18 +0800 Subject: [PATCH 49/55] extern abilities spi processor, refactor AbilityKey. --- .../api/ability/constant/AbilityKey.java | 103 +++++++++++------- .../api/ability/constant/AbilityMode.java | 25 +++++ .../initializer/AbilityInitializer.java | 1 + .../initializer/AbilityPostProcessor.java | 22 ++++ .../nacos/api/utils/AbilityKeyTest.java | 37 ++++--- .../ability/ClientAbilityControlManager.java | 4 +- .../nacos/client/ability/AbilityTest.java | 16 +-- .../AbstractAbilityControlManager.java | 28 ++++- .../control/ServerAbilityControlManager.java | 12 +- .../ability/AbilityControlManagerTest.java | 35 +++--- .../ability/config/AbilityConfigsTest.java | 54 ++++----- .../ability/config/TestAbilityConfig.java | 4 +- .../nacos/test/ability/AbilityDiscovery.java | 12 +- .../TestServerAbilityControlManager.java | 8 +- 14 files changed, 229 insertions(+), 132 deletions(-) create mode 100644 api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityMode.java create mode 100644 api/src/main/java/com/alibaba/nacos/api/ability/initializer/AbilityPostProcessor.java diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java index a6d3d691a..918395455 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java @@ -16,26 +16,28 @@ package com.alibaba.nacos.api.ability.constant; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Map; -import java.util.function.Function; +import java.util.*; import java.util.stream.Collectors; -/**. +/** + * Ability key constant. It is used to constrain the ability key.
+ * Ensure that return value of {@link AbilityKey#getName()} is unique under one specify {@link AbilityMode}. + * * @author Daydreamer - * @description Ability key constant. It is used to constrain the ability key. * @date 2022/8/31 12:27 **/ public enum AbilityKey { - TEST_1("test_1", "just for junit test"), + SERVER_TEST_1("test_1", "just for junit test", AbilityMode.SERVER), - TEST_2("test_2", "just for junit test"); + SERVER_TEST_2("test_2", "just for junit test", AbilityMode.SERVER), + + SDK_CLIENT_TEST_1("test_1", "just for junit test", AbilityMode.SDK_CLIENT), + + CLUSTER_CLIENT_TEST_1("test_1", "just for junit test", AbilityMode.CLUSTER_CLIENT); - /**. - * the name of a certain ability + /** + * the name of a certain ability. */ private final String keyName; @@ -44,11 +46,17 @@ public enum AbilityKey { */ private final String description; - AbilityKey(String name, String description) { - this.keyName = name; + /** + * ability mode, which endpoint hold this ability. + */ + private final AbilityMode mode; + + AbilityKey(String keyName, String description, AbilityMode mode) { + this.keyName = keyName; this.description = description; + this.mode = mode; } - + public String getName() { return keyName; } @@ -56,54 +64,58 @@ public enum AbilityKey { public String getDescription() { return description; } - - /**. - * All key set + + public AbilityMode getMode() { + return mode; + } + + /** + * All key set. */ - private static final Map ALL_ABILITIES; + private static final Map> ALL_ABILITIES = new HashMap<>(); - /**. - * Get all keys + /** + * Get all keys. * * @return all keys */ - public static Collection getAllValues() { - return Collections.unmodifiableCollection(ALL_ABILITIES.values()); + public static Collection getAllValues(AbilityMode mode) { + return Collections.unmodifiableCollection(ALL_ABILITIES.get(mode).values()); } - /**. - * Get all names + /** + * Get all names. * * @return all names */ - public static Collection getAllNames() { - return Collections.unmodifiableCollection(ALL_ABILITIES.keySet()); + public static Collection getAllNames(AbilityMode mode) { + return Collections.unmodifiableCollection(ALL_ABILITIES.get(mode).keySet()); } - /**. - * Whether contains this name + /** + * Whether contains this name. * * @param name key name * @return whether contains */ - public static boolean isLegalKey(String name) { - return ALL_ABILITIES.containsKey(name); + public static boolean isLegalKey(AbilityMode mode, String name) { + return ALL_ABILITIES.get(mode).containsKey(name); } - /**. - * Map the string key to enum + /** + * Map the string key to enum. * * @param abilities map * @return enum map */ - public static Map mapEnum(Map abilities) { + public static Map mapEnum(AbilityMode mode, Map abilities) { if (abilities == null || abilities.isEmpty()) { return Collections.emptyMap(); } return abilities.entrySet() .stream() - .filter(entry -> isLegalKey(entry.getKey())) - .collect(Collectors.toMap((entry) -> getEnum(entry.getKey()), Map.Entry::getValue)); + .filter(entry -> isLegalKey(mode, entry.getKey())) + .collect(Collectors.toMap((entry) -> getEnum(mode, entry.getKey()), Map.Entry::getValue)); } /**. @@ -127,11 +139,26 @@ public enum AbilityKey { * @param key string key * @return enum */ - public static AbilityKey getEnum(String key) { - return ALL_ABILITIES.get(key); + public static AbilityKey getEnum(AbilityMode mode, String key) { + return ALL_ABILITIES.get(mode).get(key); } static { - ALL_ABILITIES = Arrays.stream(AbilityKey.values()).collect(Collectors.toMap(AbilityKey::getName, Function.identity())); + // check for developer + // ensure that name filed is unique under a AbilityMode + try { + for (AbilityKey value : AbilityKey.values()) { + AbilityMode mode = value.mode; + Map map = ALL_ABILITIES.getOrDefault(mode, new HashMap<>()); + AbilityKey previous = map.putIfAbsent(value.getName(), value); + if (previous != null) { + throw new IllegalStateException("Duplicate key name field " + value + " and " + previous + " under mode: " + mode); + } + ALL_ABILITIES.put(mode, map); + } + } catch (Throwable t) { + // for developer checking + t.printStackTrace(); + } } } diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityMode.java b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityMode.java new file mode 100644 index 000000000..518572b16 --- /dev/null +++ b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityMode.java @@ -0,0 +1,25 @@ +package com.alibaba.nacos.api.ability.constant; + +/** + * Ability mode. + * + * @author Daydreamer + * @date 2023/9/25 12:32 + **/ +public enum AbilityMode { + + /** + * for server ability. + */ + SERVER, + + /** + * for sdk client. + */ + SDK_CLIENT, + + /** + * for cluster client. + */ + CLUSTER_CLIENT; +} diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/initializer/AbilityInitializer.java b/api/src/main/java/com/alibaba/nacos/api/ability/initializer/AbilityInitializer.java index f7ad356c1..71192dffa 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/initializer/AbilityInitializer.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/initializer/AbilityInitializer.java @@ -21,6 +21,7 @@ package com.alibaba.nacos.api.ability.initializer; * * @author xiweng.yy */ +@Deprecated public interface AbilityInitializer { /** diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/initializer/AbilityPostProcessor.java b/api/src/main/java/com/alibaba/nacos/api/ability/initializer/AbilityPostProcessor.java new file mode 100644 index 000000000..bec04d6e4 --- /dev/null +++ b/api/src/main/java/com/alibaba/nacos/api/ability/initializer/AbilityPostProcessor.java @@ -0,0 +1,22 @@ +package com.alibaba.nacos.api.ability.initializer; + +import com.alibaba.nacos.api.ability.constant.AbilityKey; + +import java.util.Map; + +/** + * Nacos ability post processor, load by spi. + * + * @author Daydreamer-ia + */ +public interface AbilityPostProcessor { + + + /** + * process before loading by Ability Controller . + * + * @param abilities abilities + */ + void process(Map abilities); + +} diff --git a/api/src/test/java/com/alibaba/nacos/api/utils/AbilityKeyTest.java b/api/src/test/java/com/alibaba/nacos/api/utils/AbilityKeyTest.java index baf0d1c2d..32af5ad2b 100644 --- a/api/src/test/java/com/alibaba/nacos/api/utils/AbilityKeyTest.java +++ b/api/src/test/java/com/alibaba/nacos/api/utils/AbilityKeyTest.java @@ -17,6 +17,7 @@ package com.alibaba.nacos.api.utils; import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.constant.AbilityMode; import org.junit.Assert; import org.junit.Test; @@ -36,39 +37,39 @@ public class AbilityKeyTest { Map stringBooleanMap = AbilityKey.mapStr(enumMap); Assert.assertEquals(0, stringBooleanMap.size()); - enumMap.put(AbilityKey.TEST_1, true); - enumMap.put(AbilityKey.TEST_2, false); + enumMap.put(AbilityKey.SERVER_TEST_1, true); + enumMap.put(AbilityKey.SERVER_TEST_2, false); stringBooleanMap = AbilityKey.mapStr(enumMap); Assert.assertEquals(2, stringBooleanMap.size()); - Assert.assertTrue(stringBooleanMap.get(AbilityKey.TEST_1.getName())); - Assert.assertFalse(stringBooleanMap.get(AbilityKey.TEST_2.getName())); + Assert.assertTrue(stringBooleanMap.get(AbilityKey.SERVER_TEST_1.getName())); + Assert.assertFalse(stringBooleanMap.get(AbilityKey.SERVER_TEST_2.getName())); - enumMap.put(AbilityKey.TEST_2, true); + enumMap.put(AbilityKey.SERVER_TEST_2, true); stringBooleanMap = AbilityKey.mapStr(enumMap); Assert.assertEquals(2, stringBooleanMap.size()); - Assert.assertTrue(stringBooleanMap.get(AbilityKey.TEST_1.getName())); - Assert.assertTrue(stringBooleanMap.get(AbilityKey.TEST_2.getName())); + Assert.assertTrue(stringBooleanMap.get(AbilityKey.SERVER_TEST_1.getName())); + Assert.assertTrue(stringBooleanMap.get(AbilityKey.SERVER_TEST_2.getName())); } @Test public void testMapEnum() { Map mapStr = new HashMap<>(); mapStr.put("test-no-existed", true); - Map enumMap = AbilityKey.mapEnum(mapStr); + Map enumMap = AbilityKey.mapEnum(AbilityMode.SERVER, mapStr); Assert.assertEquals(0, enumMap.size()); - mapStr.put(AbilityKey.TEST_2.getName(), false); - mapStr.put(AbilityKey.TEST_1.getName(), true); - enumMap = AbilityKey.mapEnum(mapStr); - Assert.assertFalse(enumMap.get(AbilityKey.TEST_2)); - Assert.assertTrue(enumMap.get(AbilityKey.TEST_1)); + mapStr.put(AbilityKey.SERVER_TEST_2.getName(), false); + mapStr.put(AbilityKey.SERVER_TEST_1.getName(), true); + enumMap = AbilityKey.mapEnum(AbilityMode.SERVER, mapStr); + Assert.assertFalse(enumMap.get(AbilityKey.SERVER_TEST_2)); + Assert.assertTrue(enumMap.get(AbilityKey.SERVER_TEST_1)); mapStr.clear(); - mapStr.put(AbilityKey.TEST_2.getName(), true); - mapStr.put(AbilityKey.TEST_1.getName(), true); - enumMap = AbilityKey.mapEnum(mapStr); - Assert.assertTrue(enumMap.get(AbilityKey.TEST_2)); - Assert.assertTrue(enumMap.get(AbilityKey.TEST_1)); + mapStr.put(AbilityKey.SERVER_TEST_2.getName(), true); + mapStr.put(AbilityKey.SERVER_TEST_1.getName(), true); + enumMap = AbilityKey.mapEnum(AbilityMode.SERVER, mapStr); + Assert.assertTrue(enumMap.get(AbilityKey.SERVER_TEST_2)); + Assert.assertTrue(enumMap.get(AbilityKey.SERVER_TEST_1)); } diff --git a/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java b/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java index af537a60b..f1cb6cf7d 100644 --- a/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java +++ b/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java @@ -33,8 +33,8 @@ public class ClientAbilityControlManager extends AbstractAbilityControlManager { } @Override - protected Map initCurrentNodeAbilities() { - return AbilityKey.mapStr(ClientAbilities.getStaticAbilities()); + protected Map initCurrentNodeAbilities() { + return ClientAbilities.getStaticAbilities(); } @Override diff --git a/client/src/test/java/com/alibaba/nacos/client/ability/AbilityTest.java b/client/src/test/java/com/alibaba/nacos/client/ability/AbilityTest.java index 75ca686d4..e4b53de10 100644 --- a/client/src/test/java/com/alibaba/nacos/client/ability/AbilityTest.java +++ b/client/src/test/java/com/alibaba/nacos/client/ability/AbilityTest.java @@ -98,8 +98,8 @@ public class AbilityTest { { super.abilityTable = new HashMap<>(); - super.abilityTable.put(AbilityKey.TEST_1.getName(), true); - super.abilityTable.put(AbilityKey.TEST_2.getName(), false); + super.abilityTable.put(AbilityKey.SERVER_TEST_1.getName(), true); + super.abilityTable.put(AbilityKey.SERVER_TEST_2.getName(), false); } @Override @@ -127,7 +127,7 @@ public class AbilityTest { }; rpcClient.start(); // test not ready - Assert.assertNull(rpcClient.getConnectionAbility(AbilityKey.TEST_1)); + Assert.assertNull(rpcClient.getConnectionAbility(AbilityKey.SERVER_TEST_1)); // test ready rpcClient.serverListFactory(new ServerListFactory() { @@ -149,23 +149,23 @@ public class AbilityTest { }); rpcClient.start(); // if connect successfully - Assert.assertEquals(rpcClient.getConnectionAbility(AbilityKey.TEST_1), AbilityStatus.SUPPORTED); - Assert.assertEquals(rpcClient.getConnectionAbility(AbilityKey.TEST_2), AbilityStatus.NOT_SUPPORTED); + Assert.assertEquals(rpcClient.getConnectionAbility(AbilityKey.SERVER_TEST_1), AbilityStatus.SUPPORTED); + Assert.assertEquals(rpcClient.getConnectionAbility(AbilityKey.SERVER_TEST_2), AbilityStatus.NOT_SUPPORTED); } @After public void testServerRequestAbility() { //test support ServerRequestHandler serverRequestHandler = (request, connection) -> { - Assert.assertEquals(connection.getConnectionAbility(AbilityKey.TEST_1), AbilityStatus.SUPPORTED); - Assert.assertEquals(connection.getConnectionAbility(AbilityKey.TEST_2), AbilityStatus.NOT_SUPPORTED); + Assert.assertEquals(connection.getConnectionAbility(AbilityKey.SERVER_TEST_1), AbilityStatus.SUPPORTED); + Assert.assertEquals(connection.getConnectionAbility(AbilityKey.SERVER_TEST_2), AbilityStatus.NOT_SUPPORTED); return new Response() { }; }; serverRequestHandler.requestReply(null, connection); // test no ability table serverRequestHandler = (request, connection) -> { - Assert.assertEquals(connection.getConnectionAbility(AbilityKey.TEST_1), AbilityStatus.UNKNOWN); + Assert.assertEquals(connection.getConnectionAbility(AbilityKey.SERVER_TEST_1), AbilityStatus.UNKNOWN); return new Response() { }; }; serverRequestHandler.requestReply(null, new TestConnection(new RpcClient.ServerInfo())); diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java index a501145cb..aa4036509 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java @@ -17,12 +17,14 @@ package com.alibaba.nacos.common.ability; import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.initializer.AbilityPostProcessor; import com.alibaba.nacos.api.ability.register.AbstractAbilityRegistry; import com.alibaba.nacos.common.JustForTest; import com.alibaba.nacos.common.ability.handler.HandlerMapping; import com.alibaba.nacos.common.executor.ExecutorFactory; import com.alibaba.nacos.common.notify.Event; import com.alibaba.nacos.common.notify.NotifyCenter; +import com.alibaba.nacos.common.spi.NacosServiceLoader; import com.alibaba.nacos.common.utils.CollectionUtils; import com.alibaba.nacos.common.utils.MapUtil; import com.alibaba.nacos.common.utils.ThreadUtils; @@ -32,6 +34,7 @@ import org.slf4j.LoggerFactory; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Collection; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; @@ -41,9 +44,10 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; -/**. +/** + * It is a capability control center, manager current node abilities or other control. + * * @author Daydreamer - * @description It is a capability control center, manager current node abilities or other control. * @date 2022/7/12 19:18 **/ public abstract class AbstractAbilityControlManager { @@ -72,7 +76,23 @@ public abstract class AbstractAbilityControlManager { protected AbstractAbilityControlManager() { ThreadUtils.addShutdownHook(this::destroy); NotifyCenter.registerToPublisher(AbilityUpdateEvent.class, 16384); - currentRunningAbility.putAll(initCurrentNodeAbilities()); + currentRunningAbility.putAll(getAbilityTable()); + } + + /** + * initialize abilities. + * + * @return abilities + */ + private Map getAbilityTable() { + // get processors + Collection processors = NacosServiceLoader.load(AbilityPostProcessor.class); + Map abilities = initCurrentNodeAbilities(); + // get abilities + for (AbilityPostProcessor processor : processors) { + processor.process(abilities); + } + return AbilityKey.mapStr(abilities); } /**. @@ -110,7 +130,7 @@ public abstract class AbstractAbilityControlManager { * * @return current node abilities */ - protected abstract Map initCurrentNodeAbilities(); + protected abstract Map initCurrentNodeAbilities(); /**. * Return the abilities current node diff --git a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java index b42eaf9c8..67845d821 100644 --- a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java +++ b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java @@ -38,16 +38,16 @@ public class ServerAbilityControlManager extends AbstractAbilityControlManager { } @Override - protected Map initCurrentNodeAbilities() { + protected Map initCurrentNodeAbilities() { // static abilities - Map staticAbilities = AbilityKey.mapStr(ServerAbilities.getStaticAbilities()); + Map staticAbilities = ServerAbilities.getStaticAbilities(); // all function server can support - Set abilityKeys = staticAbilities.keySet(); - Map abilityTable = new HashMap<>(abilityKeys.size()); + Set abilityKeys = staticAbilities.keySet(); + Map abilityTable = new HashMap<>(abilityKeys.size()); // if not define in config, then load from ServerAbilities - Set unIncludedInConfig = new HashSet<>(); + Set unIncludedInConfig = new HashSet<>(); abilityKeys.forEach(abilityKey -> { - String key = AbilityConfigs.PREFIX + abilityKey; + String key = AbilityConfigs.PREFIX + abilityKey.getName(); try { Boolean property = EnvUtil.getProperty(key, Boolean.class); // if not null diff --git a/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java b/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java index 44180a7aa..f2ef1e523 100644 --- a/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java +++ b/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java @@ -17,6 +17,7 @@ package com.alibaba.nacos.core.ability; import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.constant.AbilityMode; import com.alibaba.nacos.common.ability.handler.HandlerMapping; import org.junit.Assert; import org.junit.Before; @@ -40,7 +41,7 @@ public class AbilityControlManagerTest { @Before public void inject() { Map newTable = new HashMap<>(); - newTable.put(AbilityKey.TEST_1.getName(), true); + newTable.put(AbilityKey.SERVER_TEST_1.getName(), true); serverAbilityControlManager.setCurrentSupportingAbility(newTable); } @@ -48,65 +49,65 @@ public class AbilityControlManagerTest { public void testComponent() throws InterruptedException { enabled = 0; // invoke enable() or disable() when registering - serverAbilityControlManager.registerComponent(AbilityKey.TEST_1, new TestHandlerMapping(), -1); + serverAbilityControlManager.registerComponent(AbilityKey.SERVER_TEST_1, new TestHandlerMapping(), -1); Assert.assertEquals(1, serverAbilityControlManager.handlerMappingCount()); - serverAbilityControlManager.enableCurrentNodeAbility(AbilityKey.TEST_1); + serverAbilityControlManager.enableCurrentNodeAbility(AbilityKey.SERVER_TEST_1); // wait for invoking handler asyn Thread.sleep(200L); // nothing happens if it has enabled Assert.assertEquals(enabled, 1); - Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); + Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_1)); // invoke disable() - serverAbilityControlManager.disableCurrentNodeAbility(AbilityKey.TEST_1); + serverAbilityControlManager.disableCurrentNodeAbility(AbilityKey.SERVER_TEST_1); // wait for invoking handler asyn Thread.sleep(200L); // disable will invoke handler Assert.assertEquals(enabled, 0); - Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); + Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_1)); - serverAbilityControlManager.disableCurrentNodeAbility(AbilityKey.TEST_1); + serverAbilityControlManager.disableCurrentNodeAbility(AbilityKey.SERVER_TEST_1); // wait for invoking handler asyn Thread.sleep(200L); // nothing to do because it has disable Assert.assertEquals(enabled, 0); - Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); + Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_1)); - serverAbilityControlManager.enableCurrentNodeAbility(AbilityKey.TEST_1); + serverAbilityControlManager.enableCurrentNodeAbility(AbilityKey.SERVER_TEST_1); // wait for invoking handler asyn Thread.sleep(200L); Assert.assertEquals(enabled, 1); - Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); + Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_1)); - serverAbilityControlManager.enableCurrentNodeAbility(AbilityKey.TEST_1); + serverAbilityControlManager.enableCurrentNodeAbility(AbilityKey.SERVER_TEST_1); // wait for invoking handler asyn Thread.sleep(200L); Assert.assertEquals(enabled, 1); - Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); + Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_1)); } @Test public void testCurrentNodeAbility() { Set keySet = serverAbilityControlManager.getCurrentNodeAbilities().keySet(); // diable all - keySet.forEach(key -> serverAbilityControlManager.disableCurrentNodeAbility(AbilityKey.getEnum(key))); + keySet.forEach(key -> serverAbilityControlManager.disableCurrentNodeAbility(AbilityKey.getEnum(AbilityMode.SERVER, key))); // get all keySet.forEach(key -> { - Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.getEnum(key))); + Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.getEnum(AbilityMode.SERVER, key))); }); // enable all - keySet.forEach(key -> serverAbilityControlManager.enableCurrentNodeAbility(AbilityKey.getEnum(key))); + keySet.forEach(key -> serverAbilityControlManager.enableCurrentNodeAbility(AbilityKey.getEnum(AbilityMode.SERVER, key))); // get all keySet.forEach(key -> { - Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.getEnum(key))); + Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.getEnum(AbilityMode.SERVER, key))); }); } @Test public void testPriority() throws InterruptedException { TestServerAbilityControlManager testClientAbilityControlManager = new TestServerAbilityControlManager(); - AbilityKey key = AbilityKey.TEST_1; + AbilityKey key = AbilityKey.SERVER_TEST_1; TestPriority handlerMapping1 = new TestPriority("1"); TestPriority handlerMapping2 = new TestPriority("2"); TestPriority handlerMapping3 = new TestPriority("3"); diff --git a/core/src/test/java/com/alibaba/nacos/core/ability/config/AbilityConfigsTest.java b/core/src/test/java/com/alibaba/nacos/core/ability/config/AbilityConfigsTest.java index d0da81084..ade83ecda 100644 --- a/core/src/test/java/com/alibaba/nacos/core/ability/config/AbilityConfigsTest.java +++ b/core/src/test/java/com/alibaba/nacos/core/ability/config/AbilityConfigsTest.java @@ -57,18 +57,18 @@ public class AbilityConfigsTest { EnvUtil.setEnvironment(environment); abilityConfigs = new TestAbilityConfig(); inject(abilityConfigs); - serverAbilityControlManager.enableCurrentNodeAbility(AbilityKey.TEST_1); - serverAbilityControlManager.enableCurrentNodeAbility(AbilityKey.TEST_2); - serverAbilityControlManager.registerComponent(AbilityKey.TEST_1, new TestHandler()); - serverAbilityControlManager.registerComponent(AbilityKey.TEST_2, new TestHandler()); + serverAbilityControlManager.enableCurrentNodeAbility(AbilityKey.SERVER_TEST_1); + serverAbilityControlManager.enableCurrentNodeAbility(AbilityKey.SERVER_TEST_2); + serverAbilityControlManager.registerComponent(AbilityKey.SERVER_TEST_1, new TestHandler()); + serverAbilityControlManager.registerComponent(AbilityKey.SERVER_TEST_2, new TestHandler()); // tmp is 2 now } void inject(AbilityConfigs abilityConfigs) { TestServerAbilityControlManager serverAbilityControlManager = new TestServerAbilityControlManager(); Map newTable = new HashMap<>(); - newTable.put(AbilityKey.TEST_1.getName(), true); - newTable.put(AbilityKey.TEST_2.getName(), true); + newTable.put(AbilityKey.SERVER_TEST_1.getName(), true); + newTable.put(AbilityKey.SERVER_TEST_2.getName(), true); serverAbilityControlManager.setCurrentSupportingAbility(newTable); abilityConfigs.setAbilityHandlerRegistry(serverAbilityControlManager); this.serverAbilityControlManager = serverAbilityControlManager; @@ -86,63 +86,63 @@ public class AbilityConfigsTest { instanceField.setAccessible(true); ServerAbilities serverAbilities = (ServerAbilities) instanceField.get(ServerAbilities.class); currentAbilities = (Map) abilitiesField.get(serverAbilities); - currentAbilities.put(AbilityKey.TEST_1, true); - currentAbilities.put(AbilityKey.TEST_2, true); + currentAbilities.put(AbilityKey.SERVER_TEST_1, true); + currentAbilities.put(AbilityKey.SERVER_TEST_2, true); } @Test public void testLoadAbilities() throws Exception { - environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.TEST_1.getName(), Boolean.TRUE.toString()); - environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.TEST_2.getName(), Boolean.FALSE.toString()); + environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.SERVER_TEST_1.getName(), Boolean.TRUE.toString()); + environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.SERVER_TEST_2.getName(), Boolean.FALSE.toString()); // test load fill(); ServerAbilityControlManager manager = new ServerAbilityControlManager(); // config has higher priority - Assert.assertTrue(manager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); - Assert.assertFalse(manager.isCurrentNodeAbilityRunning(AbilityKey.TEST_2)); + Assert.assertTrue(manager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_1)); + Assert.assertFalse(manager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_2)); // clear currentAbilities.clear(); } @Test public void testInit() { - Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); - Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_2)); + Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_1)); + Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_2)); } @Test public void testConfigChange() throws InterruptedException { // test no change - environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.TEST_1.getName(), Boolean.TRUE.toString()); - environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.TEST_2.getName(), Boolean.TRUE.toString()); + environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.SERVER_TEST_1.getName(), Boolean.TRUE.toString()); + environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.SERVER_TEST_2.getName(), Boolean.TRUE.toString()); abilityConfigs.onEvent(new ServerConfigChangeEvent()); - Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); - Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_2)); + Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_1)); + Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_2)); //wait for invoke Thread.sleep(100); Assert.assertEquals(tmp, 2); // test change - environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.TEST_1.getName(), Boolean.FALSE.toString()); + environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.SERVER_TEST_1.getName(), Boolean.FALSE.toString()); abilityConfigs.onEvent(new ServerConfigChangeEvent()); - Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); - Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_2)); + Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_1)); + Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_2)); //wait for invoke Thread.sleep(100); Assert.assertEquals(tmp, 1); - environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.TEST_1.getName(), Boolean.TRUE.toString()); + environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.SERVER_TEST_1.getName(), Boolean.TRUE.toString()); abilityConfigs.onEvent(new ServerConfigChangeEvent()); - Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); + Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_1)); //wait for invoke Thread.sleep(100); Assert.assertEquals(tmp, 2); - environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.TEST_1.getName(), Boolean.FALSE.toString()); - environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.TEST_2.getName(), Boolean.FALSE.toString()); + environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.SERVER_TEST_1.getName(), Boolean.FALSE.toString()); + environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.SERVER_TEST_2.getName(), Boolean.FALSE.toString()); abilityConfigs.onEvent(new ServerConfigChangeEvent()); - Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_1)); - Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.TEST_2)); + Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_1)); + Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_2)); //wait for invoke Thread.sleep(100); Assert.assertEquals(tmp, 0); diff --git a/core/src/test/java/com/alibaba/nacos/core/ability/config/TestAbilityConfig.java b/core/src/test/java/com/alibaba/nacos/core/ability/config/TestAbilityConfig.java index c0cbcea02..446d2630b 100644 --- a/core/src/test/java/com/alibaba/nacos/core/ability/config/TestAbilityConfig.java +++ b/core/src/test/java/com/alibaba/nacos/core/ability/config/TestAbilityConfig.java @@ -29,7 +29,7 @@ public class TestAbilityConfig extends AbilityConfigs { public TestAbilityConfig() { Set serverAbilityKeys = super.getServerAbilityKeys(); - serverAbilityKeys.add(AbilityKey.TEST_1); - serverAbilityKeys.add(AbilityKey.TEST_2); + serverAbilityKeys.add(AbilityKey.SERVER_TEST_1); + serverAbilityKeys.add(AbilityKey.SERVER_TEST_2); } } diff --git a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityDiscovery.java b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityDiscovery.java index 7dd60999e..bbd21257a 100644 --- a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityDiscovery.java +++ b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityDiscovery.java @@ -130,8 +130,8 @@ public class AbilityDiscovery { @Test public void testClientDiscovery() throws NacosException { // client judge ability - Assert.assertEquals(client.getConnectionAbility(AbilityKey.TEST_1), AbilityStatus.SUPPORTED); - Assert.assertEquals(client.getConnectionAbility(AbilityKey.TEST_2), AbilityStatus.NOT_SUPPORTED); + Assert.assertEquals(client.getConnectionAbility(AbilityKey.SERVER_TEST_1), AbilityStatus.SUPPORTED); + Assert.assertEquals(client.getConnectionAbility(AbilityKey.SERVER_TEST_2), AbilityStatus.NOT_SUPPORTED); } @Test @@ -157,8 +157,8 @@ public class AbilityDiscovery { client.registerServerRequestHandler(new ServerRequestHandler() { @Override public Response requestReply(Request request, Connection connection) { - if (connection.getConnectionAbility(AbilityKey.TEST_1).equals(AbilityStatus.SUPPORTED) && connection - .getConnectionAbility(AbilityKey.TEST_2).equals(AbilityStatus.NOT_SUPPORTED)) { + if (connection.getConnectionAbility(AbilityKey.SERVER_TEST_1).equals(AbilityStatus.SUPPORTED) && connection + .getConnectionAbility(AbilityKey.SERVER_TEST_2).equals(AbilityStatus.NOT_SUPPORTED)) { clientSuccess = true; } return new Response(){}; @@ -199,8 +199,8 @@ public class AbilityDiscovery { @Override public ConfigQueryResponse handle(ConfigQueryRequest request, RequestMeta meta) throws NacosException { - if (meta.getConnectionAbility(AbilityKey.TEST_1).equals(AbilityStatus.SUPPORTED) && meta - .getConnectionAbility(AbilityKey.TEST_2).equals(AbilityStatus.NOT_SUPPORTED)) { + if (meta.getConnectionAbility(AbilityKey.SERVER_TEST_1).equals(AbilityStatus.SUPPORTED) && meta + .getConnectionAbility(AbilityKey.SERVER_TEST_2).equals(AbilityStatus.NOT_SUPPORTED)) { serverSuccess = true; } return new ConfigQueryResponse(); diff --git a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/component/TestServerAbilityControlManager.java b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/component/TestServerAbilityControlManager.java index 4620977fa..b1f58f3eb 100644 --- a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/component/TestServerAbilityControlManager.java +++ b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/component/TestServerAbilityControlManager.java @@ -9,10 +9,10 @@ import java.util.Map; public class TestServerAbilityControlManager extends ServerAbilityControlManager { @Override - protected Map initCurrentNodeAbilities() { - Map map = new HashMap<>(); - map.put(AbilityKey.TEST_1.getName(), true); - map.put(AbilityKey.TEST_2.getName(), false); + protected Map initCurrentNodeAbilities() { + Map map = new HashMap<>(); + map.put(AbilityKey.SERVER_TEST_1, true); + map.put(AbilityKey.SERVER_TEST_2, false); return map; } } From 41a3f13a66e3215a223bd94784784c5ea5c5746c Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Mon, 25 Sep 2023 14:33:20 +0800 Subject: [PATCH 50/55] remove HandlerMapping.java and ability change call back --- .../AbstractAbilityControlManager.java | 279 ++---------------- .../ability/handler/HandlerMapping.java | 41 --- .../ability/AbilityControlManagerTest.java | 117 -------- .../TestServerAbilityControlManager.java | 17 -- .../ability/config/AbilityConfigsTest.java | 31 -- 5 files changed, 20 insertions(+), 465 deletions(-) delete mode 100644 common/src/main/java/com/alibaba/nacos/common/ability/handler/HandlerMapping.java diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java index aa4036509..ed346525f 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java @@ -18,31 +18,17 @@ package com.alibaba.nacos.common.ability; import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.ability.initializer.AbilityPostProcessor; -import com.alibaba.nacos.api.ability.register.AbstractAbilityRegistry; -import com.alibaba.nacos.common.JustForTest; -import com.alibaba.nacos.common.ability.handler.HandlerMapping; -import com.alibaba.nacos.common.executor.ExecutorFactory; import com.alibaba.nacos.common.notify.Event; import com.alibaba.nacos.common.notify.NotifyCenter; import com.alibaba.nacos.common.spi.NacosServiceLoader; -import com.alibaba.nacos.common.utils.CollectionUtils; -import com.alibaba.nacos.common.utils.MapUtil; import com.alibaba.nacos.common.utils.ThreadUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Collections; -import java.util.List; import java.util.Map; import java.util.Collection; -import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.Executor; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; /** * It is a capability control center, manager current node abilities or other control. @@ -54,25 +40,11 @@ public abstract class AbstractAbilityControlManager { private static final Logger LOGGER = LoggerFactory.getLogger(AbstractAbilityControlManager.class); - /**. - * These handlers will be invoked when the flag of ability change key: - * ability key from {@link com.alibaba.nacos.api.ability.constant.AbilityKey} value: - * components who want to be invoked if its interested ability turn on/off - */ - private final Map> handlerMappings = new ConcurrentHashMap<>(); - - /**. - * run for HandlerMapping - */ - private final Executor simpleThreadPool = ExecutorFactory.newSingleExecutorService(); - /**. * ability current node running */ protected final Map currentRunningAbility = new ConcurrentHashMap<>(); - private final ReentrantLock lockForHandlerMappings = new ReentrantLock(); - protected AbstractAbilityControlManager() { ThreadUtils.addShutdownHook(this::destroy); NotifyCenter.registerToPublisher(AbilityUpdateEvent.class, 16384); @@ -95,24 +67,32 @@ public abstract class AbstractAbilityControlManager { return AbilityKey.mapStr(abilities); } - /**. - * Turn on the ability whose key is

abilityKey

+ /** + * Turn on the ability whose key is

abilityKey

. * * @param abilityKey ability key{@link AbilityKey} - * @return if turn success */ - public boolean enableCurrentNodeAbility(AbilityKey abilityKey) { - return doTurn(true, abilityKey); + public void enableCurrentNodeAbility(AbilityKey abilityKey) { + doTurn(this.currentRunningAbility, abilityKey, true); + } + + protected void doTurn(Map abilities, AbilityKey key, boolean turn) { + abilities.put(key.getName(), turn); + // notify event + AbilityUpdateEvent abilityUpdateEvent = new AbilityUpdateEvent(); + abilityUpdateEvent.setTable(Collections.unmodifiableMap(currentRunningAbility)); + abilityUpdateEvent.isOn = turn; + abilityUpdateEvent.abilityKey = key; + NotifyCenter.publishEvent(abilityUpdateEvent); } - /**. - * Turn off the ability whose key is

abilityKey

{@link AbilityKey} + /** + * Turn off the ability whose key is

abilityKey

{@link AbilityKey}. * * @param abilityKey ability key - * @return if turn success */ - public boolean disableCurrentNodeAbility(AbilityKey abilityKey) { - return doTurn(false, abilityKey); + public void disableCurrentNodeAbility(AbilityKey abilityKey) { + doTurn(this.currentRunningAbility, abilityKey, false); } /**. @@ -141,78 +121,11 @@ public abstract class AbstractAbilityControlManager { return Collections.unmodifiableMap(currentRunningAbility); } - /**. - * Turn on/off the ability of current node - * - * @param isOn is on - * @param abilityKey ability key from {@link AbilityKey} - * @return if turn success - */ - private boolean doTurn(boolean isOn, AbilityKey abilityKey) { - Boolean isEnabled = currentRunningAbility.get(abilityKey.getName()); - // if not supporting this key - if (isEnabled == null) { - LOGGER.warn("[AbilityControlManager] Attempt to turn on/off a not existed ability!"); - return false; - } else if (isOn == isEnabled) { - // if already turn on/off - return true; - } - // turn on/off - currentRunningAbility.put(abilityKey.getName(), isOn); - // handler mappings - triggerHandlerMappingAsyn(abilityKey, isOn, this.handlerMappings); - // notify event - AbilityUpdateEvent abilityUpdateEvent = new AbilityUpdateEvent(); - abilityUpdateEvent.setTable(Collections.unmodifiableMap(currentRunningAbility)); - abilityUpdateEvent.isOn = isOn; - abilityUpdateEvent.abilityKey = abilityKey; - NotifyCenter.publishEvent(abilityUpdateEvent); - return true; - } - - /** - * Register the component which is managed by {@link AbstractAbilityControlManager}. if you are hoping that a - * component will be invoked when turn on/off the ability whose key is

abilityKey

. - * - * @param abilityKey component key. - * @param priority the higher the priority is, the faster it will be called. - * @param handlerMapping component instance. - */ - public void registerComponent(AbilityKey abilityKey, HandlerMapping handlerMapping, int priority) { - doRegisterComponent(abilityKey, handlerMapping, this.handlerMappings, lockForHandlerMappings, priority, currentRunningAbility); - } - - /**. - * Register component with the lowest priority - * - * @param abilityKey ability key - * @param handlerMapping handler - */ - public void registerComponent(AbilityKey abilityKey, HandlerMapping handlerMapping) { - registerComponent(abilityKey, handlerMapping, -1); - } - - /**. - * Remove the specific type handler for a certain ability - * - * @param abilityKey ability key - * @param handlerMappingClazz type - * @return the count of handlers are removed - */ - public int removeComponent(AbilityKey abilityKey, Class handlerMappingClazz) { - return doRemove(abilityKey, handlerMappingClazz, lockForHandlerMappings, handlerMappings); - } - /**. * Close */ public final void destroy() { LOGGER.warn("[DefaultAbilityControlManager] - Start destroying..."); - ((ThreadPoolExecutor) simpleThreadPool).shutdown(); - if (MapUtil.isNotEmpty(handlerMappings)) { - handlerMappings.keySet().forEach(key -> doTriggerSyn(key, false, handlerMappings)); - } // hook doDestroy(); LOGGER.warn("[DefaultAbilityControlManager] - Destruction of the end"); @@ -225,127 +138,6 @@ public abstract class AbstractAbilityControlManager { // for server ability manager } - /** - * Remove the component instance of

handlerMappingClazz

. - * - * @param abilityKey ability key from {@link AbstractAbilityRegistry} - * @param handlerMappingClazz implement of {@link HandlerMapping} - * @param lock lock for operation - * @param handlerMappingsMap handler collection map - * @return the count of components have removed - */ - protected int doRemove(AbilityKey abilityKey, Class handlerMappingClazz, Lock lock, - Map> handlerMappingsMap) { - List handlerMappings = handlerMappingsMap.get(abilityKey); - if (CollectionUtils.isEmpty(handlerMappings)) { - return 0; - } - lock.lock(); - try { - AtomicInteger count = new AtomicInteger(); - handlerMappings.removeIf(item -> { - if (item.handlerMapping.getClass().equals(handlerMappingClazz)) { - count.getAndIncrement(); - return true; - } - return false; - }); - return count.get(); - } finally { - lock.unlock(); - } - } - - public int removeAll(AbilityKey abilityKey) { - List remove = this.handlerMappings.remove(abilityKey); - return Optional.ofNullable(remove).orElse(Collections.emptyList()).size(); - } - - /**. - * Register the component into handlerMappings locking by lockForHandlerMappings to ensure concurrency security. - * - * @param abilityKey ability key - * @param handlerMapping component instance. - * @param handlerMappings container - * @param lockForHandlerMappings lock to ensure concurrency - * @param abilityTable behavioral basis of handler - */ - protected void doRegisterComponent(AbilityKey abilityKey, HandlerMapping handlerMapping, - Map> handlerMappings, Lock lockForHandlerMappings, - int priority, Map abilityTable) { - if (!currentRunningAbility.containsKey(abilityKey.getName())) { - LOGGER.warn("[AbilityHandlePostProcessor] Failed to register processor: {}, because illegal key!", - handlerMapping.getClass().getSimpleName()); - } - - // legal key - lockForHandlerMappings.lock(); - try { - List handlers = handlerMappings.getOrDefault(abilityKey, new CopyOnWriteArrayList<>()); - HandlerWithPriority handlerWithPriority = new HandlerWithPriority(handlerMapping, priority); - handlers.add(handlerWithPriority); - handlerMappings.put(abilityKey, handlers); - // choose behavior - // enable default - if (abilityTable.getOrDefault(abilityKey.getName(), false)) { - handlerMapping.enable(); - } else { - handlerMapping.disable(); - } - } catch (Exception e) { - e.printStackTrace(); - LOGGER.error("[DefaultAbilityControlManager] Fail to register handler: {}", handlerMapping.getClass().getSimpleName()); - } finally { - lockForHandlerMappings.unlock(); - LOGGER.info("[DefaultAbilityControlManager] Successfully registered processor: {}", - handlerMapping.getClass().getSimpleName()); - } - } - - /** - * Invoke componments which linked to ability key asyn. - * - * @param key ability key from {@link AbstractAbilityRegistry} - * @param isEnabled turn on/off - * @param handlerMappingsMap handler collection - */ - protected void triggerHandlerMappingAsyn(AbilityKey key, boolean isEnabled, - Map> handlerMappingsMap) { - simpleThreadPool.execute(() -> doTriggerSyn(key, isEnabled, handlerMappingsMap)); - } - - /** - * Invoke componments which linked to ability key syn. - * - * @param key ability key from {@link AbstractAbilityRegistry} - * @param isEnabled turn on/off - * @param handlerMappingsMap handler collection - */ - protected void doTriggerSyn(AbilityKey key, boolean isEnabled, - Map> handlerMappingsMap) { - List handlerWithPriorities = handlerMappingsMap.get(key); - // return if empty - if (CollectionUtils.isEmpty(handlerWithPriorities)) { - return; - } - Collections.sort(handlerWithPriorities); - // invoked all - handlerWithPriorities.forEach(handlerMappingWithPriorities -> { - // any error from current handler does not affect other handler - HandlerMapping handlerMapping = handlerMappingWithPriorities.handlerMapping; - try { - if (isEnabled) { - handlerMapping.enable(); - } else { - handlerMapping.disable(); - } - } catch (Throwable t) { - LOGGER.warn("[HandlerMapping] Failed to invoke {} :{}", handlerMapping.getClass().getSimpleName(), - t.getLocalizedMessage()); - } - }); - } - /** * A legal nacos application has a ability control manager. * If there are more than one, the one with higher priority is preferred @@ -353,40 +145,9 @@ public abstract class AbstractAbilityControlManager { * @return priority */ public abstract int getPriority(); - - @JustForTest - protected Map> handlerMapping() { - return this.handlerMappings; - } - + /** - * Support priority handler. - */ - protected class HandlerWithPriority implements Comparable { - - /**. - * Decorated - */ - public HandlerMapping handlerMapping; - - /**. - * the higher the priority, the faster it will be called - */ - public int priority; - - public HandlerWithPriority(HandlerMapping handlerMapping, int priority) { - this.handlerMapping = handlerMapping; - this.priority = priority; - } - - @Override - public int compareTo(HandlerWithPriority o) { - return o.priority - this.priority; - } - } - - /**. - * notify when current node ability changing + * notify when current node ability changing. */ public class AbilityUpdateEvent extends Event { diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/handler/HandlerMapping.java b/common/src/main/java/com/alibaba/nacos/common/ability/handler/HandlerMapping.java deleted file mode 100644 index e7623d5e0..000000000 --- a/common/src/main/java/com/alibaba/nacos/common/ability/handler/HandlerMapping.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 1999-2022 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.nacos.common.ability.handler; - -/**. - * @author Daydreamer - * @description This component will be invoked if the ability of current node is turned on/off. - * @date 2022/7/12 19:21 - **/ -public interface HandlerMapping { - - /**. - * It will be invoked in order to enable this component after update the - * ability table key to true - */ - default void enable() { - // Nothing to do! - } - - /**. - * It will be invoked in order to disable this component after update the - * ability table key to false - */ - default void disable() { - // Nothing to do! - } -} diff --git a/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java b/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java index f2ef1e523..2170a7fb8 100644 --- a/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java +++ b/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java @@ -18,14 +18,12 @@ package com.alibaba.nacos.core.ability; import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.ability.constant.AbilityMode; -import com.alibaba.nacos.common.ability.handler.HandlerMapping; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.springframework.boot.test.context.SpringBootTest; import java.util.HashMap; -import java.util.LinkedList; import java.util.Map; import java.util.Set; @@ -34,10 +32,6 @@ public class AbilityControlManagerTest { private TestServerAbilityControlManager serverAbilityControlManager = new TestServerAbilityControlManager(); - private volatile int enabled = 0; - - private volatile LinkedList testPriority = new LinkedList<>(); - @Before public void inject() { Map newTable = new HashMap<>(); @@ -45,48 +39,6 @@ public class AbilityControlManagerTest { serverAbilityControlManager.setCurrentSupportingAbility(newTable); } - @Test - public void testComponent() throws InterruptedException { - enabled = 0; - // invoke enable() or disable() when registering - serverAbilityControlManager.registerComponent(AbilityKey.SERVER_TEST_1, new TestHandlerMapping(), -1); - Assert.assertEquals(1, serverAbilityControlManager.handlerMappingCount()); - - serverAbilityControlManager.enableCurrentNodeAbility(AbilityKey.SERVER_TEST_1); - // wait for invoking handler asyn - Thread.sleep(200L); - // nothing happens if it has enabled - Assert.assertEquals(enabled, 1); - Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_1)); - - // invoke disable() - serverAbilityControlManager.disableCurrentNodeAbility(AbilityKey.SERVER_TEST_1); - // wait for invoking handler asyn - Thread.sleep(200L); - // disable will invoke handler - Assert.assertEquals(enabled, 0); - Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_1)); - - serverAbilityControlManager.disableCurrentNodeAbility(AbilityKey.SERVER_TEST_1); - // wait for invoking handler asyn - Thread.sleep(200L); - // nothing to do because it has disable - Assert.assertEquals(enabled, 0); - Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_1)); - - serverAbilityControlManager.enableCurrentNodeAbility(AbilityKey.SERVER_TEST_1); - // wait for invoking handler asyn - Thread.sleep(200L); - Assert.assertEquals(enabled, 1); - Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_1)); - - serverAbilityControlManager.enableCurrentNodeAbility(AbilityKey.SERVER_TEST_1); - // wait for invoking handler asyn - Thread.sleep(200L); - Assert.assertEquals(enabled, 1); - Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_1)); - } - @Test public void testCurrentNodeAbility() { Set keySet = serverAbilityControlManager.getCurrentNodeAbilities().keySet(); @@ -104,75 +56,6 @@ public class AbilityControlManagerTest { }); } - @Test - public void testPriority() throws InterruptedException { - TestServerAbilityControlManager testClientAbilityControlManager = new TestServerAbilityControlManager(); - AbilityKey key = AbilityKey.SERVER_TEST_1; - TestPriority handlerMapping1 = new TestPriority("1"); - TestPriority handlerMapping2 = new TestPriority("2"); - TestPriority handlerMapping3 = new TestPriority("3"); - // first one, invoke enable() - testClientAbilityControlManager.registerComponent(key, handlerMapping2, 128); - // last one, invoke enable() - testClientAbilityControlManager.registerComponent(key, handlerMapping3); - // second one, invoke enable() - testClientAbilityControlManager.registerComponent(key, handlerMapping1, 12); - // trigger - testClientAbilityControlManager.trigger(key); - Assert.assertEquals(3, testClientAbilityControlManager.getHandlerMapping(key).size()); - // wait for invoking - Thread.sleep(200L); - Assert.assertEquals("2", testPriority.poll()); - Assert.assertEquals("3", testPriority.poll()); - Assert.assertEquals("1", testPriority.poll()); - // here are priority - Assert.assertEquals("2", testPriority.poll()); - Assert.assertEquals("1", testPriority.poll()); - Assert.assertEquals("3", testPriority.poll()); - - // remove - testClientAbilityControlManager.registerComponent(key, new TestHandlerMapping(), -1); - Assert.assertEquals(4, testClientAbilityControlManager.getHandlerMapping(key).size()); - Assert.assertEquals(1, testClientAbilityControlManager.removeComponent(key, TestHandlerMapping.class)); - Assert.assertEquals(3, testClientAbilityControlManager.getHandlerMapping(key).size()); - testClientAbilityControlManager.removeAll(key); - Assert.assertNull(testClientAbilityControlManager.getHandlerMapping(key)); - } - - class TestPriority implements HandlerMapping { - - String mark; - - public TestPriority(String mark) { - // unique one - this.mark = mark.intern(); - } - - @Override - public void enable() { - testPriority.offer(mark); - } - - @Override - public void disable() { - testPriority.offer(mark); - } - } - - class TestHandlerMapping implements HandlerMapping { - - @Override - public void enable() { - enabled++; - } - - @Override - public void disable() { - enabled--; - } - - } - } diff --git a/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java b/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java index a3685bd79..798857f80 100644 --- a/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java +++ b/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java @@ -16,11 +16,9 @@ package com.alibaba.nacos.core.ability; -import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.common.JustForTest; import com.alibaba.nacos.core.ability.control.ServerAbilityControlManager; -import java.util.List; import java.util.Map; public class TestServerAbilityControlManager extends ServerAbilityControlManager { @@ -30,20 +28,5 @@ public class TestServerAbilityControlManager extends ServerAbilityControlManager currentRunningAbility.clear(); currentRunningAbility.putAll(ability); } - - @JustForTest - public int handlerMappingCount() { - return super.handlerMapping().size(); - } - - @JustForTest - public List getHandlerMapping(AbilityKey abilityKey) { - return super.handlerMapping().get(abilityKey); - } - - @JustForTest - public void trigger(AbilityKey abilityKey) { - triggerHandlerMappingAsyn(abilityKey, true, handlerMapping()); - } } diff --git a/core/src/test/java/com/alibaba/nacos/core/ability/config/AbilityConfigsTest.java b/core/src/test/java/com/alibaba/nacos/core/ability/config/AbilityConfigsTest.java index ade83ecda..eb182d28f 100644 --- a/core/src/test/java/com/alibaba/nacos/core/ability/config/AbilityConfigsTest.java +++ b/core/src/test/java/com/alibaba/nacos/core/ability/config/AbilityConfigsTest.java @@ -19,7 +19,6 @@ package com.alibaba.nacos.core.ability.config; import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.ability.register.AbstractAbilityRegistry; import com.alibaba.nacos.api.ability.register.impl.ServerAbilities; -import com.alibaba.nacos.common.ability.handler.HandlerMapping; import com.alibaba.nacos.common.event.ServerConfigChangeEvent; import com.alibaba.nacos.core.ability.TestServerAbilityControlManager; import com.alibaba.nacos.core.ability.control.ServerAbilityControlManager; @@ -45,8 +44,6 @@ public class AbilityConfigsTest { private TestAbilityConfig abilityConfigs; - private int tmp; - private ServerAbilityControlManager serverAbilityControlManager; private Map currentAbilities; @@ -59,9 +56,6 @@ public class AbilityConfigsTest { inject(abilityConfigs); serverAbilityControlManager.enableCurrentNodeAbility(AbilityKey.SERVER_TEST_1); serverAbilityControlManager.enableCurrentNodeAbility(AbilityKey.SERVER_TEST_2); - serverAbilityControlManager.registerComponent(AbilityKey.SERVER_TEST_1, new TestHandler()); - serverAbilityControlManager.registerComponent(AbilityKey.SERVER_TEST_2, new TestHandler()); - // tmp is 2 now } void inject(AbilityConfigs abilityConfigs) { @@ -118,47 +112,22 @@ public class AbilityConfigsTest { abilityConfigs.onEvent(new ServerConfigChangeEvent()); Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_1)); Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_2)); - //wait for invoke - Thread.sleep(100); - Assert.assertEquals(tmp, 2); // test change environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.SERVER_TEST_1.getName(), Boolean.FALSE.toString()); abilityConfigs.onEvent(new ServerConfigChangeEvent()); Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_1)); Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_2)); - //wait for invoke - Thread.sleep(100); - Assert.assertEquals(tmp, 1); environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.SERVER_TEST_1.getName(), Boolean.TRUE.toString()); abilityConfigs.onEvent(new ServerConfigChangeEvent()); Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_1)); - //wait for invoke - Thread.sleep(100); - Assert.assertEquals(tmp, 2); environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.SERVER_TEST_1.getName(), Boolean.FALSE.toString()); environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.SERVER_TEST_2.getName(), Boolean.FALSE.toString()); abilityConfigs.onEvent(new ServerConfigChangeEvent()); Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_1)); Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_2)); - //wait for invoke - Thread.sleep(100); - Assert.assertEquals(tmp, 0); - } - - class TestHandler implements HandlerMapping { - - @Override - public void enable() { - tmp++; - } - - @Override - public void disable() { - tmp--; - } } } From 6bce3bda7be450c5ea793f5e11d35b75aeb3fba6 Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Mon, 25 Sep 2023 14:44:47 +0800 Subject: [PATCH 51/55] add AbilityPostProcessor param to know abilities init detail, sdk client, server or cluster client --- .../api/ability/initializer/AbilityPostProcessor.java | 4 +++- .../client/ability/ClientAbilityControlManager.java | 8 +++++++- .../common/ability/AbstractAbilityControlManager.java | 11 ++++++++++- .../ability/control/ServerAbilityControlManager.java | 8 +++++++- 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/initializer/AbilityPostProcessor.java b/api/src/main/java/com/alibaba/nacos/api/ability/initializer/AbilityPostProcessor.java index bec04d6e4..078671ac2 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/initializer/AbilityPostProcessor.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/initializer/AbilityPostProcessor.java @@ -1,6 +1,7 @@ package com.alibaba.nacos.api.ability.initializer; import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.constant.AbilityMode; import java.util.Map; @@ -15,8 +16,9 @@ public interface AbilityPostProcessor { /** * process before loading by Ability Controller . * + * @param mode mode: sdk client, server or cluster client * @param abilities abilities */ - void process(Map abilities); + void process(AbilityMode mode, Map abilities); } diff --git a/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java b/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java index f1cb6cf7d..a47b9b87e 100644 --- a/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java +++ b/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java @@ -17,6 +17,7 @@ package com.alibaba.nacos.client.ability; import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.constant.AbilityMode; import com.alibaba.nacos.api.ability.register.impl.ClientAbilities; import com.alibaba.nacos.common.ability.AbstractAbilityControlManager; @@ -36,7 +37,12 @@ public class ClientAbilityControlManager extends AbstractAbilityControlManager { protected Map initCurrentNodeAbilities() { return ClientAbilities.getStaticAbilities(); } - + + @Override + protected AbilityMode initializeMode() { + return AbilityMode.SDK_CLIENT; + } + @Override public int getPriority() { // if server ability manager exist, you should choose the server one diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java index ed346525f..447d214ef 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java @@ -17,6 +17,7 @@ package com.alibaba.nacos.common.ability; import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.constant.AbilityMode; import com.alibaba.nacos.api.ability.initializer.AbilityPostProcessor; import com.alibaba.nacos.common.notify.Event; import com.alibaba.nacos.common.notify.NotifyCenter; @@ -60,9 +61,10 @@ public abstract class AbstractAbilityControlManager { // get processors Collection processors = NacosServiceLoader.load(AbilityPostProcessor.class); Map abilities = initCurrentNodeAbilities(); + AbilityMode mode = initializeMode(); // get abilities for (AbilityPostProcessor processor : processors) { - processor.process(abilities); + processor.process(mode, abilities); } return AbilityKey.mapStr(abilities); } @@ -111,6 +113,13 @@ public abstract class AbstractAbilityControlManager { * @return current node abilities */ protected abstract Map initCurrentNodeAbilities(); + + /** + * initialize mode. + * + * @return mode. + */ + protected abstract AbilityMode initializeMode(); /**. * Return the abilities current node diff --git a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java index 67845d821..99e3fbb12 100644 --- a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java +++ b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java @@ -17,6 +17,7 @@ package com.alibaba.nacos.core.ability.control; import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.constant.AbilityMode; import com.alibaba.nacos.api.ability.register.impl.ServerAbilities; import com.alibaba.nacos.common.ability.AbstractAbilityControlManager; import com.alibaba.nacos.core.ability.config.AbilityConfigs; @@ -65,7 +66,12 @@ public class ServerAbilityControlManager extends AbstractAbilityControlManager { unIncludedInConfig.forEach(abilityKey -> abilityTable.put(abilityKey, staticAbilities.get(abilityKey))); return abilityTable; } - + + @Override + protected AbilityMode initializeMode() { + return AbilityMode.SERVER; + } + @Override public int getPriority() { return 1; From cb70aaf3c760a0053801c338cbb640657e2d814c Mon Sep 17 00:00:00 2001 From: Daydreamer-ia <2296032269@qq.com> Date: Mon, 25 Sep 2023 19:24:44 +0800 Subject: [PATCH 52/55] refactor AbilityControlManager with multiple ability mode. --- .../register/impl/ClusterClientAbilities.java | 41 +++++++ ...Abilities.java => SdkClientAbilities.java} | 9 +- .../register/impl/ServerAbilities.java | 5 +- .../ability/ClientAbilityControlManager.java | 14 +-- .../AbstractAbilityControlManager.java | 112 ++++++++++-------- .../common/remote/client/grpc/GrpcClient.java | 12 +- .../remote/client/grpc/GrpcClusterClient.java | 6 + .../remote/client/grpc/GrpcSdkClient.java | 6 + .../remote/client/grpc/GrpcClientTest.java | 6 + .../remote/client/grpc/GrpcClientTlsTest.java | 18 +++ .../control/ServerAbilityControlManager.java | 31 ++++- .../listener/StartingApplicationListener.java | 1 - .../grpc/GrpcBiStreamRequestAcceptor.java | 3 +- .../ability/AbilityControlManagerTest.java | 7 +- .../TestServerAbilityControlManager.java | 5 +- .../ability/config/AbilityConfigsTest.java | 23 ++-- .../nacos/test/ability/AbilityDiscovery.java | 78 +++++++++++- .../TestServerAbilityControlManager.java | 17 ++- 18 files changed, 300 insertions(+), 94 deletions(-) create mode 100644 api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClusterClientAbilities.java rename api/src/main/java/com/alibaba/nacos/api/ability/register/impl/{ClientAbilities.java => SdkClientAbilities.java} (89%) diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClusterClientAbilities.java b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClusterClientAbilities.java new file mode 100644 index 000000000..76327a848 --- /dev/null +++ b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClusterClientAbilities.java @@ -0,0 +1,41 @@ +package com.alibaba.nacos.api.ability.register.impl; + +import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.register.AbstractAbilityRegistry; + +import java.util.Map; + +/** + * It is used to register cluster client abilities. + * + * @author Daydreamer + **/ +public class ClusterClientAbilities extends AbstractAbilityRegistry { + + private static final ClusterClientAbilities INSTANCE = new ClusterClientAbilities(); + + { + /* + * example: + * There is a function named "compression". + * The key is from

AbilityKey

, the value is whether turn on. + * + * You can add a new public field in

AbilityKey

like: + * DATA_COMPRESSION("compression", "description about this ability") + * + * And then you need to declare whether turn on in the ability table, you can: + * supportedAbilities.put(AbilityKey.DATA_COMPRESSION, true); means that current client support compression. + * + */ + // put ability here, which you want current client supports + } + + /** + * get static ability current cluster client supports. + * + * @return static ability + */ + public static Map getStaticAbilities() { + return INSTANCE.getSupportedAbilities(); + } +} diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/SdkClientAbilities.java similarity index 89% rename from api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java rename to api/src/main/java/com/alibaba/nacos/api/ability/register/impl/SdkClientAbilities.java index 669bd2ab3..cb306f11d 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClientAbilities.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/SdkClientAbilities.java @@ -21,14 +21,15 @@ import com.alibaba.nacos.api.ability.register.AbstractAbilityRegistry; import java.util.Map; -/**. +/** + * It is used to register client abilities. + * * @author Daydreamer - * @description It is used to register client abilities. * @date 2022/8/31 12:32 **/ -public class ClientAbilities extends AbstractAbilityRegistry { +public class SdkClientAbilities extends AbstractAbilityRegistry { - private static final ClientAbilities INSTANCE = new ClientAbilities(); + private static final SdkClientAbilities INSTANCE = new SdkClientAbilities(); { /* diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java index 456b9f906..2fa8f9693 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java @@ -21,9 +21,10 @@ import com.alibaba.nacos.api.ability.register.AbstractAbilityRegistry; import java.util.Map; -/**. +/** + * It is used to register server abilities. + * * @author Daydreamer - * @description It is used to register server abilities. * @date 2022/8/31 12:32 **/ public class ServerAbilities extends AbstractAbilityRegistry { diff --git a/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java b/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java index a47b9b87e..cdbae28e3 100644 --- a/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java +++ b/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java @@ -18,9 +18,10 @@ package com.alibaba.nacos.client.ability; import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.ability.constant.AbilityMode; -import com.alibaba.nacos.api.ability.register.impl.ClientAbilities; +import com.alibaba.nacos.api.ability.register.impl.SdkClientAbilities; import com.alibaba.nacos.common.ability.AbstractAbilityControlManager; +import java.util.HashMap; import java.util.Map; /**. @@ -34,13 +35,10 @@ public class ClientAbilityControlManager extends AbstractAbilityControlManager { } @Override - protected Map initCurrentNodeAbilities() { - return ClientAbilities.getStaticAbilities(); - } - - @Override - protected AbilityMode initializeMode() { - return AbilityMode.SDK_CLIENT; + protected Map> initCurrentNodeAbilities() { + Map> abilities = new HashMap<>(); + abilities.put(AbilityMode.SDK_CLIENT, SdkClientAbilities.getStaticAbilities()); + return abilities; } @Override diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java index 447d214ef..1ef0f3d81 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java @@ -18,17 +18,18 @@ package com.alibaba.nacos.common.ability; import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.ability.constant.AbilityMode; +import com.alibaba.nacos.api.ability.constant.AbilityStatus; import com.alibaba.nacos.api.ability.initializer.AbilityPostProcessor; import com.alibaba.nacos.common.notify.Event; import com.alibaba.nacos.common.notify.NotifyCenter; import com.alibaba.nacos.common.spi.NacosServiceLoader; -import com.alibaba.nacos.common.utils.ThreadUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Collections; import java.util.Map; import java.util.Collection; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; /** @@ -40,16 +41,15 @@ import java.util.concurrent.ConcurrentHashMap; public abstract class AbstractAbilityControlManager { private static final Logger LOGGER = LoggerFactory.getLogger(AbstractAbilityControlManager.class); - - /**. - * ability current node running + + /** + * current node support abilities. */ - protected final Map currentRunningAbility = new ConcurrentHashMap<>(); + protected final Map> currentNodeAbilities = new ConcurrentHashMap<>(); protected AbstractAbilityControlManager() { - ThreadUtils.addShutdownHook(this::destroy); NotifyCenter.registerToPublisher(AbilityUpdateEvent.class, 16384); - currentRunningAbility.putAll(getAbilityTable()); + initAbilityTable(); } /** @@ -57,16 +57,37 @@ public abstract class AbstractAbilityControlManager { * * @return abilities */ - private Map getAbilityTable() { + private void initAbilityTable() { + LOGGER.info("Ready to get current node abilities..."); // get processors - Collection processors = NacosServiceLoader.load(AbilityPostProcessor.class); - Map abilities = initCurrentNodeAbilities(); - AbilityMode mode = initializeMode(); + Map> abilities = initCurrentNodeAbilities(); // get abilities - for (AbilityPostProcessor processor : processors) { - processor.process(mode, abilities); + for (AbilityMode mode : AbilityMode.values()) { + Map abilitiesTable = abilities.get(mode); + if (abilitiesTable == null) { + continue; + } + // check whether exist error key + // check for developer + for (AbilityKey abilityKey : abilitiesTable.keySet()) { + if (!mode.equals(abilityKey.getMode())) { + LOGGER.error("You should not contain a other mode: {} in a specify mode: {} abilities set, error key: {}, please check again.", + abilityKey.getMode(), mode, abilityKey); + throw new IllegalStateException("Except mode: " + mode + " but " + abilityKey + " mode: " + abilityKey.getMode() + ", please check again."); + } + } + Collection processors = NacosServiceLoader.load(AbilityPostProcessor.class); + for (AbilityPostProcessor processor : processors) { + processor.process(mode, abilitiesTable); + } } - return AbilityKey.mapStr(abilities); + // init + Set abilityModes = abilities.keySet(); + LOGGER.info("Ready to initialize current node abilities, support modes: {}", abilityModes); + for (AbilityMode abilityMode : abilityModes) { + this.currentNodeAbilities.put(abilityMode, new ConcurrentHashMap<>(AbilityKey.mapStr(abilities.get(abilityMode)))); + } + LOGGER.info("Initialize current abilities finish..."); } /** @@ -75,14 +96,21 @@ public abstract class AbstractAbilityControlManager { * @param abilityKey ability key{@link AbilityKey} */ public void enableCurrentNodeAbility(AbilityKey abilityKey) { - doTurn(this.currentRunningAbility, abilityKey, true); + Map abilities = this.currentNodeAbilities.get(abilityKey.getMode()); + if (abilities != null) { + doTurn(abilities, abilityKey, true, abilityKey.getMode()); + } } - protected void doTurn(Map abilities, AbilityKey key, boolean turn) { + protected void doTurn(Map abilities, AbilityKey key, boolean turn, AbilityMode mode) { + if (!key.getMode().equals(mode)) { + throw new IllegalStateException("Except " + mode + " but " + key.getMode()); + } + LOGGER.info("Turn current node ability: {}, turn: {}", key, turn); abilities.put(key.getName(), turn); // notify event AbilityUpdateEvent abilityUpdateEvent = new AbilityUpdateEvent(); - abilityUpdateEvent.setTable(Collections.unmodifiableMap(currentRunningAbility)); + abilityUpdateEvent.setTable(Collections.unmodifiableMap(abilities)); abilityUpdateEvent.isOn = turn; abilityUpdateEvent.abilityKey = key; NotifyCenter.publishEvent(abilityUpdateEvent); @@ -94,7 +122,10 @@ public abstract class AbstractAbilityControlManager { * @param abilityKey ability key */ public void disableCurrentNodeAbility(AbilityKey abilityKey) { - doTurn(this.currentRunningAbility, abilityKey, false); + Map abilities = this.currentNodeAbilities.get(abilityKey.getMode()); + if (abilities != null) { + doTurn(abilities, abilityKey, false, abilityKey.getMode()); + } } /**. @@ -103,8 +134,15 @@ public abstract class AbstractAbilityControlManager { * @param abilityKey ability key from {@link AbilityKey} * @return whether support */ - public boolean isCurrentNodeAbilityRunning(AbilityKey abilityKey) { - return currentRunningAbility.getOrDefault(abilityKey.getName(), false); + public AbilityStatus isCurrentNodeAbilityRunning(AbilityKey abilityKey) { + Map abilities = currentNodeAbilities.get(abilityKey.getMode()); + if (abilities != null) { + Boolean support = abilities.get(abilityKey.getName()); + if (support != null) { + return support ? AbilityStatus.SUPPORTED : AbilityStatus.NOT_SUPPORTED; + } + } + return AbilityStatus.UNKNOWN; } /**. @@ -112,39 +150,19 @@ public abstract class AbstractAbilityControlManager { * * @return current node abilities */ - protected abstract Map initCurrentNodeAbilities(); - - /** - * initialize mode. - * - * @return mode. - */ - protected abstract AbilityMode initializeMode(); + protected abstract Map> initCurrentNodeAbilities(); /**. * Return the abilities current node * * @return current abilities */ - public Map getCurrentNodeAbilities() { - return Collections.unmodifiableMap(currentRunningAbility); - } - - /**. - * Close - */ - public final void destroy() { - LOGGER.warn("[DefaultAbilityControlManager] - Start destroying..."); - // hook - doDestroy(); - LOGGER.warn("[DefaultAbilityControlManager] - Destruction of the end"); - } - - /**. - * hook for subclass - */ - protected void doDestroy() { - // for server ability manager + public Map getCurrentNodeAbilities(AbilityMode mode) { + Map abilities = currentNodeAbilities.get(mode); + if (abilities != null) { + return Collections.unmodifiableMap(abilities); + } + return Collections.emptyMap(); } /** diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java index c4a96fccd..8047ce01a 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java @@ -16,6 +16,7 @@ package com.alibaba.nacos.common.remote.client.grpc; +import com.alibaba.nacos.api.ability.constant.AbilityMode; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.grpc.auto.BiRequestStreamGrpc; import com.alibaba.nacos.api.grpc.auto.Payload; @@ -62,9 +63,9 @@ import org.slf4j.LoggerFactory; import java.util.Map; import java.util.Optional; -import java.util.concurrent.CountDownLatch; import java.util.Arrays; import java.util.Properties; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -390,7 +391,7 @@ public abstract class GrpcClient extends RpcClient { conSetupRequest.setClientVersion(VersionUtils.getFullClientVersion()); conSetupRequest.setLabels(super.getLabels()); // set ability table - conSetupRequest.setAbilityTable(NacosAbilityManagerHolder.getInstance().getCurrentNodeAbilities()); + conSetupRequest.setAbilityTable(NacosAbilityManagerHolder.getInstance().getCurrentNodeAbilities(abilityMode())); conSetupRequest.setTenant(super.getTenant()); grpcConn.sendRequest(conSetupRequest); // wait for response @@ -413,6 +414,13 @@ public abstract class GrpcClient extends RpcClient { return null; } + /** + * ability mode: sdk client or cluster client. + * + * @return mode + */ + protected abstract AbilityMode abilityMode(); + @Override protected void afterReset(ConnectResetRequest request) { recAbilityContext.release(null); diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClusterClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClusterClient.java index 61f5b7649..7749f69b6 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClusterClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClusterClient.java @@ -16,6 +16,7 @@ package com.alibaba.nacos.common.remote.client.grpc; +import com.alibaba.nacos.api.ability.constant.AbilityMode; import com.alibaba.nacos.api.common.Constants; import com.alibaba.nacos.common.remote.client.RpcClientTlsConfig; @@ -75,6 +76,11 @@ public class GrpcClusterClient extends GrpcClient { super(name, threadPoolCoreSize, threadPoolMaxSize, labels, tlsConfig); } + @Override + protected AbilityMode abilityMode() { + return AbilityMode.CLUSTER_CLIENT; + } + @Override public int rpcPortOffset() { return Integer.parseInt(System.getProperty(GrpcConstants.NACOS_SERVER_GRPC_PORT_OFFSET_KEY, diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcSdkClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcSdkClient.java index 3b8f859e2..0ede2af6d 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcSdkClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcSdkClient.java @@ -16,6 +16,7 @@ package com.alibaba.nacos.common.remote.client.grpc; +import com.alibaba.nacos.api.ability.constant.AbilityMode; import com.alibaba.nacos.api.common.Constants; import com.alibaba.nacos.common.remote.client.RpcClientTlsConfig; @@ -65,6 +66,11 @@ public class GrpcSdkClient extends GrpcClient { super(name, threadPoolCoreSize, threadPoolMaxSize, labels, tlsConfig); } + @Override + protected AbilityMode abilityMode() { + return AbilityMode.SDK_CLIENT; + } + /** * constructor. * diff --git a/common/src/test/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClientTest.java b/common/src/test/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClientTest.java index 246952dda..c3f8bf8ed 100644 --- a/common/src/test/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClientTest.java +++ b/common/src/test/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClientTest.java @@ -16,6 +16,7 @@ package com.alibaba.nacos.common.remote.client.grpc; +import com.alibaba.nacos.api.ability.constant.AbilityMode; import com.alibaba.nacos.api.grpc.auto.RequestGrpc; import com.alibaba.nacos.common.remote.client.RpcClient; import com.alibaba.nacos.common.remote.client.RpcClientTlsConfig; @@ -70,6 +71,11 @@ public class GrpcClientTest { public void setUp() throws Exception { when(clientConfig.name()).thenReturn("testClient"); grpcClient = spy(new GrpcClient(clientConfig) { + @Override + protected AbilityMode abilityMode() { + return AbilityMode.SDK_CLIENT; + } + @Override public int rpcPortOffset() { return 1000; diff --git a/common/src/test/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClientTlsTest.java b/common/src/test/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClientTlsTest.java index 4a65577be..75397ae06 100644 --- a/common/src/test/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClientTlsTest.java +++ b/common/src/test/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClientTlsTest.java @@ -16,6 +16,7 @@ package com.alibaba.nacos.common.remote.client.grpc; +import com.alibaba.nacos.api.ability.constant.AbilityMode; import org.junit.Test; import static org.mockito.Mockito.when; @@ -33,6 +34,12 @@ public class GrpcClientTlsTest extends GrpcClientTest { when(clientConfig.tlsConfig()).thenReturn(tlsConfig); grpcClient = new GrpcClient(clientConfig) { + + @Override + protected AbilityMode abilityMode() { + return AbilityMode.SDK_CLIENT; + } + @Override public int rpcPortOffset() { return 1000; @@ -51,6 +58,12 @@ public class GrpcClientTlsTest extends GrpcClientTest { when(clientConfig.tlsConfig()).thenReturn(tlsConfig); grpcClient = new GrpcClient(clientConfig) { + + @Override + protected AbilityMode abilityMode() { + return AbilityMode.SDK_CLIENT; + } + @Override public int rpcPortOffset() { return 1000; @@ -72,6 +85,11 @@ public class GrpcClientTlsTest extends GrpcClientTest { when(clientConfig.name()).thenReturn("testClient"); when(clientConfig.tlsConfig()).thenReturn(tlsConfig); grpcClient = new GrpcClient(clientConfig) { + @Override + protected AbilityMode abilityMode() { + return AbilityMode.SDK_CLIENT; + } + @Override public int rpcPortOffset() { return 1000; diff --git a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java index 99e3fbb12..20b4ee32c 100644 --- a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java +++ b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java @@ -18,6 +18,8 @@ package com.alibaba.nacos.core.ability.control; import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.ability.constant.AbilityMode; +import com.alibaba.nacos.api.ability.register.impl.ClusterClientAbilities; +import com.alibaba.nacos.api.ability.register.impl.SdkClientAbilities; import com.alibaba.nacos.api.ability.register.impl.ServerAbilities; import com.alibaba.nacos.common.ability.AbstractAbilityControlManager; import com.alibaba.nacos.core.ability.config.AbilityConfigs; @@ -39,7 +41,13 @@ public class ServerAbilityControlManager extends AbstractAbilityControlManager { } @Override - protected Map initCurrentNodeAbilities() { + protected Map> initCurrentNodeAbilities() { + // init client abilities + Map> res = new HashMap<>(); + res.put(AbilityMode.CLUSTER_CLIENT, initClusterClientAbilities()); + res.put(AbilityMode.SDK_CLIENT, initSdkClientAbilities()); + + // init server abilities // static abilities Map staticAbilities = ServerAbilities.getStaticAbilities(); // all function server can support @@ -64,12 +72,25 @@ public class ServerAbilityControlManager extends AbstractAbilityControlManager { }); // load from ServerAbilities unIncludedInConfig.forEach(abilityKey -> abilityTable.put(abilityKey, staticAbilities.get(abilityKey))); - return abilityTable; + + res.put(AbilityMode.SERVER, abilityTable); + return res; } - @Override - protected AbilityMode initializeMode() { - return AbilityMode.SERVER; + /** + * init cluster client abilities. + */ + private Map initClusterClientAbilities() { + // static abilities + return ClusterClientAbilities.getStaticAbilities(); + } + + /** + * init sdk client abilities. + */ + private Map initSdkClientAbilities() { + // static abilities + return SdkClientAbilities.getStaticAbilities(); } @Override diff --git a/core/src/main/java/com/alibaba/nacos/core/listener/StartingApplicationListener.java b/core/src/main/java/com/alibaba/nacos/core/listener/StartingApplicationListener.java index 2ddacee91..19fe93a55 100644 --- a/core/src/main/java/com/alibaba/nacos/core/listener/StartingApplicationListener.java +++ b/core/src/main/java/com/alibaba/nacos/core/listener/StartingApplicationListener.java @@ -142,7 +142,6 @@ public class StartingApplicationListener implements NacosApplicationListener { ThreadPoolManager.shutdown(); WatchFileCenter.shutdown(); NotifyCenter.shutdown(); - NacosAbilityManagerHolder.getInstance().destroy(); closeExecutor(); diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java index d01420b62..526e8e70e 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java @@ -16,6 +16,7 @@ package com.alibaba.nacos.core.remote.grpc; +import com.alibaba.nacos.api.ability.constant.AbilityMode; import com.alibaba.nacos.api.common.Constants; import com.alibaba.nacos.api.grpc.auto.BiRequestStreamGrpc; import com.alibaba.nacos.api.grpc.auto.Payload; @@ -138,7 +139,7 @@ public class GrpcBiStreamRequestAcceptor extends BiRequestStreamGrpc.BiRequestSt } else { try { // finish register, tell client has set up successfully - connection.request(new SetupAckRequest(NacosAbilityManagerHolder.getInstance().getCurrentNodeAbilities()), 3000L); + connection.request(new SetupAckRequest(NacosAbilityManagerHolder.getInstance().getCurrentNodeAbilities(AbilityMode.SERVER)), 3000L); } catch (Exception e) { // nothing to do diff --git a/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java b/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java index 2170a7fb8..272bfe6d4 100644 --- a/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java +++ b/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java @@ -18,6 +18,7 @@ package com.alibaba.nacos.core.ability; import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.ability.constant.AbilityMode; +import com.alibaba.nacos.api.ability.constant.AbilityStatus; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -41,18 +42,18 @@ public class AbilityControlManagerTest { @Test public void testCurrentNodeAbility() { - Set keySet = serverAbilityControlManager.getCurrentNodeAbilities().keySet(); + Set keySet = serverAbilityControlManager.getCurrentNodeAbilities(AbilityMode.SERVER).keySet(); // diable all keySet.forEach(key -> serverAbilityControlManager.disableCurrentNodeAbility(AbilityKey.getEnum(AbilityMode.SERVER, key))); // get all keySet.forEach(key -> { - Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.getEnum(AbilityMode.SERVER, key))); + Assert.assertNotEquals(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.getEnum(AbilityMode.SERVER, key)), AbilityStatus.SUPPORTED); }); // enable all keySet.forEach(key -> serverAbilityControlManager.enableCurrentNodeAbility(AbilityKey.getEnum(AbilityMode.SERVER, key))); // get all keySet.forEach(key -> { - Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.getEnum(AbilityMode.SERVER, key))); + Assert.assertEquals(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.getEnum(AbilityMode.SERVER, key)), AbilityStatus.SUPPORTED); }); } diff --git a/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java b/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java index 798857f80..087b94ef1 100644 --- a/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java +++ b/core/src/test/java/com/alibaba/nacos/core/ability/TestServerAbilityControlManager.java @@ -16,6 +16,7 @@ package com.alibaba.nacos.core.ability; +import com.alibaba.nacos.api.ability.constant.AbilityMode; import com.alibaba.nacos.common.JustForTest; import com.alibaba.nacos.core.ability.control.ServerAbilityControlManager; @@ -25,8 +26,8 @@ public class TestServerAbilityControlManager extends ServerAbilityControlManager @JustForTest public void setCurrentSupportingAbility(Map ability) { - currentRunningAbility.clear(); - currentRunningAbility.putAll(ability); + currentNodeAbilities.get(AbilityMode.SERVER).clear(); + currentNodeAbilities.get(AbilityMode.SERVER).putAll(ability); } } diff --git a/core/src/test/java/com/alibaba/nacos/core/ability/config/AbilityConfigsTest.java b/core/src/test/java/com/alibaba/nacos/core/ability/config/AbilityConfigsTest.java index eb182d28f..ccca0bb2c 100644 --- a/core/src/test/java/com/alibaba/nacos/core/ability/config/AbilityConfigsTest.java +++ b/core/src/test/java/com/alibaba/nacos/core/ability/config/AbilityConfigsTest.java @@ -17,6 +17,7 @@ package com.alibaba.nacos.core.ability.config; import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.constant.AbilityStatus; import com.alibaba.nacos.api.ability.register.AbstractAbilityRegistry; import com.alibaba.nacos.api.ability.register.impl.ServerAbilities; import com.alibaba.nacos.common.event.ServerConfigChangeEvent; @@ -92,16 +93,16 @@ public class AbilityConfigsTest { fill(); ServerAbilityControlManager manager = new ServerAbilityControlManager(); // config has higher priority - Assert.assertTrue(manager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_1)); - Assert.assertFalse(manager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_2)); + Assert.assertEquals(manager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_1), AbilityStatus.SUPPORTED); + Assert.assertNotEquals(manager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_2), AbilityStatus.SUPPORTED); // clear currentAbilities.clear(); } @Test public void testInit() { - Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_1)); - Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_2)); + Assert.assertEquals(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_1), AbilityStatus.SUPPORTED); + Assert.assertEquals(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_2), AbilityStatus.SUPPORTED); } @Test @@ -110,24 +111,24 @@ public class AbilityConfigsTest { environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.SERVER_TEST_1.getName(), Boolean.TRUE.toString()); environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.SERVER_TEST_2.getName(), Boolean.TRUE.toString()); abilityConfigs.onEvent(new ServerConfigChangeEvent()); - Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_1)); - Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_2)); + Assert.assertEquals(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_1), AbilityStatus.SUPPORTED); + Assert.assertEquals(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_2), AbilityStatus.SUPPORTED); // test change environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.SERVER_TEST_1.getName(), Boolean.FALSE.toString()); abilityConfigs.onEvent(new ServerConfigChangeEvent()); - Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_1)); - Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_2)); + Assert.assertNotEquals(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_1), AbilityStatus.SUPPORTED); + Assert.assertEquals(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_2), AbilityStatus.SUPPORTED); environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.SERVER_TEST_1.getName(), Boolean.TRUE.toString()); abilityConfigs.onEvent(new ServerConfigChangeEvent()); - Assert.assertTrue(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_1)); + Assert.assertEquals(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_1), AbilityStatus.SUPPORTED); environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.SERVER_TEST_1.getName(), Boolean.FALSE.toString()); environment.setProperty(AbilityConfigs.PREFIX + AbilityKey.SERVER_TEST_2.getName(), Boolean.FALSE.toString()); abilityConfigs.onEvent(new ServerConfigChangeEvent()); - Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_1)); - Assert.assertFalse(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_2)); + Assert.assertNotEquals(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_1), AbilityStatus.SUPPORTED); + Assert.assertNotEquals(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_TEST_2), AbilityStatus.SUPPORTED); } } diff --git a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityDiscovery.java b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityDiscovery.java index bbd21257a..4e3252008 100644 --- a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityDiscovery.java +++ b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityDiscovery.java @@ -63,7 +63,9 @@ public class AbilityDiscovery { private ConnectionManager connectionManager; private RpcClient client; - + + private RpcClient clusterClient; + private ConfigService configService; private AbstractAbilityControlManager oldInstance; @@ -74,10 +76,14 @@ public class AbilityDiscovery { private volatile boolean serverSuccess = false; private volatile boolean clientSuccess = false; + + private volatile boolean clusterSuccess = false; private Field abstractAbilityControlManager; private Field registryHandlerFields; + + private Field serverReuqestHandlersField; private Field currentConnField; @@ -104,7 +110,11 @@ public class AbilityDiscovery { Properties properties = new Properties(); properties.put(PropertyKeyConst.SERVER_ADDR, "127.0.0.1:" + port); configService = NacosFactory.createConfigService(properties); - + + // server request handler + serverReuqestHandlersField = RpcClient.class.getDeclaredField("serverRequestHandlers"); + serverReuqestHandlersField.setAccessible(true); + // init client client = RpcClientFactory.createClient(UUID.randomUUID().toString(), ConnectionType.GRPC, new HashMap<>()); client.serverListFactory(new ServerListFactory() { @@ -125,6 +135,26 @@ public class AbilityDiscovery { }); // connect to server client.start(); + + clusterClient = RpcClientFactory.createClusterClient(UUID.randomUUID().toString(), ConnectionType.GRPC, new HashMap<>()); + clusterClient.serverListFactory(new ServerListFactory() { + @Override + public String genNextServer() { + return "127.0.0.1:" + port; + } + + @Override + public String getCurrentServer() { + return "127.0.0.1:" + port; + } + + @Override + public List getServerList() { + return Collections.singletonList("127.0.0.1:" + port); + } + }); + // connect to server + clusterClient.start(); } @Test @@ -153,6 +183,8 @@ public class AbilityDiscovery { @Test public void testClientJudge() throws Exception { + List handlers = (List) serverReuqestHandlersField.get(client); + handlers.clear(); // register client.registerServerRequestHandler(new ServerRequestHandler() { @Override @@ -164,7 +196,7 @@ public class AbilityDiscovery { return new Response(){}; } }); - + // get id Connection conn = (Connection) currentConnField.get(client); @@ -179,6 +211,23 @@ public class AbilityDiscovery { Thread.sleep(4000); Assert.assertTrue(clientSuccess); } + + @Test + public void testClusterClient() throws IllegalAccessException, NacosException, InterruptedException, NoSuchFieldException { + Map handlers = (Map) registryHandlerFields + .get(requestHandlerRegistry); + + // set handler + RequestHandler oldRequestHandler = handlers.remove(ConfigQueryRequest.class.getSimpleName()); + handlers.put(ConfigQueryRequest.class.getSimpleName(), new ClusterClientRequestHandler(filters)); + configService.getConfig("test", "DEFAULT_GROUP", 2000); + // wait server invoke + Thread.sleep(3000); + Assert.assertTrue(clusterSuccess); + // recover + handlers.remove(ConfigQueryRequest.class.getSimpleName()); + handlers.put(ConfigQueryRequest.class.getSimpleName(), oldRequestHandler); + } @After public void recover() throws IllegalAccessException, NacosException { @@ -199,11 +248,30 @@ public class AbilityDiscovery { @Override public ConfigQueryResponse handle(ConfigQueryRequest request, RequestMeta meta) throws NacosException { - if (meta.getConnectionAbility(AbilityKey.SERVER_TEST_1).equals(AbilityStatus.SUPPORTED) && meta - .getConnectionAbility(AbilityKey.SERVER_TEST_2).equals(AbilityStatus.NOT_SUPPORTED)) { + if (meta.getConnectionAbility(AbilityKey.SDK_CLIENT_TEST_1).equals(AbilityStatus.SUPPORTED)) { serverSuccess = true; } return new ConfigQueryResponse(); } } + + /** + * just to test ability. + */ + class ClusterClientRequestHandler extends RequestHandler { + + public ClusterClientRequestHandler(RequestFilters requestFilters) throws NoSuchFieldException, IllegalAccessException { + Field declaredField = RequestHandler.class.getDeclaredField("requestFilters"); + declaredField.setAccessible(true); + declaredField.set(this, requestFilters); + } + + @Override + public ConfigQueryResponse handle(ConfigQueryRequest request, RequestMeta meta) throws NacosException { + if (meta.getConnectionAbility(AbilityKey.CLUSTER_CLIENT_TEST_1).equals(AbilityStatus.SUPPORTED)) { + clusterSuccess = true; + } + return new ConfigQueryResponse(); + } + } } diff --git a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/component/TestServerAbilityControlManager.java b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/component/TestServerAbilityControlManager.java index b1f58f3eb..cba747a94 100644 --- a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/component/TestServerAbilityControlManager.java +++ b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/component/TestServerAbilityControlManager.java @@ -1,18 +1,29 @@ package com.alibaba.nacos.test.ability.component; import com.alibaba.nacos.api.ability.constant.AbilityKey; +import com.alibaba.nacos.api.ability.constant.AbilityMode; import com.alibaba.nacos.core.ability.control.ServerAbilityControlManager; import java.util.HashMap; import java.util.Map; public class TestServerAbilityControlManager extends ServerAbilityControlManager { - + @Override - protected Map initCurrentNodeAbilities() { + protected Map> initCurrentNodeAbilities() { Map map = new HashMap<>(); map.put(AbilityKey.SERVER_TEST_1, true); map.put(AbilityKey.SERVER_TEST_2, false); - return map; + HashMap res = new HashMap<>(); + res.put(AbilityMode.SERVER, map); + + Map map1 = new HashMap<>(); + map1.put(AbilityKey.SDK_CLIENT_TEST_1, true); + res.put(AbilityMode.SDK_CLIENT, map1); + + Map map2 = new HashMap<>(); + map2.put(AbilityKey.CLUSTER_CLIENT_TEST_1, true); + res.put(AbilityMode.CLUSTER_CLIENT, map2); + return res; } } From 4522cbcccb8c9c180d0763f62aacc9bc3f1392c0 Mon Sep 17 00:00:00 2001 From: KomachiSion Date: Thu, 28 Sep 2023 10:49:10 +0800 Subject: [PATCH 53/55] For checkstyle. --- .../api/ability/constant/AbilityKey.java | 22 +++-- .../api/ability/constant/AbilityMode.java | 16 ++++ .../initializer/AbilityPostProcessor.java | 16 ++++ .../register/impl/ClusterClientAbilities.java | 16 ++++ .../ability/ClientAbilityControlManager.java | 2 +- .../AbstractAbilityControlManager.java | 51 ++++++------ .../client/grpc/DefaultGrpcClientConfig.java | 81 ++++++++++--------- .../control/ServerAbilityControlManager.java | 2 +- .../listener/StartingApplicationListener.java | 13 ++- .../grpc/GrpcBiStreamRequestAcceptor.java | 10 ++- .../ability/AbilityControlManagerTest.java | 16 ++-- .../nacos/test/ability/AbilityDiscovery.java | 16 ++++ .../TestServerAbilityControlManager.java | 16 ++++ 13 files changed, 190 insertions(+), 87 deletions(-) diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java index c848a1db9..d77460cf3 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java @@ -24,19 +24,31 @@ import java.util.stream.Collectors; /** * Ability key constant. It is used to constrain the ability key.
- * Ensure that return value of {@link AbilityKey#getName()} is unique under one specify {@link AbilityMode}. + * Ensure that return value of {@link AbilityKey#getName()} is unique under one specify {@link AbilityMode}. * * @author Daydreamer * @date 2022/8/31 12:27 **/ public enum AbilityKey { - + + /** + * For Test temporarily. + */ SERVER_TEST_1("test_1", "just for junit test", AbilityMode.SERVER), - + + /** + * For Test temporarily. + */ SERVER_TEST_2("test_2", "just for junit test", AbilityMode.SERVER), - + + /** + * For Test temporarily. + */ SDK_CLIENT_TEST_1("test_1", "just for junit test", AbilityMode.SDK_CLIENT), - + + /** + * For Test temporarily. + */ CLUSTER_CLIENT_TEST_1("test_1", "just for junit test", AbilityMode.CLUSTER_CLIENT); /** diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityMode.java b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityMode.java index 518572b16..2355a48bf 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityMode.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityMode.java @@ -1,3 +1,19 @@ +/* + * Copyright 1999-2023 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.nacos.api.ability.constant; /** diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/initializer/AbilityPostProcessor.java b/api/src/main/java/com/alibaba/nacos/api/ability/initializer/AbilityPostProcessor.java index 078671ac2..667c21c58 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/initializer/AbilityPostProcessor.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/initializer/AbilityPostProcessor.java @@ -1,3 +1,19 @@ +/* + * Copyright 1999-2023 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.nacos.api.ability.initializer; import com.alibaba.nacos.api.ability.constant.AbilityKey; diff --git a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClusterClientAbilities.java b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClusterClientAbilities.java index 76327a848..b43f43dae 100644 --- a/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClusterClientAbilities.java +++ b/api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClusterClientAbilities.java @@ -1,3 +1,19 @@ +/* + * Copyright 1999-2023 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.nacos.api.ability.register.impl; import com.alibaba.nacos.api.ability.constant.AbilityKey; diff --git a/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java b/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java index cdbae28e3..05d8fef47 100644 --- a/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java +++ b/client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java @@ -36,7 +36,7 @@ public class ClientAbilityControlManager extends AbstractAbilityControlManager { @Override protected Map> initCurrentNodeAbilities() { - Map> abilities = new HashMap<>(); + Map> abilities = new HashMap<>(1); abilities.put(AbilityMode.SDK_CLIENT, SdkClientAbilities.getStaticAbilities()); return abilities; } diff --git a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java index 1ef0f3d81..7571f5f70 100644 --- a/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java +++ b/common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java @@ -26,9 +26,9 @@ import com.alibaba.nacos.common.spi.NacosServiceLoader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Collection; import java.util.Collections; import java.util.Map; -import java.util.Collection; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -41,7 +41,7 @@ import java.util.concurrent.ConcurrentHashMap; public abstract class AbstractAbilityControlManager { private static final Logger LOGGER = LoggerFactory.getLogger(AbstractAbilityControlManager.class); - + /** * current node support abilities. */ @@ -51,7 +51,7 @@ public abstract class AbstractAbilityControlManager { NotifyCenter.registerToPublisher(AbilityUpdateEvent.class, 16384); initAbilityTable(); } - + /** * initialize abilities. * @@ -71,9 +71,12 @@ public abstract class AbstractAbilityControlManager { // check for developer for (AbilityKey abilityKey : abilitiesTable.keySet()) { if (!mode.equals(abilityKey.getMode())) { - LOGGER.error("You should not contain a other mode: {} in a specify mode: {} abilities set, error key: {}, please check again.", + LOGGER.error( + "You should not contain a other mode: {} in a specify mode: {} abilities set, error key: {}, please check again.", abilityKey.getMode(), mode, abilityKey); - throw new IllegalStateException("Except mode: " + mode + " but " + abilityKey + " mode: " + abilityKey.getMode() + ", please check again."); + throw new IllegalStateException( + "Except mode: " + mode + " but " + abilityKey + " mode: " + abilityKey.getMode() + + ", please check again."); } } Collection processors = NacosServiceLoader.load(AbilityPostProcessor.class); @@ -85,7 +88,8 @@ public abstract class AbstractAbilityControlManager { Set abilityModes = abilities.keySet(); LOGGER.info("Ready to initialize current node abilities, support modes: {}", abilityModes); for (AbilityMode abilityMode : abilityModes) { - this.currentNodeAbilities.put(abilityMode, new ConcurrentHashMap<>(AbilityKey.mapStr(abilities.get(abilityMode)))); + this.currentNodeAbilities + .put(abilityMode, new ConcurrentHashMap<>(AbilityKey.mapStr(abilities.get(abilityMode)))); } LOGGER.info("Initialize current abilities finish..."); } @@ -101,7 +105,7 @@ public abstract class AbstractAbilityControlManager { doTurn(abilities, abilityKey, true, abilityKey.getMode()); } } - + protected void doTurn(Map abilities, AbilityKey key, boolean turn, AbilityMode mode) { if (!key.getMode().equals(mode)) { throw new IllegalStateException("Except " + mode + " but " + key.getMode()); @@ -128,8 +132,8 @@ public abstract class AbstractAbilityControlManager { } } - /**. - * Whether current node support + /** + * . Whether current node support * * @param abilityKey ability key from {@link AbilityKey} * @return whether support @@ -145,15 +149,15 @@ public abstract class AbstractAbilityControlManager { return AbilityStatus.UNKNOWN; } - /**. - * Init current node abilities + /** + * . Init current node abilities * * @return current node abilities */ protected abstract Map> initCurrentNodeAbilities(); - /**. - * Return the abilities current node + /** + * . Return the abilities current node * * @return current abilities */ @@ -166,13 +170,13 @@ public abstract class AbstractAbilityControlManager { } /** - * A legal nacos application has a ability control manager. - * If there are more than one, the one with higher priority is preferred + * A legal nacos application has a ability control manager. If there are more than one, the one with higher priority + * is preferred * * @return priority */ public abstract int getPriority(); - + /** * notify when current node ability changing. */ @@ -185,13 +189,14 @@ public abstract class AbstractAbilityControlManager { private boolean isOn; private Map table; - - private AbilityUpdateEvent(){} - + + private AbilityUpdateEvent() { + } + public Map getAbilityTable() { return table; } - + public void setTable(Map abilityTable) { this.table = abilityTable; } @@ -199,15 +204,15 @@ public abstract class AbstractAbilityControlManager { public AbilityKey getAbilityKey() { return abilityKey; } - + public void setAbilityKey(AbilityKey abilityKey) { this.abilityKey = abilityKey; } - + public boolean isOn() { return isOn; } - + public void setOn(boolean on) { isOn = on; } diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/DefaultGrpcClientConfig.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/DefaultGrpcClientConfig.java index a191081f9..fd44229af 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/DefaultGrpcClientConfig.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/DefaultGrpcClientConfig.java @@ -59,13 +59,13 @@ public class DefaultGrpcClientConfig implements GrpcClientConfig { private int healthCheckRetryTimes; private long healthCheckTimeOut; - + private long capabilityNegotiationTimeout; private Map labels; - + private RpcClientTlsConfig tlsConfig = new RpcClientTlsConfig(); - + /** * constructor. * @@ -92,7 +92,8 @@ public class DefaultGrpcClientConfig implements GrpcClientConfig { this.healthCheckTimeOut = loadLongConfig(GrpcConstants.GRPC_HEALTHCHECK_TIMEOUT, builder.healthCheckTimeOut); this.channelKeepAliveTimeout = loadLongConfig(GrpcConstants.GRPC_CHANNEL_KEEP_ALIVE_TIMEOUT, builder.channelKeepAliveTimeout); - this.capabilityNegotiationTimeout = loadLongConfig(GrpcConstants.GRPC_CHANNEL_CAPABILITY_NEGOTIATION_TIMEOUT, builder.capabilityNegotiationTimeout); + this.capabilityNegotiationTimeout = loadLongConfig(GrpcConstants.GRPC_CHANNEL_CAPABILITY_NEGOTIATION_TIMEOUT, + builder.capabilityNegotiationTimeout); this.labels = builder.labels; this.labels.put("tls.enable", "false"); if (Objects.nonNull(builder.tlsConfig)) { @@ -170,31 +171,31 @@ public class DefaultGrpcClientConfig implements GrpcClientConfig { public long channelKeepAliveTimeout() { return channelKeepAliveTimeout; } - + @Override public RpcClientTlsConfig tlsConfig() { return tlsConfig; } - + public void setTlsConfig(RpcClientTlsConfig tlsConfig) { this.tlsConfig = tlsConfig; } - + @Override public long capabilityNegotiationTimeout() { return this.capabilityNegotiationTimeout; } - + @Override public int healthCheckRetryTimes() { return healthCheckRetryTimes; } - + @Override public long healthCheckTimeOut() { return healthCheckTimeOut; } - + @Override public Map labels() { return this.labels; @@ -233,13 +234,13 @@ public class DefaultGrpcClientConfig implements GrpcClientConfig { private int healthCheckRetryTimes = 3; private long healthCheckTimeOut = 3000L; - + private long capabilityNegotiationTimeout = 5000L; private Map labels = new HashMap<>(); - + private RpcClientTlsConfig tlsConfig = new RpcClientTlsConfig(); - + private Builder() { } @@ -260,51 +261,51 @@ public class DefaultGrpcClientConfig implements GrpcClientConfig { this.timeOutMills = Long.parseLong(properties.getProperty(GrpcConstants.GRPC_TIMEOUT_MILLS)); } if (properties.contains(GrpcConstants.GRPC_CONNECT_KEEP_ALIVE_TIME)) { - this.connectionKeepAlive = Long.parseLong( - properties.getProperty(GrpcConstants.GRPC_CONNECT_KEEP_ALIVE_TIME)); + this.connectionKeepAlive = Long + .parseLong(properties.getProperty(GrpcConstants.GRPC_CONNECT_KEEP_ALIVE_TIME)); } if (properties.contains(GrpcConstants.GRPC_THREADPOOL_KEEPALIVETIME)) { - this.threadPoolKeepAlive = Long.parseLong( - properties.getProperty(GrpcConstants.GRPC_THREADPOOL_KEEPALIVETIME)); + this.threadPoolKeepAlive = Long + .parseLong(properties.getProperty(GrpcConstants.GRPC_THREADPOOL_KEEPALIVETIME)); } if (properties.contains(GrpcConstants.GRPC_THREADPOOL_CORE_SIZE)) { - this.threadPoolCoreSize = Integer.parseInt( - properties.getProperty(GrpcConstants.GRPC_THREADPOOL_CORE_SIZE)); + this.threadPoolCoreSize = Integer + .parseInt(properties.getProperty(GrpcConstants.GRPC_THREADPOOL_CORE_SIZE)); } if (properties.contains(GrpcConstants.GRPC_THREADPOOL_MAX_SIZE)) { - this.threadPoolMaxSize = Integer.parseInt( - properties.getProperty(GrpcConstants.GRPC_THREADPOOL_MAX_SIZE)); + this.threadPoolMaxSize = Integer + .parseInt(properties.getProperty(GrpcConstants.GRPC_THREADPOOL_MAX_SIZE)); } if (properties.contains(GrpcConstants.GRPC_SERVER_CHECK_TIMEOUT)) { - this.serverCheckTimeOut = Long.parseLong( - properties.getProperty(GrpcConstants.GRPC_SERVER_CHECK_TIMEOUT)); + this.serverCheckTimeOut = Long + .parseLong(properties.getProperty(GrpcConstants.GRPC_SERVER_CHECK_TIMEOUT)); } if (properties.contains(GrpcConstants.GRPC_QUEUESIZE)) { this.threadPoolQueueSize = Integer.parseInt(properties.getProperty(GrpcConstants.GRPC_QUEUESIZE)); } if (properties.contains(GrpcConstants.GRPC_MAX_INBOUND_MESSAGE_SIZE)) { - this.maxInboundMessageSize = Integer.parseInt( - properties.getProperty(GrpcConstants.GRPC_MAX_INBOUND_MESSAGE_SIZE)); + this.maxInboundMessageSize = Integer + .parseInt(properties.getProperty(GrpcConstants.GRPC_MAX_INBOUND_MESSAGE_SIZE)); } if (properties.contains(GrpcConstants.GRPC_CHANNEL_KEEP_ALIVE_TIME)) { - this.channelKeepAlive = Integer.parseInt( - properties.getProperty(GrpcConstants.GRPC_CHANNEL_KEEP_ALIVE_TIME)); + this.channelKeepAlive = Integer + .parseInt(properties.getProperty(GrpcConstants.GRPC_CHANNEL_KEEP_ALIVE_TIME)); } if (properties.contains(GrpcConstants.GRPC_CHANNEL_CAPABILITY_NEGOTIATION_TIMEOUT)) { - this.capabilityNegotiationTimeout = Integer.parseInt( - properties.getProperty(GrpcConstants.GRPC_CHANNEL_CAPABILITY_NEGOTIATION_TIMEOUT)); + this.capabilityNegotiationTimeout = Integer + .parseInt(properties.getProperty(GrpcConstants.GRPC_CHANNEL_CAPABILITY_NEGOTIATION_TIMEOUT)); } if (properties.contains(GrpcConstants.GRPC_HEALTHCHECK_RETRY_TIMES)) { - this.healthCheckRetryTimes = Integer.parseInt( - properties.getProperty(GrpcConstants.GRPC_HEALTHCHECK_RETRY_TIMES)); + this.healthCheckRetryTimes = Integer + .parseInt(properties.getProperty(GrpcConstants.GRPC_HEALTHCHECK_RETRY_TIMES)); } if (properties.contains(GrpcConstants.GRPC_HEALTHCHECK_TIMEOUT)) { - this.healthCheckTimeOut = Long.parseLong( - properties.getProperty(GrpcConstants.GRPC_HEALTHCHECK_TIMEOUT)); + this.healthCheckTimeOut = Long + .parseLong(properties.getProperty(GrpcConstants.GRPC_HEALTHCHECK_TIMEOUT)); } if (properties.contains(GrpcConstants.GRPC_CHANNEL_KEEP_ALIVE_TIMEOUT)) { - this.channelKeepAliveTimeout = Integer.parseInt( - properties.getProperty(GrpcConstants.GRPC_CHANNEL_KEEP_ALIVE_TIMEOUT)); + this.channelKeepAliveTimeout = Integer + .parseInt(properties.getProperty(GrpcConstants.GRPC_CHANNEL_KEEP_ALIVE_TIMEOUT)); } this.tlsConfig = RpcClientTlsConfig.properties(properties); return this; @@ -412,11 +413,11 @@ public class DefaultGrpcClientConfig implements GrpcClientConfig { this.channelKeepAliveTimeout = channelKeepAliveTimeout; return this; } - + public void setCapabilityNegotiationTimeout(long capabilityNegotiationTimeout) { this.capabilityNegotiationTimeout = capabilityNegotiationTimeout; } - + /** * set healthCheckRetryTimes. */ @@ -440,7 +441,7 @@ public class DefaultGrpcClientConfig implements GrpcClientConfig { this.labels.putAll(labels); return this; } - + /** * set tlsConfig. * @@ -451,7 +452,7 @@ public class DefaultGrpcClientConfig implements GrpcClientConfig { this.tlsConfig = tlsConfig; return this; } - + /** * build GrpcClientConfig. */ @@ -459,5 +460,5 @@ public class DefaultGrpcClientConfig implements GrpcClientConfig { return new DefaultGrpcClientConfig(this); } } - + } diff --git a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java index 20b4ee32c..fe467ff1d 100644 --- a/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java +++ b/core/src/main/java/com/alibaba/nacos/core/ability/control/ServerAbilityControlManager.java @@ -43,7 +43,7 @@ public class ServerAbilityControlManager extends AbstractAbilityControlManager { @Override protected Map> initCurrentNodeAbilities() { // init client abilities - Map> res = new HashMap<>(); + Map> res = new HashMap<>(2); res.put(AbilityMode.CLUSTER_CLIENT, initClusterClientAbilities()); res.put(AbilityMode.SDK_CLIENT, initSdkClientAbilities()); diff --git a/core/src/main/java/com/alibaba/nacos/core/listener/StartingApplicationListener.java b/core/src/main/java/com/alibaba/nacos/core/listener/StartingApplicationListener.java index 19fe93a55..fcc3faea9 100644 --- a/core/src/main/java/com/alibaba/nacos/core/listener/StartingApplicationListener.java +++ b/core/src/main/java/com/alibaba/nacos/core/listener/StartingApplicationListener.java @@ -18,12 +18,12 @@ package com.alibaba.nacos.core.listener; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.exception.runtime.NacosRuntimeException; -import com.alibaba.nacos.common.ability.discover.NacosAbilityManagerHolder; +import com.alibaba.nacos.common.event.ServerConfigChangeEvent; import com.alibaba.nacos.common.executor.ExecutorFactory; import com.alibaba.nacos.common.executor.NameThreadFactory; import com.alibaba.nacos.common.executor.ThreadPoolManager; import com.alibaba.nacos.common.notify.NotifyCenter; -import com.alibaba.nacos.common.event.ServerConfigChangeEvent; +import com.alibaba.nacos.common.utils.StringUtils; import com.alibaba.nacos.sys.env.EnvUtil; import com.alibaba.nacos.sys.file.FileChangeEvent; import com.alibaba.nacos.sys.file.FileWatcher; @@ -31,7 +31,6 @@ import com.alibaba.nacos.sys.file.WatchFileCenter; import com.alibaba.nacos.sys.utils.ApplicationUtils; import com.alibaba.nacos.sys.utils.DiskUtils; import com.alibaba.nacos.sys.utils.InetUtils; -import com.alibaba.nacos.common.utils.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.env.OriginTrackedMapPropertySource; @@ -116,12 +115,12 @@ public class StartingApplicationListener implements NacosApplicationListener { logStarting(); } - + @Override public void contextLoaded(ConfigurableApplicationContext context) { EnvUtil.customEnvironment(); } - + @Override public void started(ConfigurableApplicationContext context) { starting = false; @@ -237,8 +236,8 @@ public class StartingApplicationListener implements NacosApplicationListener { private void logStarting() { if (!EnvUtil.getStandaloneMode()) { - scheduledExecutorService = ExecutorFactory.newSingleScheduledExecutorService( - new NameThreadFactory("com.alibaba.nacos.core.nacos-starting")); + scheduledExecutorService = ExecutorFactory + .newSingleScheduledExecutorService(new NameThreadFactory("com.alibaba.nacos.core.nacos-starting")); scheduledExecutorService.scheduleWithFixedDelay(() -> { if (starting) { diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java index 526e8e70e..25af8c0a7 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.java @@ -110,12 +110,13 @@ public class GrpcBiStreamRequestAcceptor extends BiRequestStreamGrpc.BiRequestSt if (labels != null && labels.containsKey(Constants.APPNAME)) { appName = labels.get(Constants.APPNAME); } - + ConnectionMeta metaInfo = new ConnectionMeta(connectionId, payload.getMetadata().getClientIp(), remoteIp, remotePort, localPort, ConnectionType.GRPC.getType(), setUpRequest.getClientVersion(), appName, setUpRequest.getLabels()); metaInfo.setTenant(setUpRequest.getTenant()); - Connection connection = new GrpcConnection(metaInfo, responseObserver, GrpcServerConstants.CONTEXT_KEY_CHANNEL.get()); + Connection connection = new GrpcConnection(metaInfo, responseObserver, + GrpcServerConstants.CONTEXT_KEY_CHANNEL.get()); // null if supported if (setUpRequest.getAbilityTable() != null) { // map to table @@ -139,10 +140,11 @@ public class GrpcBiStreamRequestAcceptor extends BiRequestStreamGrpc.BiRequestSt } else { try { // finish register, tell client has set up successfully - connection.request(new SetupAckRequest(NacosAbilityManagerHolder.getInstance().getCurrentNodeAbilities(AbilityMode.SERVER)), 3000L); + connection.request(new SetupAckRequest(NacosAbilityManagerHolder.getInstance() + .getCurrentNodeAbilities(AbilityMode.SERVER)), 3000L); } catch (Exception e) { // nothing to do - + } } diff --git a/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java b/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java index 272bfe6d4..2ef69de74 100644 --- a/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java +++ b/core/src/test/java/com/alibaba/nacos/core/ability/AbilityControlManagerTest.java @@ -30,9 +30,9 @@ import java.util.Set; @SpringBootTest public class AbilityControlManagerTest { - + private TestServerAbilityControlManager serverAbilityControlManager = new TestServerAbilityControlManager(); - + @Before public void inject() { Map newTable = new HashMap<>(); @@ -44,16 +44,20 @@ public class AbilityControlManagerTest { public void testCurrentNodeAbility() { Set keySet = serverAbilityControlManager.getCurrentNodeAbilities(AbilityMode.SERVER).keySet(); // diable all - keySet.forEach(key -> serverAbilityControlManager.disableCurrentNodeAbility(AbilityKey.getEnum(AbilityMode.SERVER, key))); + keySet.forEach(key -> serverAbilityControlManager + .disableCurrentNodeAbility(AbilityKey.getEnum(AbilityMode.SERVER, key))); // get all keySet.forEach(key -> { - Assert.assertNotEquals(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.getEnum(AbilityMode.SERVER, key)), AbilityStatus.SUPPORTED); + Assert.assertNotEquals(serverAbilityControlManager + .isCurrentNodeAbilityRunning(AbilityKey.getEnum(AbilityMode.SERVER, key)), AbilityStatus.SUPPORTED); }); // enable all - keySet.forEach(key -> serverAbilityControlManager.enableCurrentNodeAbility(AbilityKey.getEnum(AbilityMode.SERVER, key))); + keySet.forEach(key -> serverAbilityControlManager + .enableCurrentNodeAbility(AbilityKey.getEnum(AbilityMode.SERVER, key))); // get all keySet.forEach(key -> { - Assert.assertEquals(serverAbilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.getEnum(AbilityMode.SERVER, key)), AbilityStatus.SUPPORTED); + Assert.assertEquals(serverAbilityControlManager + .isCurrentNodeAbilityRunning(AbilityKey.getEnum(AbilityMode.SERVER, key)), AbilityStatus.SUPPORTED); }); } diff --git a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityDiscovery.java b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityDiscovery.java index 4e3252008..22a711d1c 100644 --- a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityDiscovery.java +++ b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/AbilityDiscovery.java @@ -1,3 +1,19 @@ +/* + * Copyright 1999-2023 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.nacos.test.ability; import com.alibaba.nacos.Nacos; diff --git a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/component/TestServerAbilityControlManager.java b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/component/TestServerAbilityControlManager.java index cba747a94..fccc8b22a 100644 --- a/test/core-test/src/test/java/com/alibaba/nacos/test/ability/component/TestServerAbilityControlManager.java +++ b/test/core-test/src/test/java/com/alibaba/nacos/test/ability/component/TestServerAbilityControlManager.java @@ -1,3 +1,19 @@ +/* + * Copyright 1999-2023 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.nacos.test.ability.component; import com.alibaba.nacos.api.ability.constant.AbilityKey; From 40b46dba816bb1335fd064e6376d64b20c068914 Mon Sep 17 00:00:00 2001 From: KomachiSion Date: Thu, 28 Sep 2023 11:42:57 +0800 Subject: [PATCH 54/55] Revert invalid application.properties change. --- .../src/main/resources/application.properties | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/console/src/main/resources/application.properties b/console/src/main/resources/application.properties index 6d60e17dc..a3629d911 100644 --- a/console/src/main/resources/application.properties +++ b/console/src/main/resources/application.properties @@ -31,16 +31,16 @@ server.port=8848 #*************** Config Module Related Configurations ***************# ### Deprecated configuration property, it is recommended to use `spring.sql.init.platform` replaced. -spring.datasource.platform=mysql -nacos.plugin.datasource.log.enabled=true -spring.sql.init.platform=mysql -## Count of DB: -db.num=1 +# spring.datasource.platform=mysql +# nacos.plugin.datasource.log.enabled=true +#spring.sql.init.platform=mysql +### Count of DB: +# db.num=1 -## Connect URL of DB: -db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC -db.user=root -db.password=123456 +### Connect URL of DB: +# db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC +# db.user=nacos +# db.password=nacos ### the maximum retry times for push nacos.config.push.maxRetryTime=50 From 3cfe5e82f228c6a5082378eb174371091e60c94d Mon Sep 17 00:00:00 2001 From: KomachiSion Date: Thu, 28 Sep 2023 11:55:00 +0800 Subject: [PATCH 55/55] Fix server push is intercepted by SetupRequestHandler problem. --- .../alibaba/nacos/common/remote/client/grpc/GrpcClient.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java index 8047ce01a..923acc997 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java @@ -518,8 +518,9 @@ public abstract class GrpcClient extends RpcClient { SetupAckRequest setupAckRequest = (SetupAckRequest) request; // remove and count down recAbilityContext.release(setupAckRequest.getAbilityTable()); + return new SetupAckResponse(); } - return new SetupAckResponse(); + return null; } }