大家好,我是烤鸭:
nacos 真的是有点意思,有时候哪怕某个jar包版本冲突了都可能导致莫名其妙的错误,源码走一波吧。
当前版本
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.6.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR12</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
</dependencies>
报错日志
com.alibaba.nacos.api.exception.NacosException: <html><body><h1>Whitelabel Error Page</h1><p>This application has no explicit mapping for /error, so you are seeing this as a fallback.</p><div id='created'>Sat May 14 06:51:53 CST 2022</div><div>There was an unexpected error (type=Forbidden, status=403).</div><div>unknown user!</div></body></html>
at com.alibaba.nacos.client.config.impl.ClientWorker.getServerConfig(ClientWorker.java:262)
at com.alibaba.nacos.client.config.NacosConfigService.getConfigInner(NacosConfigService.java:143)
at com.alibaba.nacos.client.config.NacosConfigService.getConfig(NacosConfigService.java:92)
at com.alibaba.cloud.nacos.client.NacosPropertySourceBuilder.loadNacosData(NacosPropertySourceBuilder.java:85)
at com.alibaba.cloud.nacos.client.NacosPropertySourceBuilder.build(NacosPropertySourceBuilder.java:74)
at com.alibaba.cloud.nacos.client.NacosPropertySourceLocator.loadNacosPropertySource(NacosPropertySourceLocator.java:204)
at com.alibaba.cloud.nacos.client.NacosPropertySourceLocator.loadNacosDataIfPresent(NacosPropertySourceLocator.java:191)
at com.alibaba.cloud.nacos.client.NacosPropertySourceLocator.loadNacosConfiguration(NacosPropertySourceLocator.java:161)
at com.alibaba.cloud.nacos.client.NacosPropertySourceLocator.loadExtConfiguration(NacosPropertySourceLocator.java:129)
at com.alibaba.cloud.nacos.client.NacosPropertySourceLocator.locate(NacosPropertySourceLocator.java:102)
at org.springframework.cloud.bootstrap.config.PropertySourceLocator.locateCollection(PropertySourceLocator.java:52)
at org.springframework.cloud.bootstrap.config.PropertySourceLocator.locateCollection(PropertySourceLocator.java:47)
at org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration.initialize(PropertySourceBootstrapConfiguration.java:101)
at org.springframework.boot.SpringApplication.applyInitializers(SpringApplication.java:623)
at org.springframework.boot.SpringApplication.prepareContext(SpringApplication.java:367)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:311)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1204)
at com.xxx.xxx.task.XxxTaskApplication.main(XxxTaskApplication.java:11)
问题猜想
nacos-client 1.2.0 以下的官方bug
https://blog.csdn.net/qq_35337554/article/details/104914397
这种问题大概率是版本问题,springboot/cloud/alibaba-cloud 参考版本。
https://blog.csdn.net/qq_38637558/article/details/114448690
client版本和server版本也要对的上,要注意下,不能盲目升client的版本,client和server 参考版本。
https://www.jianshu.com/p/df88e1967036
看看源码
如果上面的博客都看过了,还没解决问题,可能跟我的问题相似。
我们看下报错地方的源码, 为什么会报错。
ClientWorker 中 getServerConfig方法的 agent.httpGet 返回 403
public String[] getServerConfig(String dataId, String group, String tenant, long readTimeout)
throws NacosException {
String[] ct = new String[2];
if (StringUtils.isBlank(group)) {
group = Constants.DEFAULT_GROUP;
}
HttpResult result = null;
try {
List<String> params = null;
if (StringUtils.isBlank(tenant)) {
params = new ArrayList<String>(Arrays.asList("dataId", dataId, "group", group));
} else {
params = new ArrayList<String>(Arrays.asList("dataId", dataId, "group", group, "tenant", tenant));
}
result = agent.httpGet(Constants.CONFIG_CONTROLLER_PATH, null, params, agent.getEncode(), readTimeout);
} catch (IOException e) {
// 忽略无关代码
}
switch (result.code) {
// 忽略无关代码
case HttpURLConnection.HTTP_FORBIDDEN: {
LOGGER.error("[{}] [sub-server-error] no right, dataId={}, group={}, tenant={}", agent.getName(), dataId,
group, tenant);
throw new NacosException(result.code, result.content);
}
default: {
// 忽略无关代码
}
}
}
发现agent中的请求accessToken是null
accessToken 是项目启动后登录nacos返回的
这个就是 nacos-1.2.1 的源码,记住下面这个没有打印日志的异常。
SecurityProxy
public boolean login(List<String> servers) {
try {
if ((System.currentTimeMillis() - lastRefreshTime) < TimeUnit.SECONDS.toMillis(tokenTtl - tokenRefreshWindow)) {
return true;
}
for (String server : servers) {
if (login(server)) {
lastRefreshTime = System.currentTimeMillis();
return true;
}
}
} catch (Throwable ignore) {
}
return false;
}
进 login 方法里看,我擦,报红了。
问题解决
Charsets 来自
import org.apache.commons.codec.Charsets;
pom
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.4</version>
</dependency>
问题找到了, 我们项目用的 commons-codec 版本是1.4 ,已经没有这个类了,降到 1.13 没问题了
总结
一个简单的问题搞这么复杂,翻了n多博客,都没找到原因。
编译没报错,启动时候报错日志也没有,到请求nacos的时候,变成403了,这尼玛怎么找。
阿里开源的果然很坑,不过 2.0 据说优化了很多内容,性能也有很大提升。
伟大的开源都少不了大家的踩坑和pr,希望国产开源也越来越好吧,而不是为了什么OKR。