Spring Cloud 基于 Nacos 本地优化负载均衡配置

青苗 青苗 | 414 | 2023-05-16

基于 Nacos 负载均衡本地优先处理策略

下面是处理本地优先负载均衡,未处理 nacos 集群优先,这部分代码主要也是用于本地调试,因此集群优化不在考虑范围采用默认随机策略。

@Slf4j
public class DevNacosLoadBalancer extends NacosLoadBalancer {
    private ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;
    private final String serviceId;

    public DevNacosLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider, String serviceId, NacosDiscoveryProperties nacosDiscoveryProperties) {
        super(serviceInstanceListSupplierProvider, serviceId, nacosDiscoveryProperties);
        this.serviceId = serviceId;
        this.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider;
    }

    @Override
    public Mono<Response<ServiceInstance>> choose(Request request) {
        ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider.getIfAvailable(NoopServiceInstanceListSupplier::new);
        return supplier.get().next().map(serviceInstances -> {
            if (serviceInstances.isEmpty()) {
                log.warn("No servers available for service: " + this.serviceId);
                return new EmptyResponse();
            }
            ServiceInstance chooseService = null;
            for (ServiceInstance serviceInstance : serviceInstances) {
                if (this.isLocalIp(serviceInstance.getHost())) {
                    log.debug("choose: {}, {}", serviceInstance.getHost(), serviceInstance.getServiceId());
                    chooseService = serviceInstance;
                    break;
                }
            }
            if (null == chooseService) {
                // 内置随机策略选择
                chooseService = NacosBalancer.getHostByRandomWeight3(serviceInstances);
            }
            return new DefaultResponse(chooseService);
        });
    }

    /**
     * 判断是否为本地 IP
     *
     * @param ip 待判断 IP
     * @return
     */
    public static boolean isLocalIp(String ip) {
        try {
            Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
            while (networkInterfaces.hasMoreElements()) {
                NetworkInterface ni = networkInterfaces.nextElement();
                Enumeration<InetAddress> e2 = ni.getInetAddresses();
                while (e2.hasMoreElements()) {
                    InetAddress ia = e2.nextElement();
                    if (ia instanceof Inet6Address) {
                        continue;
                    }
                    String address = ia.getHostAddress();
                    if (null != address && address.equals(ip)) {
                        return true;
                    }
                }
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }
        return false;
    }
}

本地优化负载均衡配置

需要通过注解@LoadBalancerClients注入自定义的负载均衡器,注解 @ConditionalOnDiscoveryEnabled启动负载均衡,也可以通过配置例如:spring.cloud.loadbalancer.nacos.enabled = true

@Configuration(proxyBeanMethods = false)
@ConditionalOnDiscoveryEnabled
@LoadBalancerClients(defaultConfiguration = LocalFirstLoadBalancerConfiguration.class)
public class LocalFirstLoadBalancerConfiguration {

    @Bean
    @Primary
    public ReactorLoadBalancer<ServiceInstance> nacosLoadBalancer(Environment environment,
                                                                  LoadBalancerClientFactory loadBalancerClientFactory,
                                                                  NacosDiscoveryProperties nacosDiscoveryProperties) {
        String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
        return new DevNacosLoadBalancer(loadBalancerClientFactory.getLazyProvider(name,
                ServiceInstanceListSupplier.class), name, nacosDiscoveryProperties);
    }
}
文章标签: SpringBoot
推荐指数:

真诚点赞 诚不我欺~

Spring Cloud 基于 Nacos 本地优化负载均衡配置

点赞 收藏 评论

关于作者

青苗
青苗

青苗幼儿园园长

等级 LV5

粉丝 20

获赞 47

经验 1182