目录
3.如果没有就在nacos的配置中心中在对应的配置中配置nacos客户端的日志类型
SpringCloudAlibaba已经火了几年了,nacos同样也已经被大家使用很久了。我之前使用nacos的时候偶尔也会遇到一些问题,不过很快解决了,也就没有记录什么东西。
最近公司项目把项目拆分进行微服务化,原先的基础包里面的依赖是另一个同事添加进去的,是一些比较老旧的版本,大致如下:
组件 | 公司版本 | 稳定版本 |
Spring Boot | 2.3.3.RELEASE | 2.7.3 |
Spring Cloud | Hoxton.SR8 | 2021.0.4 |
Spring Cloud Alibaba | 2.2.3.RELEASE | 2021.1 |
看上图,我们就发现,公司使用的这三大组件的版本太低了,距离现在最新的稳定版差距还是很大的。更重要的是,这是把各种公司需要的依赖添加进去,作为一个基础包使用的一个项目,使用这样低的版本,很容易影响使用者的。我们项目中的有一些方法或者公共方法配置中就完全不支持。
还有一点,项目最终上线估计要在明年了,springboot的2.4x的版本以后变更很大,还使用这么低的版本,而且是新的项目,说实话,是很离谱的。
目前Alibaba官方的推荐组合是:
Spring Boot 2.6.3 + Spring Cloud 2021.0.1 + alibaba 2021.0.1.0
这不,我这就遇到了nacos的一个bug。
先说具体情况:
项目启动后,控制台一直刷新日志:
我们先记住红框框柱的这个md5的值:
md5=06b0426db5b6f399dbeb77a36a873ea8
本身我没有在意这个问题,项目中的配置为了做到动态刷新,做了一个配置了,增加了
@RefreshScope
这个注解,然后通过 SpringContextUtil 这个工具类获取对应的bean,然后再拿到对应的 属性。具体如下:
- @Data
- @Component
- @RefreshScope
- public class CommonConfig {
-
- @Value("${username}")
- private String name;
-
- @Value("${ip}")
- private String ip;
-
- }
使用的时候使用:
- CommonConfig config = SpringContextUtil.getBean(CommonConfig.class);
- String ip = config.getIp();
当然,上面是在静态方法中的使用方式,如果是在bean中,比如controller或者service中,可以直接注入,然后调用get方法即可。
项目本来是没问题的,但是我加了这个之后不知道为什么控制台就一直刷日志,而且非常频繁,几乎是一秒钟好几次,称作为刷屏完全不过分。
刚开始没有多想,以为是添加了
@RefreshScope
注解的缘故。
后来一想,也不对啊,nacos并不是采用定时任务判断配置有没有变更进而动态刷新值的,而是通过RefreshScope注解的
@Scope("refresh")
注解加上
ScopedProxyMode.TARGET_CLASS
来实现的。
代码如下:
- @Target({ElementType.TYPE, ElementType.METHOD})
- @Retention(RetentionPolicy.RUNTIME)
- @Scope("refresh")
- @Documented
- public @interface RefreshScope {
- ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS;
- }
最终是通过cglib来实现动态刷新的。
具体实现大家可以自行研究或者百度,这里与我们本篇关系不大,我们不细说。
其实这个问题是nacos1.2.1的一个bug,官网的issue:
nacos中的MD5和服务收到的MD5不一致,导致日志不断打印
我们看看nacos上的md5的值:
和我们上面说的那个md5的值比较是不是少了最前面的那个0呢?
md5字段有时候只有31位,与服务中计算的md5比较,首位缺少个0。如果经过多次修改dataId配置文件,这个md5又可能会恢复正常。所以说,这还是个偶发性错误,我们都都知道,不怕项目有错误,就怕这种偶发性的错误,其实是最难搞的,因为出现过之后,怎么复现就说不准了,那就难以定位问题所在。当然这个不在本文的讨论范围。
当然这个bug已经被官方修复了。
那我们如何解决这个问题呢?
升级依赖简单,但是nacos本身是有server的,要部署到服务器的,也就是说nacos要重新安装了。当然这个也是最稳妥的方法,更何况,现在还在用nacos1.2.1版本的大多都是老项目了,新项目应该会比较少了吧!
- <logger name="com.alibaba.nacos.client">
- <level value="ERROR" />
- logger>
- logging:
- level:
- com:
- alibaba:
- nacos:
- client:
- naming: error
第一种方法,我们暂且不尝试了,这个肯定是好使的。我们先试试第二种方法。
这个方案是ok的。
我们试试第二种方案,我们先把logback-spring.xml文件中刚才加的日志配置注释掉再尝试。
我们打开nacos对应的dataId,增加上面说的配置,当然,如果是properties方式的话,可以使用:
logging.level.com.alibaba.nacos.client=error
尝试了之后,有效果。
五、总结
1.nacos的1.2.1版本存在控制台不断刷新日志的bug;
2.解决方案有三:
(1)升级到更高版本;
(2)logback-xml文件中增加nacos的日志级别为error;
(3)nacos中添加nacos的日志级别为error。
最后,项目中的组件的版本,不一定非要用最新的,但是也尽量不要使用太老旧的。
六、后记
怎么算新与旧呢?
我想起来最近一两年的新能源汽车,我和同事们说一句话,我说你们不着急用车的其实可以等一等,一两年,两三年之后,新能源汽车就会比现在更成熟,也更稳定了,踩坑的可能性就好很多了。但是新能源汽车肯定不是三两年就能稳定下来的,技术也不大可能在两三年就沉淀下来形成技术壁垒的。当今的新能源汽车和当年的智能手机如出一辙,都属于大变革的时代,这个时候追风的,都要被风打落在地,除了真正飞起来的极少数人。
那技术也是同样的道理,有些组件已经很稳定了,虽然一直在维护中,但是很少有大的变化那种,就是一个稳定的版本,稳定的组件,已经成熟的组件。相反,虽然有的项目或者组件,维护的人很多,社区很活跃,但是处于一个新技术变更的阶段,那进去的时候所使用的组件肯定能要定期更新的,不然很容易出现一些坑,不升级又比较难解决的。
这就是为什么jdk大家都使用长期稳定版,而不是频繁尝鲜的原因。jdk8都出来多少年了,到今年才总算被jdk17有所动摇。这就是缘故。那么如果公司是新项目,真的建议直接上17。不管是从官方的维护与商业支持,还是垃圾回收、性能等各个方面,可以说都比8强了不少。8唯一的强势点,可能就在于基础用户太多,不管是个人开发者还是公司项目中,其实就是形成了规模效应,所以也就难以改变了。