同时使用@LoadBalanced @RefreshScope注解负载均衡失效分析
作者:毕小宝 发布时间:2023-12-07 10:59:24
背景
最近引入了 Nacos Config 配置管理能力,说起来用法很简单,还是踩了三个坑。
Nacos Config 的 nacos 的帐号密码加密配置后,怎么解密而且在
NacosConfigBootstrapConfiguration
真正注入 Nacos Config 注入之前,而且不能触发NacosDiscoveryProperties
的isNacosDiscoveryInfoChanged
变动事件。因为NacosDiscoveryProperties
接受NacosContextRefresher
事件时,还是从 yml 配置中获取属性,不会从Environment
对象中加载。@RefreshScope
要想生效,该注意什么?非 shared-config 的配置变动时,要想实时生效,必须在当前应用的 bootstrap.yml 中配置spring.application.name
属性,注册该应用在配置中心需要监听的配置。@RefreshScope + @LoadBalanced
同时使用导致 Ribbon 负载均衡失效问题。
问题一比较复杂,此处不做讨论,本文记录问题三的解决方法及个人思考。
问题
有个模块使用了 @LoadBalanced
负载均衡,通过配置控制超时时间。
引入 Nacos Config 配置后,按照常规用法,在对象上添加了 @RefreshScope
属性,希望配置变动时,能实时生效。
注入代码如下:
@Value("${rest.template.connect-timeout:10000}")
private Integer connectTimeout;
@Value("${rest.template.read-timeout:10000}")
private Integer readTimeout;
@Bean
@RefreshScope
@LoadBalanced
public RestTemplate restTemplate(RestTemplateBuilder builder){
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setConnectTimeout(connectTimeout); //连接超时设置
requestFactory.setReadTimeout(readTimeout); //读写超时设置
RestTemplate restTemplate = new RestTemplate(requestFactory);
logger.info("初始化负载均衡的 RestTemplate 对象 {} {}", connectTimeout, readTimeout);
return restTemplate;
}
修改配置中心的配置后,可以监控到 RestTemplate
会在配置变化后重新初始化了,也打印了最新的配置。
但真正使用这个类,调用某个服务时,出现了服务无法解析的异常:
分析
首先,检查调用的目标服务是否注册成功,目标服务是正常启动的。
其次,对比其他同样引用了 @LoadBalanced
的 RestTemplate
的模块,它调用是正常的。
最后,对比异常调用和正常调用的注入代码的区别,多了一个 @RefreshScope
,调整代码验证结果正常。引入 @RefreshScope
时,在配置变化后才会发生这个异常,首次运行时正常的。
延伸搜索发现,负载均衡 RestTemplate
也有类似的问题 @scope("prototype")+@loadbalanced注解时负载均衡失效问题。
启示录
@LoadBalanced
和 @RefreshScope
同时使用,首次初始化时,RestTemplate
对象具有负载均衡的能力;当 Nacos 配置中的配置变动时,这个对象会重新创建,而且此时并没有使用 @LoadBalanced
的能力,导致负载均衡失效。
就是说,这两个注解同时使用时,在不同的时机,只会有一个注解生效:
初始创建时,
@LoadBalanced
生效,系统中的实例是负载均衡的RestTemplate
;当 Nacos 配置变化,
NacosContextRefresher
触发通知@RefreshScope
注解的@Bean
对象时,重新创建的实例就是普通的RestTemplate
了。
引入任何一个第三方工具,面对的都是黑盒,各种资料用法看似简单,一用就坑不断啊!建议 Nacos Config 官方配置给出一个使用建议 @RefreshScope
不要用在 @LoadBalanced
注解上。
最后记录一个偶然的发现:
选中几个图片文件后,右侧概览图是一个堆叠的图,才注意到!
来源:https://juejin.cn/post/7198099134363353125


猜你喜欢
- 什么是banner组件?在许多Android应用上,比如爱奇艺客户端、百度美拍、应用宝等上面,都有一个可以手动滑动的小广告条,这就是bann
- 本文实例讲述了Android编程之重力感应用法。分享给大家供大家参考,具体如下:重力感应主要是依靠手机的加速度传感器(acceleromet
- 本文实例讲述了Spring实战之清除缓存操作。分享给大家供大家参考,具体如下:一 配置文件<?xml version="1.
- 1. 概述当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。2. 解决的问题主要解决的是当控制一个对象状态转换的条件表
- 先看看效果:用极少的代码实现了 动态详情 及 二级评论 的 数据获取与处理 和 UI显示与交互,并且高解耦、高复用、高灵活。动态列表界面Mo
- 一、APP端调用1、注册广播监听查找结果//蓝牙发现设备和查找结束广播IntentFilter intentFilter = new Int
- 一、遇到一个问题1、读取CSV文件package com.guor.demo.charset;import java.io.Buffered
- 本文实例讲述了java实现将结果集封装到List中的方法。分享给大家供大家参考,具体如下:import java.sql.Connectio
- 本文实例讲述了Android编程实现AIDL(跨进程通信)的方法。分享给大家供大家参考,具体如下:一. 概述:跨进程通信(AIDL),主要实
- @RequestBody,@RequestParam和@Param区别@Param@Param是mybatis中的注解,用注解来简化xml配
- mybatis count()按条件查询1、sql count()函数count()函数返回匹配指定条件的行数。sql count(colu
- 本文实例为大家分享了C++ socket实现miniFTP的方法,供大家参考,具体内容如下客户端:服务端:建立连接 &
- 在 Android 的一些界面中,有时候我们需要为一副图片生成大小为 n * n 的缩略图,有时候需要的缩略图特殊一些,比如:1、带圆角的缩
- 要点1:cmd命令行的输入命令netsh wlan set hostednetwork mode=allow ssid=用户名
- 本文实例讲述了C#编程实现获取文件夹中所有文件的文件名。分享给大家供大家参考,具体如下:想实现这样一个功能:批量修改一个目录所有jpg文件的
- 目录基本查询延迟查询属性类型筛选复合from子句多级排序分组联合查询-join合并-zip()分区(分页)并行linq取消长时间运行的并行l
- Json格式是常见的读写形式。读写Json文件也是常用的操作。这次来实践一下Json文件的读写。首先在SD卡上的读写权限是一定要申请的。那么
- 1.引言在开发过程中,我们经常会遇到需要显示或隐藏View视图的情况,如果在隐藏或显示View的过程中加上动画,能让交互更加的友好和动感,本
- Redisson分布式锁之前的基于注解的锁有一种锁是基本redis的分布式锁,锁的实现我是基于redisson组件提供的RLock,这篇来看
- 程序思路:动态加载V4和V2的mscorlib.dll程序集,通过反射进行比较。之所以加载mscorlib.dll 是因为framework