nacos配置不自动刷新

当我们把nacos服务端启动起来,项目中也集成好之后,兴高采烈的启动项目准备试一下,发现在nacos中修改配置之后发现项目中的配置竟然没有刷新,然后开始怀疑是不是自己那里配置的不对、那个注解没有写、nacos版本是不是和springboot不兼容,然后一通修改,最后发现还是不行,最后开始怀疑人生。
下面两个场景可能会帮到你

1.没有开启nacos的自动刷新

springboot集成nacos的时候,需要在项目的配置文件里加入如下配置

nacos:
  config:
    bootstrap:
      enable: true
    # nacos服务ip和端口
    server-addr: 127.0.0.1:8848
    data-id: test
    group: local
    username: nacos
    password: nacos
    type: yaml
    # 开启nacos自动刷新,如果这个配置没有或者为false会导致配置不能自动刷新
    auto-refresh: true
    # 允许nacos服务端向本地同步配置
    enable-remote-sync-config: true

并且在配置属性上使用@NacosValue注解并且配置注解的autoRefreshed的值为true(默认为false,不会自动刷新),两个配置缺一不可;如果你使用的是spring的@Value注解,只能获取到配置,但不能自动刷新配置。
到这里借本就可以解决99%的问题了,剩下的1%的问题接着往下看

2.项目中集成了ulisesbocchio或者类似的插件,对配置进行加密

如果不想看细节,只想解决问题,可以直接把项目中ulisesbocchio或者类似的插件移除掉,然后把加密的配置变成明文放到nacos中就好了。
------------------------下面进行问题定位------------------------
在nacos中修改配置后,会自动通知给客户端,客户端在收到通知变更的请求后,经过一系列的前戏会执行到
com.alibaba.nacos.client.config.impl.CacheData#safeNotifyListener这个方法里,源码如下我们在这个方法的第一行打一个断点追踪一下执行链路;

    <dependency>
        <groupId>com.github.ulisesbocchio</groupId>
        <artifactId>jasypt-spring-boot-starter</artifactId>
        <version>${jasypt-spring-boot-starter.version}</version>
    </dependency>
private void safeNotifyListener(final String dataId, final String group, final String content, final String type,
            final String md5, final String encryptedDataKey, final ManagerListenerWrap listenerWrap) {
        final Listener listener = listenerWrap.listener;
        if (listenerWrap.inNotifying) {
            LOGGER.warn(
                    "[{}] [notify-currentSkip] dataId={}, group={}, md5={}, listener={}, listener is not finish yet,will try next time.",
                    name, dataId, group, md5, listener);
            return;
        }
        //这里创建了一个线程,异步的修改配置,保证保证本次配置变更请求能够快速响应
        Runnable job = new Runnable() {
            @Override
            public void run() {
                long start = System.currentTimeMillis();
                ClassLoader myClassLoader = Thread.currentThread().getContextClassLoader();
                ClassLoader appClassLoader = listener.getClass().getClassLoader();
                try {
                    if (listener instanceof AbstractSharedListener) {
                        AbstractSharedListener adapter = (AbstractSharedListener) listener;
                        adapter.fillContext(dataId, group);
                        LOGGER.info("[{}] [notify-context] dataId={}, group={}, md5={}", name, dataId, group, md5);
                    }
                    // Before executing the callback, set the thread classloader to the classloader of
                    // the specific webapp to avoid exceptions or misuses when calling the spi interface in
                    // the callback method (this problem occurs only in multi-application deployment).
                    Thread.currentThread().setContextClassLoader(appClassLoader);
                    
                    ConfigResponse cr = new ConfigResponse();
                    cr.setDataId(dataId);
                    cr.setGroup(group);
                    cr.setContent(content);
                    cr.setEncryptedDataKey(encryptedDataKey);
                    configFilterChainManager.doFilter(null, cr);
                    String contentTmp = cr.getContent();
                    listenerWrap.inNotifying = true;
                    // contentTmp这个变量里存储了最新的全量配置,也是我们这次源码追踪的重点,看看是如何自动刷新配置的
                    listener.receiveConfigInfo(contentTmp);
                    // compare lastContent and content
                    if (listener instanceof AbstractConfigChangeListener) {
                        Map data = ConfigChangeHandler.getInstance()
                                .parseChangeData(listenerWrap.lastContent, content, type);
                        ConfigChangeEvent event = new ConfigChangeEvent(data);
                        ((AbstractConfigChangeListener) listener).receiveConfigChange(event);
                        listenerWrap.lastContent = content;
                    }
                    
                    listenerWrap.lastCallMd5 = md5;
                    LOGGER.info("[{}] [notify-ok] dataId={}, group={}, md5={}, listener={} ,cost={} millis.", name,
                            dataId, group, md5, listener, (System.currentTimeMillis() - start));
                } catch (NacosException ex) {
                    LOGGER.error("[{}] [notify-error] dataId={}, group={}, md5={}, listener={} errCode={} errMsg={}",
                            name, dataId, group, md5, listener, ex.getErrCode(), ex.getErrMsg());
                } catch (Throwable t) {
                    LOGGER.error("[{}] [notify-error] dataId={}, group={}, md5={}, listener={} tx={}", name, dataId,
                            group, md5, listener, t.getCause());
                } finally {
                    listenerWrap.inNotifying = false;
                    Thread.currentThread().setContextClassLoader(myClassLoader);
                }
            }
        };
        
        final long startNotify = System.currentTimeMillis();
        try {
            if (null != listener.getExecutor()) {
                //将上面创建的线程放到线程池里执行
                listener.getExecutor().execute(job);
            } else {
                try {
                    INTERNAL_NOTIFIER.submit(job);
                } catch (RejectedExecutionException rejectedExecutionException) {
                    LOGGER.warn(
                            "[{}] [notify-blocked] dataId={}, group={}, md5={}, listener={}, no available internal notifier,will sync notifier ",
                            name, dataId, group, md5, listener);
                    job.run();
                } catch (Throwable throwable) {
                    LOGGER.error(
                            "[{}] [notify-blocked] dataId={}, group={}, md5={}, listener={}, submit internal async task fail,throwable= ",
                            name, dataId, group, md5, listener, throwable);
                    job.run();
                }
            }
        } catch (Throwable t) {
            LOGGER.error("[{}] [notify-error] dataId={}, group={}, md5={}, listener={} throwable={}", name, dataId,
                    group, md5, listener, t.getCause());
        }
        final long finishNotify = System.currentTimeMillis();
        LOGGER.info("[{}] [notify-listener] time cost={}ms in ClientWorker, dataId={}, group={}, md5={}, listener={} ",
                name, (finishNotify - startNotify), dataId, group, md5, listener);
    }

由于篇幅问题,后面的我用图片展示,大家根据图片可以自行追踪

代码调试完成后,问题的根源也就找到了,接下来就是删除配置加密组件,修改为明文配置,启动项目,搞定收工。

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
Spring Boot项目中,可以通过使用@RefreshScope注解和@NacosValue注解来实现Nacos配置中心的自动刷新。 使用@RefreshScope注解是一种实现Nacos属性值自动刷新的方式。在需要动态刷新的类或方法上添加@RefreshScope注解,当Nacos上的属性值发生变化时,应用程序会自动刷新注解的类或方法中的属性值。这样就可以避免重启应用程序来应用最新的属性值。 另一种方式是使用@NacosValue注解。该注解可以直接应用于类的属性上,在属性值变化时自动刷新注解的属性。在Spring Boot项目的pom.xml文件中添加相关依赖后,需要在属性上添加@NacosValue注解,并设置autoRefreshed参数为true,以开启自动刷新功能。 示例代码如下: ```java import com.alibaba.nacos.api.config.annotation.NacosValue; import org.springframework.stereotype.Component; @Component public class MyComponent { @NacosValue(value = "${my.property}", autoRefreshed = true) private String myProperty; public String getProperty() { return myProperty; } } ``` 通过使用@RefreshScope注解和@NacosValue注解,您可以实现Nacos配置中心的自动刷新,使应用程序能够在运行时动态应用最新的属性值,而无需重启应用。这样可以提高开发效率和系统的灵活性。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [实现Nacos属性值自动刷新的三种方式](https://blog.csdn.net/run65536/article/details/131477092)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值