sentinel集成nacos启动报[check-update] get changed dataId error, code: 403错误排查及解决

整合nacos报403错误

因为平台写的一个限流代码逻辑有问题,所以准备使用sentinel来限流。平台依赖里面已经引入了,之前也测试过,把sentinel关于nacos的配置加上后,启动一直输出403错误 [fixed-10.0.20.188_8848-test] [check-update] get changed dataId error, code: 403
在这里插入图片描述

403的原因

先说结论,sentinel(我这里用到的alibaba-sentinel-datasource2.1.2.RELEASE版本)的代码有问题,他这个版本的nacos相关配置没有usernamepassword的属性,导致只能在nacos服务没有配置账号密码的时候使用,一旦改了账号密码,就无法正常访问nacos。今年不能用去年可以是因为今年测试环境nacos改了密码而去年是默认的。(文心一言竟然跟我说,他是共享了nacos的配置,所以不用配置账号密码,离谱)

仓库找了个比这高的版本(2021.0.5.0),发现这两个属性加上了,有需要的可以升级试试。不得不吐槽一句,这个依赖的版本是真的多,而且还没啥规律。如果想通过改源码的方式解决问题看最后

<!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-alibaba-sentinel -->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId><version>2021.0.5.0</version>
</dependency>

在这里插入图片描述
配置截图,
在这里插入图片描述

com.alibaba.cloud.sentinel.datasource.config.NacosDataSourceProperties类截图:
在这里插入图片描述

403问题排查过程

打断点查看http请求代码

因为控制台输出了ERROR日志,找到输出日志的代码行,打个断点。这里打断点是最方便的,我是通过logging.levellog级别改成了trace,然后看的http请求日志,在请求那里打的断点。
com.alibaba.nacos.client.config.impl.ClientWorker
在这里插入图片描述
通过调试发现在386行会发起http请求nacos服务器,agent属性是sentinel自己写的一个HttpAgent对象,主要是在发送http请求前做一些处理(比如拼上配置文件里面配置的nacos.server-addr)。
在这里插入图片描述
调用agent.httpPost之后,会在com.alibaba.nacos.client.config.http.ServerHttpAgent#httpPost处理,ServerHttpAgent类是HttpAgent接口的实现类。这里面主要就是在发送http请求之前,通过injectSecurityInfo方法给请求参数加入一些安全相关的参数。
在这里插入图片描述
injectSecurityInfo方法里面会判断securityProxy属性里面是否有token,有就加入,这里为空,所以大概率是这个问题了。
在这里插入图片描述

和nacos框架发送的http请求做对比

为了做一个对比,查看一下nacos框架发送的http请求和这个有啥区别,因为这是nacos里面的代码,所以nacos框架也会调用,可以看一下nacos框架请求nacos服务器里面有哪些信息。
在这里插入图片描述
可以发现nacos框架发送的请求,他这个securityProxy里面是有token信息的。这个是能正常请求nacos服务器的。现在能确定问题就是出现在这里了。所以现在的重点就是securityProxy这个属性。
在这里插入图片描述

securityProxy属性排查

因为SecurityProxyServerHttpAgent类的属性,搜了一下发现这个属性只在构造函数那里初始化赋值的,所以在ServerHttpAgent类的构造函数那里打个断点。在nacos框架初始化和sentinel初始化的时候,都会来调用这个,所以我们可以通过调试nacos框架的初始化来排查sentinel这边的哪里出了问题。
在这里插入图片描述
com.alibaba.nacos.client.config.http.ServerHttpAgent#ServerHttpAgent(java.util.Properties)截图
在这里插入图片描述

由于这个地方是在项目启动的时候调用,所以打完断点需要重启一下。

nacos框架初始化securityProxy

进入断点之后,发现nacos框架的这个properties里面是有账号密码配置的(配置文件里面配置了)
在这里插入图片描述

在这里插入图片描述
com.alibaba.nacos.client.security.SecurityProxy构造器里面给账号密码属性赋值(sentinel的那个压根都没有这两个属性,所以也能解释的通了,按道理这么低级的错误不应该的)
在这里插入图片描述
赋值完成之后,调用SecurityProxy里面的login方法,这个方法会发送登录请求,然后拿到token赋值给accessToken属性。
在这里插入图片描述

sentinel整合nacos的初始化securityProxy

com.alibaba.cloud.sentinel.custom.SentinelDataSourceHandler#afterSingletonsInstantiated类继承了SmartInitializingSingleton类,并重写了afterSingletonsInstantiated方法
文心一言:

SmartInitializingSingleton接口用于在Spring容器中所有单例Bean初始化完成后执行一些自定义的初始化逻辑。当所有单例Bean的依赖关系都解析完毕,并且所有单例Bean的实例化与初始化过程完成后,Spring容器会自动回调SmartInitializingSingleton接口的实现类的afterSingletonsInstantiated()方法。这个方法只会被调用一次。

在这个重写的方法内部,会对每个数据源进行初始化。sentinel里面每一个数据源都对应一个bean,这个beansentinel自己的beanFactory创建。
在这里插入图片描述
注册bean的方法。里面有一行BeanDefinitionBuilder.genericBeanDefinition(dataSourceProperties.getFactoryBeanName());代码,用来创建一个bean定义构造器对象,后面要使用这个对象要创建NacosDataSourceFactoryBean类的bean
文心一言:

BeanDefinitionBuilder主要用于在Spring的IoC(Inversion of Control,控制反转)容器中构建和配置Bean定义。Bean定义描述了如何创建一个Bean实例,包括其类名、作用域、初始化方法、属性设置等信息。通过BeanDefinitionBuilder,开发者可以以编程的方式轻松地创建和配置Bean定义,而不需要手动编写冗长的XML配置文件或注解。

在这里插入图片描述
遍历属性集合,然后里面校验一下,就通过BeanDefinitionBuilder builder对象把这些属性添加进去
在这里插入图片描述
注册bean之后又通过beanFactory来获取bean,注册的bean类型是com.alibaba.cloud.sentinel.datasource.factorybean.NacosDataSourceFactoryBean类型
在这里插入图片描述
sentinel自己实现的BeanFactory#getObject方法内,每次都是返回NacosDataSource对象(也就是说前面创建的bean是这个自定义的工厂bean,每次getBean都是获取到NacosDataSource对象,如果想获取到这个bean对象本身,getBean的时候名字前面加一个&)。在初始化Properties的时候,只判断地址是否配置,都没有关于账号密码的代码,所以sentinelnacos数据源在当初设计的时候,就是没有考虑到nacos会改账号或密码的情况,而不是配置文件里面漏了这两个属性。
在这里插入图片描述
因为前面都没有账号密码,所以ServerHttpAgent构造器这里的属性里面只有两个值,肯定也没有用户名和密码的。
在这里插入图片描述
在这里插入图片描述
大致的调用栈
在这里插入图片描述

排查结论

通过排查发现,这个对象所需的属性是从配置文件中拿的,因为nacos框架配置了usernamepassword,所以拿的到。而sentinel并没有提供相应的属性配置,所以就为空,直接导致了后面的403问题。

解决方案

  1. 如开头所说,升级版本就可以了,这是最简单的,当然有的系统可能升级之后会报错,这个就需要自己排查一下了
  2. 把账号密码改成默认的(当我没说,这个应该没人弄)
  3. 重写代码,自己项目main/java下面创建一个全类名一样的类,覆盖原有的类
    com.alibaba.cloud.sentinel.datasource.factorybean.NacosDataSourceFactoryBean类和com.alibaba.cloud.sentinel.datasource.config.NacosDataSourceProperties类,在两个类里面都加上usernamepassword属性,然后在NacosDataSourceFactoryBean里面赋值给属性类。
    或者说不改NacosDataSourceProperties代码直接改NacosDataSourceFactoryBean工厂,在里面获取nacos框架的配置,用那里面的账号密码也可以。

重写的NacosDataSourceProperties类,记得加setget方法,也可以使用Lombok

package com.alibaba.cloud.sentinel.datasource.config;import com.alibaba.cloud.sentinel.datasource.factorybean.NacosDataSourceFactoryBean;
import org.springframework.util.StringUtils;import javax.validation.constraints.NotEmpty;/*** Nacos Properties class Using by {@link DataSourcePropertiesConfiguration} and* {@link NacosDataSourceFactoryBean}.** @author <a href="mailto:fangjian0423@gmail.com">Jim</a>*/
public class NacosDataSourceProperties extends AbstractDataSourceProperties {private String serverAddr;@NotEmptyprivate String groupId = "DEFAULT_GROUP";@NotEmptyprivate String dataId;private String endpoint;private String namespace;private String accessKey;private String secretKey;/*** 自己添加的属性 用户名*/private String username;/*** 自己添加的属性 名称*/private String password;public NacosDataSourceProperties() {super(NacosDataSourceFactoryBean.class.getName());}@Overridepublic void preCheck(String dataSourceName) {if (StringUtils.isEmpty(serverAddr)) {serverAddr = this.getEnv().getProperty("spring.cloud.sentinel.datasource.nacos.server-addr","localhost:8848");}}public String getServerAddr() {return serverAddr;}public void setServerAddr(String serverAddr) {this.serverAddr = serverAddr;}public String getGroupId() {return groupId;}public void setGroupId(String groupId) {this.groupId = groupId;}public String getDataId() {return dataId;}public void setDataId(String dataId) {this.dataId = dataId;}public String getEndpoint() {return endpoint;}public void setEndpoint(String endpoint) {this.endpoint = endpoint;}public String getNamespace() {return namespace;}public void setNamespace(String namespace) {this.namespace = namespace;}public String getAccessKey() {return accessKey;}public void setAccessKey(String accessKey) {this.accessKey = accessKey;}public String getSecretKey() {return secretKey;}public void setSecretKey(String secretKey) {this.secretKey = secretKey;}public void setUsername(String username) {this.username = username;}public String getUsername() {return username;}public void setPassword(String password) {this.password = password;}public String getPassword() {return password;}
}

重写的NacosDataSourceFactoryBean类,太长了,这里就列出部分,直接加进去就行了。别忘了setget方法

    /*** 自己添加的属性 用户名*/private String username;/*** 自己添加的属性 密码*/private String password;@Overridepublic NacosDataSource getObject() throws Exception {Properties properties = new Properties();if (!StringUtils.isEmpty(this.serverAddr)) {properties.setProperty(PropertyKeyConst.SERVER_ADDR, this.serverAddr);} else {properties.setProperty(PropertyKeyConst.ACCESS_KEY, this.accessKey);properties.setProperty(PropertyKeyConst.SECRET_KEY, this.secretKey);properties.setProperty(PropertyKeyConst.ENDPOINT, this.endpoint);}if (!StringUtils.isEmpty(this.namespace)) {properties.setProperty(PropertyKeyConst.NAMESPACE, this.namespace);}// 自己加的逻辑  把账号密码加进去if (!StringUtils.isEmpty(this.username)) {properties.setProperty(PropertyKeyConst.USERNAME, this.username);}if (!StringUtils.isEmpty(this.password)) {properties.setProperty(PropertyKeyConst.PASSWORD, this.password);}return new NacosDataSource(properties, groupId, dataId, converter);}

改造之后效果截图:
在这里插入图片描述
账号密码等属性都有了
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/497941.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Redis】 数据淘汰策略

面试官询问缓存过多而内存有限时内存被占满的处理办法&#xff0c;引出 Redis 数据淘汰策略。 数据淘汰策略与数据过期策略不同&#xff0c; 过期策略针对设置过期时间的 key 删除&#xff0c; 淘汰策略是在内存不够时按规则删除内存数据。 八种数据淘汰策略介绍 no evision&…

【畅购商城】详情页模块之评论

目录 接口 分析 后端实现&#xff1a;JavaBean 后端实现 前端实现 接口 GET http://localhost:10010/web-service/comments/spu/2?current1&size2 { "code": 20000, "message": "查询成功", "data": { "impressions&q…

Kafka高性能设计

高性能设计概述 Kafka高性能是多方面协同的结果&#xff0c;包括集群架构、分布式存储、ISR数据同步及高效利用磁盘和操作系统特性等。主要体现在消息分区、顺序读写、页缓存、零拷贝、消息压缩和分批发送六个方面。 消息分区 存储不受单台服务器限制&#xff0c;能处理更多数据…

HTML——13.超链接

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>超链接</title></head><body><!--超链接:从一个网页链接到另一个网页--><!--语法&#xff1a;<a href"淘宝网链接的地址"> 淘宝…

LVS 负载均衡原理 | 配置示例

注&#xff1a;本文为 “ LVS 负载均衡原理 | 配置” 相关文章合辑。 部分内容已过时&#xff0c;可以看看原理实现。 使用 LVS 实现负载均衡原理及安装配置详解 posted on 2017-02-12 14:35 肖邦 linux 负载均衡集群是 load balance 集群的简写&#xff0c;翻译成中文就是负…

Docker 快速搭建 GBase 8s数据库服务

1.查看Gbase 8s镜像版本 可以去到docker hub网站搜索&#xff1a;gbase8s liaosnet/gbase8s如果无法访问到该网站&#xff0c;可以通过docker search搜索 docker search gbase8s2.拉取Gbase 8s镜像 以下演示的版本是目前官网最新版本Gbase8sV8.8_3.5.1 docker pull liaosn…

使用Lodash工具库的orderby和sortby进行排序的区别

简介 _.orderBy 和 _.sortBy 是 Lodash 库中用于排序数组的两个函数。 区别 _.orderBy 允许你指定一个或多个属性来排序&#xff0c;并为每个属性指定排序方向&#xff08;升序或降序&#xff09;。默认所有值为升序排&#xff0c;指定为"desc" 降序&#xff0c…

uniapp中Nvue白屏问题 ReferenceError: require is not defined

uniapp控制台输出如下 exception function:createInstanceContext, exception:white screen cause create instanceContext failed,check js stack ->Uncaught ReferenceError: require is not defined 或者 exception function:createInstanceContext, exception:white s…

STM32-笔记16-定时器中断点灯

一、实验目的 使用定时器 2 进行中断点灯&#xff0c;500ms LED 灯翻转一次。 二&#xff0c;定时器溢出时间计算 Tout&#xff1a;定时器溢出时间 Ft&#xff1a;定时器的时钟源频率 ARR&#xff1a;自动重装载寄存器的值&#xff08;可设置ARR从0开始&#xff0c;但是计数到…

Visual Studio 使用 GitHub Copilot 与 IntelliCode 辅助编码 【AI辅助开发系列】

&#x1f380;&#x1f380;&#x1f380;【AI辅助编程系列】&#x1f380;&#x1f380;&#x1f380; Visual Studio 使用 GitHub Copilot 与 IntelliCode 辅助编码Visual Studio 安装和管理 GitHub CopilotVisual Studio 使用 GitHub Copilot 扩展Visual Studio 使用 GitHu…

【数据结构】数据结构整体大纲

数据结构用来干什么的&#xff1f;很简单&#xff0c;存数据用的。 &#xff08;这篇文章仅介绍数据结构的大纲&#xff0c;详细讲解放在后面的每一个章节中&#xff0c;逐个击破&#xff09; 那为什么不直接使用数组、集合来存储呢 ——> 如果有成千上亿条数据呢&#xff…

开放世界目标检测 Grounding DINO

开放世界目标检测 Grounding DINO flyfish Grounding DINO 是一种开创性的开放集对象检测器&#xff0c;它通过结合基于Transformer的检测器DINO与基于文本描述的预训练技术&#xff0c;实现了可以根据人类输入&#xff08;如类别名称或指代表达&#xff09;检测任意对象的功…

webrtc 源码阅读 make_ref_counted模板函数用法

目录 1. 模板参数解析 1.1 typename T 1.2 typename... Args 1.3 typename std::enable_if::value, T>::type* nullptr 2. scoped_refptr 3. new RefCountedObject(std::forward(args)...); 4. 综合说明 5.在webrtc中的用法 5.1 peerConnectionFactory对象的构建过…

RK3566和Robo_C的EMC防护设计细节

USB部分的防护细节&#xff1a; ROBO C的USB接口&#xff1a; PF级别的电容滤波&#xff1a; TVS电容&#xff08;TVS Capacitor&#xff09;&#xff1a;用于与TVS二极管配合&#xff0c;保护电路免受瞬态电压冲击。电容一般较小&#xff0c;通常为几十皮法&#xff08;pF&am…

如果你的网站是h5网站,如何将h5网站变成小程序-除开完整重做方法如何快速h5转小程序-h5网站转小程序的办法-优雅草央千澈

如果你的网站是h5网站&#xff0c;如何将h5网站变成小程序-除开完整重做方法如何快速h5转小程序-h5网站转小程序的办法-优雅草央千澈 h5如何转小程序 如果当年你们开发网站是用的h5但是没有开发小程序&#xff0c;也没有使用uniapp这样的混开框架&#xff0c;但是目前根据业务需…

30天面试打卡计划 2024-12-25 26 27 面试题

2024-12-25 面试题 后端 MySQL三层B树能存多少数据&#xff1f; B 树&#xff1a;一种特殊的多路平衡查找树&#xff0c;广泛应用于数据库索引中。它具有所有叶子节点都位于同一层且包含指向相邻叶子节点指针的特点&#xff0c;这使得范围查询更加高效。InnoDB&#xff1a;My…

微信流量主挑战:用户破16!新增文档转换(新纪元3)

朋友们&#xff0c;报告好消息&#xff01;我的小程序用户数量已经涨到16个了&#xff01;没错&#xff0c;真没拉朋友圈亲戚好友来撑场子&#xff0c;全靠实力&#xff08;和一点点运气&#xff09;吸引了16位陌生小伙伴光临&#xff01;这波进步&#xff0c;连我自己都感动了…

阿里云redis内存优化——PCP数据清理

在阿里云安装了一个redis节点&#xff0c;今天使用时忽然想着点击了一下分析内存。好家伙&#xff0c;居然崩出了一个30多M的块出来。问题是我本地安装的redis没有这个啊&#xff0c;怎么奇怪冒出这个来了。 本着把系统用干榨尽的态度&#xff0c;研究了下这个问题的来源。网上…

常见的排序算法过程和比较分析

比较分析 排序类别排序算法时间复杂度&#xff08;最好&#xff09;时间复杂度&#xff08;最坏&#xff09;时间复杂度&#xff08;平均&#xff09;辅助空间复杂度稳定性插入排序直接插入排序O(n)O(n)O(n)O(1)稳定插入排序折半插入排序O(n)O(n)O(n)O(1)稳定插入排序希尔排序…

webrtc-internals调试工具

Google 的 Chrome&#xff08;87 或更高版本&#xff09;WebRTC 内部工具是一套内置于 Chrome 浏览器中的调试工具; webrtc-internals 能够查看有关视频和音频轨道、使用的编解码器以及流的一般质量的详细信息。这些知识对于解决音频和视频质量差的问题非常有帮助。 webrtc-int…