From 4a5bfc5f76e6dad08b4c0c9092ba7044793b8981 Mon Sep 17 00:00:00 2001 From: icanci Date: Mon, 30 Jan 2023 20:04:39 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=A2=E6=88=B7=E7=AB=AF=E8=B4=9F=E8=BD=BD?= =?UTF-8?q?=E5=9D=87=E8=A1=A1=E7=AE=97=E6=B3=95=E8=AE=BE=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cache/holder/RasRepositoryHolder.java | 55 ++++++++----- .../ConsistencyHashLoadBalancing.java | 34 ++++++++ .../FastestCallSpeedLoadBalancing.java | 32 ++++++++ .../loadbalancing/FirstLoadBalancing.java | 19 +++-- .../loadbalancing/InOrderLoadBalancing.java | 34 ++++++++ .../loadbalancing/LastLoadBalancing.java | 34 ++++++++ .../LeastFrequentlyUsedLoadBalancing.java | 32 ++++++++ .../LeastRecentlyUsedLoadBalancing.java | 32 ++++++++ .../cache/loadbalancing/LoadBalancing.java | 17 +++- .../loadbalancing/LoadBalancingCache.java | 2 +- .../loadbalancing/LoadBalancingSupport.java | 79 +++++++++++++++++++ .../loadbalancing/RandomLoadBalancing.java | 34 ++++++++ 12 files changed, 374 insertions(+), 30 deletions(-) create mode 100644 client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/ConsistencyHashLoadBalancing.java create mode 100644 client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/FastestCallSpeedLoadBalancing.java create mode 100644 client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/InOrderLoadBalancing.java create mode 100644 client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/LastLoadBalancing.java create mode 100644 client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/LeastFrequentlyUsedLoadBalancing.java create mode 100644 client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/LeastRecentlyUsedLoadBalancing.java create mode 100644 client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/LoadBalancingSupport.java create mode 100644 client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/RandomLoadBalancing.java diff --git a/client/src/main/java/cn/icanci/loopstack/ras/client/cache/holder/RasRepositoryHolder.java b/client/src/main/java/cn/icanci/loopstack/ras/client/cache/holder/RasRepositoryHolder.java index 1039fc9..eaff9d5 100644 --- a/client/src/main/java/cn/icanci/loopstack/ras/client/cache/holder/RasRepositoryHolder.java +++ b/client/src/main/java/cn/icanci/loopstack/ras/client/cache/holder/RasRepositoryHolder.java @@ -6,6 +6,7 @@ import cn.icanci.loopstack.api.client.Client; import cn.icanci.loopstack.api.client.http.HttpClientImpl; import cn.icanci.loopstack.lsi.common.result.R; import cn.icanci.loopstack.ras.client.cache.MetaCacheHolder; +import cn.icanci.loopstack.ras.client.cache.loadbalancing.LoadBalancingSupport; import cn.icanci.loopstack.ras.client.cache.model.ApplicationKey; import cn.icanci.loopstack.ras.client.cache.model.ApplicationValue; import cn.icanci.loopstack.ras.client.cache.model.ClientApplicationValue; @@ -23,14 +24,20 @@ import cn.icanci.loopstack.ras.common.socket.UriConstant; import io.netty.util.internal.ThrowableUtil; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.BeansException; import org.springframework.beans.factory.InitializingBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.core.annotation.Order; import org.springframework.stereotype.Service; import com.google.common.collect.Maps; @@ -39,28 +46,35 @@ import com.google.common.collect.Sets; /** * 客户端知晓的服务端信息 * - MetaCacheHolder 的写bean服务 + * - 优先加载 * * @author icanci * @since 1.0 Created in 2023/01/19 17:06 */ @Service -public class RasRepositoryHolder extends MetaCacheHolder implements InitializingBean { +@Order(100) +public class RasRepositoryHolder extends MetaCacheHolder implements InitializingBean, ApplicationContextAware { - private static final Logger logger = LoggerFactory.getLogger(RasRepositoryHolder.class); + private static final Logger logger = LoggerFactory.getLogger(RasRepositoryHolder.class); /** * http://{address}:port+UriConstant.ToClient.LOAD */ - private static final String LOAD_REQUEST_FORMAT = "http://%s:%s" + UriConstant.ToServer.LOAD; + private static final String LOAD_REQUEST_FORMAT = "http://%s:%s" + UriConstant.ToServer.LOAD; /** * 请求地址 */ - private static final String REQUEST_FORMAT = "http://%s:%s"; + private static final String REQUEST_FORMAT = "http://%s:%s"; /** * 客户端 */ - private static final Client CLIENT = HttpClientImpl.getInstance(); + private static final Client CLIENT = HttpClientImpl.getInstance(); + + /** + * 是否已经初始化加载 + */ + private static final AtomicBoolean INIT_REFRESHED = new AtomicBoolean(false); @Override public void afterPropertiesSet() throws Exception { @@ -70,6 +84,12 @@ public class RasRepositoryHolder extends MetaCacheHolder implements Initializing NamedNettyServerHandler.setRasRepositoryHolder(this); } + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + // inject + LoadBalancingSupport.setApplicationContext(applicationContext); + } + /** * 服务启动加载数据 */ @@ -126,7 +146,12 @@ public class RasRepositoryHolder extends MetaCacheHolder implements Initializing // 刷新客户端信息 refreshClientInfo(refresh.getClientApplications()); // 构建客户端请求路由算法 & 初始化请求算法逻辑 - initClientLoadBalance(); + if (!INIT_REFRESHED.get()) { + LoadBalancingSupport.initClientLoadBalance(); + INIT_REFRESHED.compareAndSet(false, true); + } + // 刷新逻辑 + LoadBalancingSupport.refreshClientLoadBalance(); } /** @@ -266,12 +291,6 @@ public class RasRepositoryHolder extends MetaCacheHolder implements Initializing return applicationValue; } - private void initClientLoadBalance() { - // 构建key - // 构建算子逻辑 - // 构建蚁群算法 - } - /** * 返回请求执行路由地址 * @@ -279,12 +298,12 @@ public class RasRepositoryHolder extends MetaCacheHolder implements Initializing * @return 返回请求地址 ip+port */ public String routingRequestAddress(String appId) { - // REQUEST_FORMAT - ClientApplicationValue clientApplicationValue = CLIENT_APPLICATION_MAP.get(appId); - if (clientApplicationValue == null) { - throw new ServiceNotFoundException("Service for appId: " + appId + " not found!"); + Optional optional = LoadBalancingSupport.route(appId); + if (optional.isPresent()) { + ApplicationValue applicationValue = optional.get(); + return String.format(REQUEST_FORMAT, applicationValue.getAddress(), applicationValue.getPort()); } - - return null; + throw new ServiceNotFoundException("Service for appId: " + appId + " not found!"); } + } diff --git a/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/ConsistencyHashLoadBalancing.java b/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/ConsistencyHashLoadBalancing.java new file mode 100644 index 0000000..4ba556a --- /dev/null +++ b/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/ConsistencyHashLoadBalancing.java @@ -0,0 +1,34 @@ +package cn.icanci.loopstack.ras.client.cache.loadbalancing; + +import cn.icanci.loopstack.ras.client.cache.model.ApplicationValue; +import cn.icanci.loopstack.ras.common.enums.LoadBalanceTypeEnum; + +import java.util.Optional; + +import org.springframework.stereotype.Service; + +/** + * 一致性hash负载均衡 + * + * @author icanci + * @since 1.0 Created in 2023/01/30 19:34 + */ +@Service +@LoadBalancingBean(LoadBalanceTypeEnum.CONSISTENCY_HASH) +public class ConsistencyHashLoadBalancing extends LoadBalancingCache implements LoadBalancing { + + @Override + public void init() { + + } + + @Override + public void refresh() { + + } + + @Override + public Optional route(String appId) { + return Optional.empty(); + } +} diff --git a/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/FastestCallSpeedLoadBalancing.java b/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/FastestCallSpeedLoadBalancing.java new file mode 100644 index 0000000..a99049b --- /dev/null +++ b/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/FastestCallSpeedLoadBalancing.java @@ -0,0 +1,32 @@ +package cn.icanci.loopstack.ras.client.cache.loadbalancing; + +import cn.icanci.loopstack.ras.client.cache.model.ApplicationValue; +import cn.icanci.loopstack.ras.common.enums.LoadBalanceTypeEnum; + +import java.util.Optional; + +import org.springframework.stereotype.Service; + +/** + * @author icanci + * @since 1.0 Created in 2023/01/30 19:36 + */ +@Service +@LoadBalancingBean(LoadBalanceTypeEnum.FASTEST_CALL_SPEED) +public class FastestCallSpeedLoadBalancing extends LoadBalancingCache implements LoadBalancing { + + @Override + public void init() { + + } + + @Override + public void refresh() { + + } + + @Override + public Optional route(String appId) { + return Optional.empty(); + } +} diff --git a/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/FirstLoadBalancing.java b/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/FirstLoadBalancing.java index 142482e..d330fc5 100644 --- a/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/FirstLoadBalancing.java +++ b/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/FirstLoadBalancing.java @@ -1,11 +1,9 @@ package cn.icanci.loopstack.ras.client.cache.loadbalancing; import cn.icanci.loopstack.ras.client.cache.model.ApplicationValue; -import cn.icanci.loopstack.ras.client.cache.model.ClientApplicationValue; import cn.icanci.loopstack.ras.common.enums.LoadBalanceTypeEnum; import java.util.Optional; -import java.util.Set; import org.springframework.stereotype.Service; @@ -20,12 +18,17 @@ import org.springframework.stereotype.Service; public class FirstLoadBalancing extends LoadBalancingCache implements LoadBalancing { @Override - public Optional route(ClientApplicationValue clientApplicationValue) { - if (clientApplicationValue == null) { - return Optional.empty(); - } - Set applicationValues = clientApplicationValue.getApplicationValues(); + public void init() { - return null; + } + + @Override + public void refresh() { + + } + + @Override + public Optional route(String appId) { + return Optional.empty(); } } diff --git a/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/InOrderLoadBalancing.java b/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/InOrderLoadBalancing.java new file mode 100644 index 0000000..8e4b8af --- /dev/null +++ b/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/InOrderLoadBalancing.java @@ -0,0 +1,34 @@ +package cn.icanci.loopstack.ras.client.cache.loadbalancing; + +import cn.icanci.loopstack.ras.client.cache.model.ApplicationValue; +import cn.icanci.loopstack.ras.common.enums.LoadBalanceTypeEnum; + +import java.util.Optional; + +import org.springframework.stereotype.Service; + +/** + * 负载均衡算法实现 + * + * @author icanci + * @since 1.0 Created in 2023/01/23 10:23 + */ +@Service +@LoadBalancingBean(LoadBalanceTypeEnum.IN_ORDER) +public class InOrderLoadBalancing extends LoadBalancingCache implements LoadBalancing { + + @Override + public void init() { + + } + + @Override + public void refresh() { + + } + + @Override + public Optional route(String appId) { + return Optional.empty(); + } +} diff --git a/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/LastLoadBalancing.java b/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/LastLoadBalancing.java new file mode 100644 index 0000000..404709f --- /dev/null +++ b/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/LastLoadBalancing.java @@ -0,0 +1,34 @@ +package cn.icanci.loopstack.ras.client.cache.loadbalancing; + +import cn.icanci.loopstack.ras.client.cache.model.ApplicationValue; +import cn.icanci.loopstack.ras.common.enums.LoadBalanceTypeEnum; + +import java.util.Optional; + +import org.springframework.stereotype.Service; + +/** + * 负载均衡算法实现 + * + * @author icanci + * @since 1.0 Created in 2023/01/23 10:23 + */ +@Service +@LoadBalancingBean(LoadBalanceTypeEnum.LAST) +public class LastLoadBalancing extends LoadBalancingCache implements LoadBalancing { + + @Override + public void init() { + + } + + @Override + public void refresh() { + + } + + @Override + public Optional route(String appId) { + return Optional.empty(); + } +} diff --git a/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/LeastFrequentlyUsedLoadBalancing.java b/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/LeastFrequentlyUsedLoadBalancing.java new file mode 100644 index 0000000..231513a --- /dev/null +++ b/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/LeastFrequentlyUsedLoadBalancing.java @@ -0,0 +1,32 @@ +package cn.icanci.loopstack.ras.client.cache.loadbalancing; + +import cn.icanci.loopstack.ras.client.cache.model.ApplicationValue; +import cn.icanci.loopstack.ras.common.enums.LoadBalanceTypeEnum; + +import java.util.Optional; + +import org.springframework.stereotype.Service; + +/** + * @author icanci + * @since 1.0 Created in 2023/01/30 19:36 + */ +@Service +@LoadBalancingBean(LoadBalanceTypeEnum.LEAST_FREQUENTLY_USED) +public class LeastFrequentlyUsedLoadBalancing extends LoadBalancingCache implements LoadBalancing { + + @Override + public void init() { + + } + + @Override + public void refresh() { + + } + + @Override + public Optional route(String appId) { + return Optional.empty(); + } +} diff --git a/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/LeastRecentlyUsedLoadBalancing.java b/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/LeastRecentlyUsedLoadBalancing.java new file mode 100644 index 0000000..0bf861e --- /dev/null +++ b/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/LeastRecentlyUsedLoadBalancing.java @@ -0,0 +1,32 @@ +package cn.icanci.loopstack.ras.client.cache.loadbalancing; + +import cn.icanci.loopstack.ras.client.cache.model.ApplicationValue; +import cn.icanci.loopstack.ras.common.enums.LoadBalanceTypeEnum; + +import java.util.Optional; + +import org.springframework.stereotype.Service; + +/** + * @author icanci + * @since 1.0 Created in 2023/01/30 19:36 + */ +@Service +@LoadBalancingBean(LoadBalanceTypeEnum.LEAST_RECENTLY_USED) +public class LeastRecentlyUsedLoadBalancing extends LoadBalancingCache implements LoadBalancing { + + @Override + public void init() { + + } + + @Override + public void refresh() { + + } + + @Override + public Optional route(String appId) { + return Optional.empty(); + } +} diff --git a/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/LoadBalancing.java b/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/LoadBalancing.java index 1ceabc0..fb29013 100644 --- a/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/LoadBalancing.java +++ b/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/LoadBalancing.java @@ -1,7 +1,6 @@ package cn.icanci.loopstack.ras.client.cache.loadbalancing; import cn.icanci.loopstack.ras.client.cache.model.ApplicationValue; -import cn.icanci.loopstack.ras.client.cache.model.ClientApplicationValue; import java.util.Optional; @@ -12,11 +11,23 @@ import java.util.Optional; * @since 1.0 Created in 2023/01/23 10:23 */ public interface LoadBalancing { + + /** + * 初始化路由表 + */ + void init(); + + /** + * 刷新路由表 + */ + void refresh(); + /** * 根据AppId路由到合适的 * - * @param clientApplicationValue 客户端服务值 + * @param appId appId * @return 返回目标实现 */ - Optional route(ClientApplicationValue clientApplicationValue); + Optional route(String appId); + } diff --git a/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/LoadBalancingCache.java b/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/LoadBalancingCache.java index 3262cf2..d9f3961 100644 --- a/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/LoadBalancingCache.java +++ b/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/LoadBalancingCache.java @@ -11,5 +11,5 @@ import cn.icanci.loopstack.ras.client.cache.MetaCacheHolder; * @since 1.0 Created in 2023/01/23 10:24 */ public abstract class LoadBalancingCache extends MetaCacheHolder { - // TODO 设计缓存的维度,方便执行和刷新 + } diff --git a/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/LoadBalancingSupport.java b/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/LoadBalancingSupport.java new file mode 100644 index 0000000..3d6352d --- /dev/null +++ b/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/LoadBalancingSupport.java @@ -0,0 +1,79 @@ +package cn.icanci.loopstack.ras.client.cache.loadbalancing; + +import cn.icanci.loopstack.ras.client.cache.MetaCacheHolder; +import cn.icanci.loopstack.ras.client.cache.model.ApplicationValue; +import cn.icanci.loopstack.ras.client.cache.model.ClientApplicationValue; +import cn.icanci.loopstack.ras.common.enums.LoadBalanceTypeEnum; + +import java.util.Collection; +import java.util.Map; +import java.util.Optional; + +import org.springframework.aop.support.AopUtils; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; + +import com.google.common.collect.Maps; + +/** + * 负载均衡算法实现Support + * 必须在RasRepositoryHolder之后加载 + * + * @author icanci + * @since 1.0 Created in 2023/01/23 10:23 + */ +public final class LoadBalancingSupport extends MetaCacheHolder { + + /** 执行存储单元 */ + private static final Map LB_REPOSITORY = Maps.newHashMap(); + + /** + * 初始化路由表 + */ + public static void initClientLoadBalance() { + for (LoadBalancing balancing : LB_REPOSITORY.values()) { + balancing.init(); + } + } + + /** + * 刷新路由表 + */ + public static void refreshClientLoadBalance() { + for (LoadBalancing balancing : LB_REPOSITORY.values()) { + balancing.refresh(); + } + } + + /** + * 路由 + * + * @param appId appId + * @return 返回路由结果 + */ + public static Optional route(String appId) { + // REQUEST_FORMAT + ClientApplicationValue clientApplicationValue = CLIENT_APPLICATION_MAP.get(appId); + if (clientApplicationValue == null) { + return Optional.empty(); + } + LoadBalanceTypeEnum loadBalanceType = clientApplicationValue.getLoadBalanceType(); + return LB_REPOSITORY.get(loadBalanceType).route(appId); + } + + /** + * 依赖bean进行注入 + * + * @param applicationContext applicationContext + * @throws BeansException BeansException + */ + public static void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + // LB_REPOSITORY + Map beansOfTypeMap = applicationContext.getBeansOfType(LoadBalancing.class); + Collection loadBalancings = beansOfTypeMap.values(); + for (LoadBalancing loadBalancing : loadBalancings) { + LoadBalancingBean loadBalancingBean = AopUtils.getTargetClass(loadBalancing).getAnnotation(LoadBalancingBean.class); + LB_REPOSITORY.put(loadBalancingBean.value(), loadBalancing); + } + } +} diff --git a/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/RandomLoadBalancing.java b/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/RandomLoadBalancing.java new file mode 100644 index 0000000..6fed5f8 --- /dev/null +++ b/client/src/main/java/cn/icanci/loopstack/ras/client/cache/loadbalancing/RandomLoadBalancing.java @@ -0,0 +1,34 @@ +package cn.icanci.loopstack.ras.client.cache.loadbalancing; + +import cn.icanci.loopstack.ras.client.cache.model.ApplicationValue; +import cn.icanci.loopstack.ras.common.enums.LoadBalanceTypeEnum; + +import java.util.Optional; + +import org.springframework.stereotype.Service; + +/** + * 负载均衡算法实现 + * + * @author icanci + * @since 1.0 Created in 2023/01/23 10:23 + */ +@Service +@LoadBalancingBean(LoadBalanceTypeEnum.RANDOM) +public class RandomLoadBalancing extends LoadBalancingCache implements LoadBalancing { + + @Override + public void init() { + + } + + @Override + public void refresh() { + + } + + @Override + public Optional route(String appId) { + return Optional.empty(); + } +} -- Gitee