SpringCloud Nacos 自定義負載均衡規則

import com.alibaba.cloud.nacos.ribbon.NacosServer; import com.alibaba.nacos.api.naming.pojo.Instance; import com.netflix.client.config.IClientConfig; import com.netflix.loadbalancer.*; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.commons.util.InetUtils; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; /** * @Author cherrishccl * @Date 2021/3/19 15:18 * @Version 1.0 * @Description 自定義負載均衡規則 * springcloud + nacos + openfeign * 包: com.netflix.ribbon:ribbon-loadbalancer, * com.netflix.ribbon:ribbon-core, * com.alibaba.cloud:spring-cloud-alibaba-nacos-discovery * */ @Slf4j @Configuration public class CustomizeLoadBalancerRule extends AbstractLoadBalancerRule implements InitializingBean { @Autowired private InetUtils inetUtils; /** 本機ip */ private String localIp = null; /** 重試次數 */ private final int TOTAL_RETRY = 10; // 輪詢 private final AtomicInteger nextIndex = new AtomicInteger(); @Override public void initWithNiwsConfig(IClientConfig iClientConfig) { log.info("ClientName: {}", iClientConfig.getClientName()); } /** * 可自定義負載均衡規則 * 參考 com.netflix.loadbalancer.RoundRobinRule * @param key * @return */ @Override public Server choose(Object key) { Server server = null; try { ILoadBalancer lb = getLoadBalancer(); // int retry = 0; while (server == null && retry++ < TOTAL_RETRY) { List<Server> reachableServers = lb.getReachableServers(); List<Server> allServers = lb.getAllServers(); int upCount = reachableServers.size(); int serverCount = allServers.size(); if (upCount == 0 || serverCount == 0) { log.warn("無可用服務: {}", lb); return null; } // 規則: 默認調用本機服務 Server localServer = null; for (Server server1 : reachableServers) { NacosServer nacosServer = (NacosServer) server1; Instance instance = nacosServer.getInstance(); String ip = instance.getIp(); if (ip.equals(localIp)) { if (server1.isAlive() && (server1.isReadyToServe())) { localServer = server1; //return server1; } } } // 如果本機服務存在, 則優先調用本機服務 if(null != localServer){ return localServer; } // 如果本機服務不存在, 則調用其他 int nextServerIndex = incrementAndGetModulo(serverCount); server = allServers.get(nextServerIndex); if (server == null) { /* Transient. */ Thread.yield(); continue; } if (server.isAlive() && (server.isReadyToServe())) { return server; } // Next. server = null; } if (retry >= TOTAL_RETRY) { log.warn("重試{}次, 仍無可用服務: {}", retry, lb); } } catch (Exception e) { log.error("rule error", e); throw new RuntimeException("rule error"); } return server; } @Override public void afterPropertiesSet() throws Exception { localIp = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress(); log.info("本機ip地址:{}", localIp); } @Profile({"dev"}) @Bean public IRule ribbonRule() { return new CustomizeLoadBalancerRule(); } /** * RoundRobinRule中的輪詢方法 * @param modulo * @return */ private int incrementAndGetModulo(int modulo) { for (;;) { int current = nextIndex.get(); int next = (current + 1) % modulo; if (nextIndex.compareAndSet(current, next) && current < modulo) { return current; } } } }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章