Nacos 自定义负载均衡,优先使用同IP服务(本地服务优先调用)

这篇具有很好参考价值的文章主要介绍了Nacos 自定义负载均衡,优先使用同IP服务(本地服务优先调用)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Nacos 自定义负载均衡,优先使用同IP服务

在微服务开发过程中,随着微服务数量越来越多,不可能将所有的微服务都在本地启用然后进行调试。最好的方式是需要调试那个服务就启动那个服务,所有的服务都使用开发Nacos,本地需要搭建nacos。

使用nacos在开发微服务的过程中,如果多人同时开发使用同一台服务就会导致服务调用错乱。也不知道自己的请求到达了那个服务。

如果在开发过程中,每个人都可以只调用自己的服务,那样调试代码就会很舒服。

鉴于以上问题,现有两种解决方案

方案一、使用nacos不同集群

每个开发都在配置文件中配置属于自己的集群,那么在进行调试代码时nacos会优先使用相同集群中的服务,如果同集群中服务找不到会返回其他集群中所有实例;这样每个人都只调用自己的服务,也能解决问题。但是会有多分配置文件。也不是太完美;

spring:
  cloud:
    loadbalancer.nacos.enabled: true
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
        group: dev
        # 指定集群的名称,每个人都有自己一份
        cluster-name: local

方案二、自定义nacos负载均衡机制

1、自定义nacos负载均衡器

自定义nacos服务加载机制,优先使用与本地同IP的服务。本地找不到则使用同集群,然后在使用其他集群服务

自定义负载均衡代码如下:


import cn.hutool.core.net.NetUtil;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.balancer.NacosBalancer;
import com.alibaba.nacos.client.naming.utils.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.DefaultResponse;
import org.springframework.cloud.client.loadbalancer.EmptyResponse;
import org.springframework.cloud.client.loadbalancer.Request;
import org.springframework.cloud.client.loadbalancer.Response;
import org.springframework.cloud.loadbalancer.core.NoopServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * nacos 本地服务优先负载均衡器
 */
public class NacosLocalFirstLoadBalancer implements ReactorServiceInstanceLoadBalancer {

    private static final Logger log = LoggerFactory.getLogger(NacosLocalFirstLoadBalancer.class);

    private final String serviceId;

    private ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;

    private final NacosDiscoveryProperties nacosDiscoveryProperties;

    private Set<String> localIps;

    public NacosLocalFirstLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider, String serviceId, NacosDiscoveryProperties nacosDiscoveryProperties) {
        this.serviceId = serviceId;
        this.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider;
        this.nacosDiscoveryProperties = nacosDiscoveryProperties;
        // 使用hutool 工具获取本机IP地址
        this.localIps = NetUtil.localIpv4s();
    }

    @Override
    public Mono<Response<ServiceInstance>> choose(Request request) {
        ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider
                .getIfAvailable(NoopServiceInstanceListSupplier::new);
        return supplier.get().next().map(this::getInstanceResponse);
    }

    /**
     * 优先获取与本地IP一致的服务,否则获取同一集群服务
     *
     * @param serviceInstances
     * @return
     */
    private Response<ServiceInstance> getInstanceResponse(
            List<ServiceInstance> serviceInstances) {
        if (serviceInstances.isEmpty()) {
            log.warn("No servers available for service: " + this.serviceId);
            return new EmptyResponse();
        }
        // 过滤与本机IP地址一样的服务实例
        if (!CollectionUtils.isEmpty(this.localIps)) {
            for (ServiceInstance instance : serviceInstances) {
                String host = instance.getHost();
                if (this.localIps.contains(host)) {
                    return new DefaultResponse(instance);
                }
            }
        }
        return this.getClusterInstanceResponse(serviceInstances);
    }

    /**
     * 同一集群下优先获取
     *
     * @param serviceInstances
     * @return
     */
    private Response<ServiceInstance> getClusterInstanceResponse(
            List<ServiceInstance> serviceInstances) {
        if (serviceInstances.isEmpty()) {
            log.warn("No servers available for service: " + this.serviceId);
            return new EmptyResponse();
        }

        try {
            String clusterName = this.nacosDiscoveryProperties.getClusterName();

            List<ServiceInstance> instancesToChoose = serviceInstances;
            if (StringUtils.isNotBlank(clusterName)) {
                List<ServiceInstance> sameClusterInstances = serviceInstances.stream()
                        .filter(serviceInstance -> {
                            String cluster = serviceInstance.getMetadata().get("nacos.cluster");
                            return StringUtils.equals(cluster, clusterName);
                        }).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(sameClusterInstances)) {
                    instancesToChoose = sameClusterInstances;
                }
            } else {
                log.warn(
                        "A cross-cluster call occurs,name = {}, clusterName = {}, instance = {}",
                        serviceId, clusterName, serviceInstances);
            }

            ServiceInstance instance = NacosBalancer.getHostByRandomWeight3(instancesToChoose);
            return new DefaultResponse(instance);
        } catch (Exception e) {
            log.warn("NacosLoadBalancer error", e);
            return null;
        }
    }
}


以上代码大部分来源于 com.alibaba.cloud.nacos.loadbalancer.NacosLoadBalancer 添加了本地优先过滤规则

2、注册自定义负载均衡器到LoadBalancerClients中

使用自定义负载均衡器覆盖默认配置

import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.loadbalancer.NacosLoadBalancerClientConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.env.Environment;

/**
 * nacos 负载均衡同IP 同区域有限
 */
@Configuration(proxyBeanMethods = false)
@ConditionalOnDiscoveryEnabled
// 这里引入 nacos 默认客户端配置,否则的话需要添加 配置 spring.cloud.loadbalancer.nacos.enabled = true
@Import(NacosLoadBalancerClientConfiguration.class)
public class NacosLocalFirstLoadBalancerClientConfiguration{
    private static final Logger log = LoggerFactory.getLogger(NacosLocalFirstLoadBalancerClientConfiguration.class);


    /**
     * 本地优先策略
     * @param environment 环境变量
     * @param loadBalancerClientFactory 工厂
     * @param nacosDiscoveryProperties 属性
     * @return ReactorLoadBalancer
     */
    @Bean
    @ConditionalOnProperty(value = "spring.cloud.loadbalancer.local-first", havingValue = "true")
    public ReactorLoadBalancer<ServiceInstance> nacosLocalFirstLoadBalancer(Environment environment,
                                                                  LoadBalancerClientFactory loadBalancerClientFactory,
                                                                  NacosDiscoveryProperties nacosDiscoveryProperties){
        String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
        if(log.isDebugEnabled()) {
            log.debug("Use nacos local first load balancer for {} service", name);
        }
        return new NacosLocalFirstLoadBalancer(
                loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class),
                name, nacosDiscoveryProperties);
    }
}

3、添加自动发现类

前两部代码不能直接添加到spring bean 中,否则在引用时获取不到请求服务名称,容易报空指针异常;

需要通过@LoadBalancerClients 注解注入自定义的负载均衡器

/**
 * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration
 * Auto-configuration} that sets up LoadBalancer for Nacos.
 */
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties
@ConditionalOnNacosDiscoveryEnabled
@LoadBalancerClients(defaultConfiguration = NacosLocalFirstLoadBalancerClientConfiguration.class)
public class LocalFirstLoadBalancerNacosAutoConfiguration {

}

4、如果需要自动装配

resources/META-INF/spring.factories

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.commmon.LocalFirstLoadBalancerNacosAutoConfiguration

经过上述配置之后,就可以在开发微服务中与同事一起调试代码了,也不会出现调用串了问题。文章来源地址https://www.toymoban.com/news/detail-804297.html

到了这里,关于Nacos 自定义负载均衡,优先使用同IP服务(本地服务优先调用)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Nacos服务治理—负载均衡

    在消费方引入负载均衡机制,同时简化获取服务提供者信息的流程 Spring Cloud引入组件LoadBalance实现负载均衡 添加依赖 properties配置 主类上添加对应的注解 定义对应的控制器,需要访问服务提供者 验证测试 缓存配置 使用LB从Nacos获取服务的注册信息,可以在本地进行缓存。添

    2024年02月13日
    浏览(34)
  • SpringCloud Alibaba(一)微服务简介+Nacos的安装部署与使用+Nacos集成springboot实现服务注册+Feign实现服务之间的远程调用+负载均衡+领域划分

    目录 一.认识微服务 1.0.学习目标 1.1.单体架构 单体架构的优缺点如下: 1.2.分布式架构 分布式架构的优缺点: 1.3.微服务 微服务的架构特征: 1.4.SpringCloud 1.5Nacos注册中心 1.6.总结 二、Nacos基本使用安装部署+服务注册 (一)linux安装包方式单节点安装部署 1. jdk安装配置 2. na

    2024年02月09日
    浏览(45)
  • Ribbon负载均衡+Nacos服务搭建

    首先通过RibbonLoadBalanceerClient获取服务名,并传给DynamicServerListLoadBalancer——通过EureKa-server获取服务名对应服务列表(也就是被注册到EureKa中的服务,可能包括不同端口的),然后我们会根据IRule中的服务负载均衡-选择某个服务,然后修改url发送请求; Ribbon的负载均衡是一个叫

    2024年02月10日
    浏览(36)
  • springCloudAlibaba组件-Nacos-服务发现与负载均衡(三)

    如果项目使用微服务架构,如果A微服务需要访问B微服务,需要http请求进行调用,当然需要B微服务的地址与端口号,微服务可以向之前提到的服务中心进行获取B服务的ip地址和端口号,这就是服务发现 1.客户端主动获取 客户端: 流程: 1.先是故障转移机制判断是否去本地文

    2024年02月10日
    浏览(41)
  • SpringCloud Alibaba集成 Gateway(自定义负载均衡器)、Nacos(配置中心、注册中心)、Loadbalancer

    路由(route):路由是网关最基础的部分,路由信息由一个ID,一个目的URL、一组断言工厂和一 组Filter组成。如果断言为真,则说明请求URL和配置的路由匹配。 断言(Predicate):Java8中的断言函数,Spring Cloud Gateway中的断言函数输入类型是 Spring5.0框架中的ServerWebExchange。Sprin

    2024年04月12日
    浏览(64)
  • 微服务技术栈-Ribbon负载均衡和Nacos注册中心

    在上面那个文章中介绍了微服务架构的概念以及eureka注册中心的概念,在本节中我们将继续介绍微服务技术栈的其他两个组件Ribbon和Nacos。 在上篇文章中讲到,Spring会自动帮助我们从eureka-server端,根据userservice这个服务名称,获取实例列表,而后完成负载均衡。 那么这个 负

    2024年02月07日
    浏览(40)
  • 【SpringCloud Alibaba】Nacos服务管理与Feign负载均衡

    目录 一、微服务搭建 1.1 服务提供者与服务消费者 1.2 依赖关系   二、服务注册与负载均衡使用 2.1 Nacos 实现服务的注册与发现 2.2 Loadbalancer负载均衡、Feign声明式服务调用 2.3 示例综合实现 2.3.1 服务注册与发现测试 2.3.2 负载均衡测试  服务提供者 服务的被调用方(即:为其他微

    2024年02月03日
    浏览(44)
  • 【微服务技术一】Eureka、Nacos、Ribbon(配置管理、注册中心、负载均衡)

    微服务完整的技术栈如图: 技术栈学习: 概念: 在Eureka架构中,微服务角色有两类EurekaServer: 服务端,注册中心 记录服务信息 心跳监控 EurekaClient:客户端 Provider:服务提供者,例如案例中的user-service注册自己的信息到EurekaServer;每隔30秒向EurekaServer发送心跳 consumer:服务消

    2024年02月12日
    浏览(46)
  • Spring Cloud Alibaba-02-Nacos Discovery服务治理及负载均衡

    Lison dreamlison@163.com , v1.0.0 , 2023.05.10 先来思考一个问题 通过上一章的操作,我们已经可以实现微服务之间的调用。但是我们把服务提供者的网络地址 (ip,端口)等硬编码到了代码中,这种做法存在许多问题: 一旦服务提供者地址变化,就需要手工修改代码 一旦是多个服务提供

    2024年02月22日
    浏览(57)
  • SpringCloud微服务注册中心:Nacos介绍,微服务注册,Ribbon通信,Ribbon负载均衡,Nacos配置管理详细介绍

    注册中心可以说是微服务架构中的”通讯录“,它记录了服务和服务地址的映射关系。在分布式架构中,服务会注册到这里,当服务需要调用其它服务时,就这里找到服务的地址,进行调用。 服务注册中心(简称注册中心)是微服务框架的一个重要组件,在微服务架构里主要

    2024年02月22日
    浏览(63)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包