ribbon和nacos获取服务列表不一致问题

前言:
1.nacos是基于推送事件模式获取服务列表信息的
2.ribbon是本地每隔一定时间主动去拉取服务信息的

这两个特性就可能会导致nacos上已经获取到了服务列表但是ribbon还没开始拉取最新的服务信息,导致在调用服务的时候会找不到nacos上的服务。

查了一下网上资料并没有很可靠的解决方案,还是看一看源码吧

解决办法:
1.在本地nacos监听到事件消息的时候,通过ribbon主动拉取一下服务信息,让ribbon上的服务信息和nacos保持一致,达到同步的目的。

nacos官方文档:https://nacos.io/zh-cn/docs/sdk.html
代码如下:
1.本地配置nacosService

@Configuration
@Data
@Slf4j
public class NacosNamingConfig {

    @Value("${spring.cloud.nacos.discovery.server-addr}")
    private String serverAddr;
    @Value("${spring.cloud.nacos.discovery.namespace}")
    private String namespace;


    private static NamingService namingService;


    @Bean(name = "namingService")
    public NamingService get() throws NacosException {
        log.info("NacosNamingConfig namingService 执行");
        Properties properties = System.getProperties();
        properties.setProperty("serverAddr", serverAddr);
        properties.setProperty("namespace", namespace);
        namingService = NamingFactory.createNamingService(properties);
        return namingService;
    }

}

2.配置updater,更新ribbon服务列表有用

@Component("ribbonServerListUpdater")
public class MyPollingServerListUpdater extends PollingServerListUpdater {

    private UpdateAction updateAction;

    @Override
    public synchronized void start(UpdateAction updateAction) {

        this.updateAction = updateAction;

        super.start(updateAction);

    }


    public UpdateAction getUpdateAction(){

        return updateAction;

    }
}

2.开启nacos订阅

@Component
@Slf4j
public class ServerStatusRunner implements CommandLineRunner {

    @Autowired
    private NamingService namingService;



    @Override
    public void run(String... args) throws Exception {
        namingService.subscribe("服务名", new NacosListener());

    }
}

3.nacos事件监听里面主动刷新ribbon里面的服务列表信息


@Slf4j
public class NacosListener implements EventListener {

    private MyPollingServerListUpdater myListUpdater;

    private NacosNamingService namingService;

    private HostReactor hostReactor;

    @Override
    public void onEvent(Event event) {
        log.info("nacos监听事件消息:"+ JSON.toJSONString(event));

        //通知ribbon更新服务列
        // 1.刷新本地缓存
        log.info("nacos监听事件,刷新ribbon本地缓存");
        namingService = SpringJobBeanFactory.getBean(NacosNamingService.class);
        Class cls = Class.forName("com.alibaba.nacos.client.naming.NacosNamingService");
        Field field = cls.getDeclaredField("hostReactor");
        field.setAccessible(true);
        Object hostReactorValue = field.get(namingService);
        this.hostReactor = (HostReactor) hostReactorValue;
        this.hostReactor.updateServiceNow("服务名", "");

        // 2.更新服务列表
        log.info("nacos监听事件,更新ribbon服务列表");
        myListUpdater = SpringJobBeanFactory.getBean(MyPollingServerListUpdater.class);
        ServerListUpdater.UpdateAction updateAction = myListUpdater.getUpdateAction();
        if (updateAction != null) {
            updateAction.doUpdate();
        }

        // 3.处理业务消息
    
    

    }
}

4.工具类:

@Component
public class SpringJobBeanFactory implements ApplicationContextAware {

    
    private static ApplicationContext applicationContext;
    
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringJobBeanFactory.applicationContext=applicationContext;
        
    }
     public static ApplicationContext getApplicationContext() {
            return applicationContext;
    }
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) throws BeansException {
            if (applicationContext == null){
                return null;
            }
            return (T)applicationContext.getBean(name);
      }
    
    public static <T> T getBean(Class<T>  name) throws BeansException {
            if (applicationContext == null){
                return null;
            }
            return applicationContext.getBean(name);
      }
}
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值