找回密码
 立即注册
首页 业界区 业界 nacos中配了一个数字,springboot取回来怎么变了 ...

nacos中配了一个数字,springboot取回来怎么变了

痕厄 8 小时前
背景

对于java开发人员来说,nacos想必不陌生了,我们这边是拿来做配置中心为主。我这边的习惯用法是,在bootstrap.yml中配置nacos相关的配置、profile:
1.png

然后呢,可以看到,nacos是支持启用或者不启用的,如果为true,就会使用nacos上的配置;我本地开发的时候,随时会把配置改来改去,我一般设置为false,不启用,此时就会使用本地的application-dev.yml中的配置。
开发得差不多了,再切换成使用nacos中配置,测一下就差不多了。
  1. {
  2.   "name": "spring.cloud.nacos.config.enabled",
  3.   "type": "java.lang.Boolean",
  4.   "description": "enable nacos config or not.",
  5.   "defaultValue": true
  6. },
复制代码
结果呢,最近遇到个小问题。如下所示,有个appCode,这个配置项,是一个应用的唯一编码,开发环境配置如下,不论使用启用nacos,这块在程序中获取的配置都是正确的。
2.png

对应的spring中接收配置的代码如下:
3.png

然后,转到测试环境后,换成了如下配置,也就是code变了,结果程序中取出来,就成了:
4.png

5.png

appCode怎么是266啥的,我当时和测试同事仔细检查了下,确认没配置错误。
那,这是咋回事呢
定位过程

排除nacos问题

由于是测试环境,网络都是通的,我直接在本地ide连测试环境,复现了下问题,抓了个本地和nacos之间的包:
6.png

看了下一点问题没有。接下来就是看代码怎么处理的了。
propertysouece

先弄个field断点,看看写入时候的栈。其实如果对nacos熟悉的话,也可以正向排查,从nacos获取到配置后的处理过程开始看,我这里就先按照反向流程来。
7.png

然后就看到断点停住了,进来的值确实不对:
8.png

把栈往上翻了翻,发现是在创建bean的过程中调用这块方法的。我们知道,一个bean的创建,一般会有:调用构造函数--》注入field的值(比如那些设置了@autowired的field、或者是我这这种注解了@ConfigurationProperties(prefix = "app")的,等等)--》调用init方法或afterpropertiesSet方法等。
此时,我的栈就处于第二步,此时bean已经通过构造函数弄出来了,正在注入ConfigurationProperties相关属性的值。
翻到上面的caller栈,发现下面这个地方,获取到的bound字段的值已经是2开头,是错的了,那看来就是这个地方,取到了错误的值,那就这里打个断点再来。
9.png

这次从上面断点进来后,发现进入了一个findProperty的方法,如下,主要就是根据app.app-list-need-query-todo-num[0].app-code这么个属性,要获取到对应的value,这也正常,要先获取到值,才能设置到bena里。
10.png

可以看到,获取property主要是从propertySource中获取。这个property是啥类型呢,
org.springframework.boot.context.properties.source.SpringIterableConfigurationPropertySource,里面有另一个propertySource字段,这个字段的类型是:org.springframework.cloud.bootstrap.config.BootstrapPropertySource,而下图可看到,BootstrapPropertySource中的delegate字段,才指向真正的propertySource,即NacosPropertySource
11.png

这里我们跟进去后,发现,property的格式不太一致,nacos中的存储都是驼峰格式,而这里获取配置的property是中划线格式,所以这次是获取不到的。
12.png

不过,spring做了兼容,会对property进行转换,变成驼峰格式再来找一次:
13.png

这次能找到了,但找到的是错误的,所以,我们还得看看nacosPropertySource中的值,为啥是错的。
nacosPropertySource中的值,存放在source这个字段中,类型是LinkedHashMap,我们就看看这个map是什么时候赋值的。
14.png

我们发现,这个source应该是构造函数时候,设置进来的,如下:
15.png

找了下调用这个构造函数的地方,如下,这里就会去先获取nacos中的配置,然后调用构造函数,我们看了下,发现下面红框的propertySource中已经是错误的了,得再打个断点跟进去
16.png

loadNacosData

下面这个方法中,先就是去nacos服务端获取到配置,然后再进行解析,可以看到,从服务端取到的是对的,那就是解析的问题,继续跟进去:
17.png

由于nacos中配置支持多种格式,如下图所示,有多种解析器,我们这边是yaml,类型是:org.springframework.boot.env.YamlPropertySourceLoader,这个loader是spring-boot自带的:
18.png

19.png

这个org.springframework.boot.env.YamlPropertySourceLoader实际自己并不能独立完成yaml格式文件的解析,而是依赖另一个jar包:
  1.     <dependency>
  2.       <groupId>org.yaml</groupId>
  3.       snakeyaml</artifactId>
  4.       <version>1.30</version>
  5.       <scope>compile</scope>
  6.     </dependency>
复制代码
20.png

21.png

yaml

yaml这个具体的解析逻辑就比较复杂了,可以使用条件断点,不然很难debug。
22.png

下面可以看到,如果这个字符串,是0开头,就认为是8进制了,且会去掉开头的0,如:01011003,由于首位为0,认为是8进制,然后去掉符号位,值为:1011003
23.png

然后把1011003转成8进制数字,变成了266755
24.png

25.png

26.png

为啥开发环境时的010190那个code没转成8进制了,可能是转换失败了(但我发现改成010190后,没走上面那段逻辑,里面yaml解析挺复杂,就没继续跟了)。
解决方式

由于是进制转换的问题,我这里的解决方式是,直接在nacos用字符串来配置,避免这些数字转换问题。
27.png


来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册