大家好,我是烤鸭:
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。