alibaba / nacos

an easy-to-use dynamic service discovery, configuration and service management platform for building cloud native applications.
https://nacos.io
Apache License 2.0
30.07k stars 12.81k forks source link

NACOS读取配置中心报错 #6456

Closed bnytezz closed 3 years ago

bnytezz commented 3 years ago

dataId invalid,异常信息为dataID无效,但其实他是存在的,我已经确认了nameSpace和group和dataId

brotherlu-xcq commented 3 years ago

可以提供一下详细的日志吗?

bnytezz commented 3 years ago

可以提供一下详细的日志吗?

您好,我已经确定异常原因并解决,我查证发现是目前Nacos的bug,下面我会沾上我使用的版本以及service版本。

bnytezz commented 3 years ago
    <!--Nacos Discovery-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        <version>2.2.6.RELEASE</version>
    </dependency>

    <!--Nacos Config-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        <version>2.2.6.RELEASE</version>
    </dependency>
    <!-- SpringCloud阿里巴巴 -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-alibaba-dependencies</artifactId>
        <version>2.2.0.RELEASE</version>
        <type>pom</type>
        <scope>import</scope>
    </dependency>
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.6.RELEASE</version>
</parent>
bnytezz commented 3 years ago

异常原因:因为我指定了 profiles: active: dev 而目前的nacos service版本为2.0.2,但是nacos会先请求${spring.application}.${file-extension},因为在我的配置中心不存在${spring.application}.${file-extension}配置,故而他无法完成装配,此时直接会抛出异常,DataSource数据源装配失败,也就是说其原因根本在于${spring.application}-${profiles.active}.${file-extension}使用该方式的情况下即使你的配置中心有了符合规定的配置,但是他依然不会读取,Nacos只读取${spring.application}.${file-extension}在配置中心中是否存在,并不会在乎${spring.application}-${profiles.active}.${file-extension}是否存在,即使存在也会抛出异常。

bnytezz commented 3 years ago

可以提供一下详细的日志吗?

这个BUG我本人认为非常严重!!!希望得到及时的解决。 @brotherlu-xcq

bnytezz commented 3 years ago

可以提供一下详细的日志吗?

如果需要复现请留下邮箱我会将BUG复现以截图方式发送给你

brotherlu-xcq commented 3 years ago

你直接贴到这个评论上,敏感信息打码就可以。社区里大家可以一起看看这个问题。

bnytezz commented 3 years ago

你直接贴到这个评论上,敏感信息打码就可以。社区里大家可以一起看看这个问题。

@brotherlu-xcq image image image

上图中在publicnamespace中已经存在了hsy-partner-service-dev.yaml配置,当启动的时候可以发现如下报错

image

而当新增了hsy-partner-service.yaml并且依然指定profiles: active: dev继续重启

image image image image

配置没有任何改变,但是启动成功了。可以知道Nacos在读默认的${spring.applicaion.name}.${file-extension}失败之后会直接抛出异常,并不会在乎${spring.application}-${profiles.active}.${file-extension}是否存在

image

删除${spring.application}-${profiles.active}.${file-extension}之后继续重启

image

重启成功。

zarkzheng commented 3 years ago

这其实不是个Bug。注意看你Nacos控制台里创建的配置文件dataid是没有带.yaml后缀的,这是导致你描述的现象的直接原因。 看下面这段代码(com.alibaba.cloud.nacos.client.NacosPropertySourceLocator),这里是Nacos客户端加载远程配置文件的逻辑。注意中文注释

    /**
     * load configuration of application.
     */
    private void loadApplicationConfiguration(
            CompositePropertySource compositePropertySource, String dataIdPrefix,
            NacosConfigProperties properties, Environment environment) {
        String fileExtension = properties.getFileExtension();
        String nacosGroup = properties.getGroup();
        // load directly once by default
               // 第一步加载:这里加载的dataid就是你配置的spring.application.name,默认其实是不带后缀的
        loadNacosDataIfPresent(compositePropertySource, dataIdPrefix, nacosGroup,
                fileExtension, true);
        // load with suffix, which have a higher priority than the default
               // 第二步加载:这里加载的dataid是spring.application.name.yaml,追加了文件后缀到dataid上
        loadNacosDataIfPresent(compositePropertySource,
                dataIdPrefix + DOT + fileExtension, nacosGroup, fileExtension, true);
        // Loaded with profile, which have a higher priority than the suffix
               // 第三步加载:最高优先级,加载带有profile的dataid,这里的dataid是spring.application.name-profile.yaml
        for (String profile : environment.getActiveProfiles()) {
            String dataId = dataIdPrefix + SEP1 + profile + DOT + fileExtension;
            loadNacosDataIfPresent(compositePropertySource, dataId, nacosGroup,
                    fileExtension, true);
        }

    }

也就是说,如果你Nacos配置文件里只有spring.application.name-profile而没有spring.application.name-profile.yaml,它是无法被加载的,而只能加载到spring.application.namespring.application.name.yamlspring.application.name-profile.yaml,这三类文件。

zarkzheng commented 3 years ago

是不是其实也可以考虑一下兼容这种情况,毕竟其他三种情况都尝试去加载了?

bnytezz commented 3 years ago

是不是其实也可以考虑一下兼容这种情况,毕竟其他三种情况都尝试去加载了?

@zarkzheng 我只是降低了日志打印等级,nacos日志中打印了带有-dev 带有文件后缀 以及不带文件后缀 他们的日志优先级顺序分别是 application.name > application.name.yaml > application.name-dev.yaml 具体顺序大概是这个,忘记了没有特意去记,总之这个顺序优先级是没错的,也就是说nacos在没有拿到application.name.yaml时也就无法完成DataSource装配,所以导致bug产生。我本人认为这就是bug,并且在低版本的时候这种方式是被兼容的,是可以正常使用的。

bnytezz commented 3 years ago

这其实不是个Bug。注意看你Nacos控制台里创建的配置文件dataid是没有带.yaml后缀的,这是导致你描述的现象的直接原因。 看下面这段代码(com.alibaba.cloud.nacos.client.NacosPropertySourceLocator),这里是Nacos客户端加载远程配置文件的逻辑。注意中文注释

  /**
   * load configuration of application.
   */
  private void loadApplicationConfiguration(
          CompositePropertySource compositePropertySource, String dataIdPrefix,
          NacosConfigProperties properties, Environment environment) {
      String fileExtension = properties.getFileExtension();
      String nacosGroup = properties.getGroup();
      // load directly once by default
               // 第一步加载:这里加载的dataid就是你配置的spring.application.name,默认其实是不带后缀的
      loadNacosDataIfPresent(compositePropertySource, dataIdPrefix, nacosGroup,
              fileExtension, true);
      // load with suffix, which have a higher priority than the default
               // 第二步加载:这里加载的dataid是spring.application.name.yaml,追加了文件后缀到dataid上
      loadNacosDataIfPresent(compositePropertySource,
              dataIdPrefix + DOT + fileExtension, nacosGroup, fileExtension, true);
      // Loaded with profile, which have a higher priority than the suffix
               // 第三步加载:最高优先级,加载带有profile的dataid,这里的dataid是spring.application.name-profile.yaml
      for (String profile : environment.getActiveProfiles()) {
          String dataId = dataIdPrefix + SEP1 + profile + DOT + fileExtension;
          loadNacosDataIfPresent(compositePropertySource, dataId, nacosGroup,
                  fileExtension, true);
      }

  }

也就是说,如果你Nacos配置文件里只有spring.application.name-profile而没有spring.application.name-profile.yaml,它是无法被加载的,而只能加载到spring.application.namespring.application.name.yamlspring.application.name-profile.yaml,这三类文件。

@zarkzheng 你可以看上边我传入的bug复现,你所说的{application.name}- profile.yaml他是存在的,因为配置的是yaml文件并且你把日志等级提升到debug之后你会发现nacos是全部都会请求,但是请求响应结果为null。

zarkzheng commented 3 years ago

或者你可以试一下,在客户端使用spring-cloud-alibaba 2021.1版本的项目里,只在nacos server添加spring.application.name-profile.yaml文件,注意dataid.yaml后缀(你截图里的dataid实际是spring.application.name-profile而不是spring.application.name-profile.yaml),然后启动一下,应该是可以正常启动的,无需spring.application.name.yaml配置。

zarkzheng commented 3 years ago

我看了一下老版本的实现,例如spring-cloud-alibaba 2.2.6.RELEASE,实现逻辑也是一样的。你之前用的哪个版本,可以加载spring.application.name-profile不带.yaml这种形式的配置?

bnytezz commented 3 years ago

你直接贴到这个评论上,敏感信息打码就可以。社区里大家可以一起看看这个问题。

部署到服务器又读不到了。。。

KomachiSion commented 3 years ago

profile的文件控制是SCA来进行的,如果有疑问可以去SCA社区问一下,看下设计思路是什么样的。

我认为应该不是bug,是对使用的理解有问题。建议还是去看下SCA的wiki或者发个issue问一下,能帮助你解决和理解这个功能。如果最后的确不符合设计预期,那可能是SCA的bug。在SCA那边修复下即可。