最近在學習Nacos元件,使用的是最新版本:2.2.3。
在本地虛擬機器器CentOS 8.5.2111
環境中安裝Nacos,並使用standalone
模式啟動,同時設定使用外部MySQL資料庫,MySQL版本為:8.0.34。
關於資料庫的設定引數如下:
spring.sql.init.platform=mysql
db.num=1
db.url.0=jdbc:mysql://192.168.2.100:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai
db.user.0=nacos
db.password.0=nacos
上述設定引數都是參考Nacos官方手冊來進行的。
進入到nacos安裝目錄執行如下啟動操作時報錯了。
cd nacos/bin
sh startup.sh -m standalone
報錯資訊如下:
cat ../logs/start.out
2023-07-28 22:31:42,401 ERROR Application run failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'configOpsController' defined in URL [jar:file:/root/opt/nacos/target/nacos-server.jar!/BOOT-INF/lib/nacos-config-2.2.3.jar!/com/alibaba/nacos/config/server/controller/ConfigOpsController.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'externalDumpService': Invocation of init method failed; nested exception is ErrCode:500, ErrMsg:Nacos Server did not start because dumpservice bean construction failure :
No DataSource set
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:229)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1372)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1222)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:745)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:423)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:307)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1317)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306)
at com.alibaba.nacos.Nacos.main(Nacos.java:35)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:108)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
at org.springframework.boot.loader.PropertiesLauncher.main(PropertiesLauncher.java:467)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'externalDumpService': Invocation of init method failed; nested exception is ErrCode:500, ErrMsg:Nacos Server did not start because dumpservice bean construction failure :
No DataSource set
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:160)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:440)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1796)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1391)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1311)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791)
... 27 common frames omitted
Caused by: com.alibaba.nacos.api.exception.NacosException: Nacos Server did not start because dumpservice bean construction failure :
No DataSource set
at com.alibaba.nacos.config.server.service.dump.DumpService.dumpOperate(DumpService.java:261)
at com.alibaba.nacos.config.server.service.dump.ExternalDumpService.init(ExternalDumpService.java:61)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:389)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:333)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:157)
... 40 common frames omitted
Caused by: java.lang.IllegalStateException: No DataSource set ## 從報錯資訊看似乎沒有設定資料來源
at org.springframework.util.Assert.state(Assert.java:76)
at org.springframework.jdbc.support.JdbcAccessor.obtainDataSource(JdbcAccessor.java:86)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:376)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:465)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:475)
at org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:508)
at org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:515)
at com.alibaba.nacos.config.server.service.repository.extrnal.ExternalConfigInfoPersistServiceImpl.findConfigMaxId(ExternalConfigInfoPersistServiceImpl.java:632)
at com.alibaba.nacos.config.server.service.dump.processor.DumpAllProcessor.process(DumpAllProcessor.java:51)
at com.alibaba.nacos.config.server.service.dump.DumpService.dumpConfigInfo(DumpService.java:318)
at com.alibaba.nacos.config.server.service.dump.DumpService.dumpOperate(DumpService.java:230)
... 48 common frames omitted
從啟動紀錄檔資訊看,似乎是資料來源未設定,但是明明已經設定了資料來源啊???另外很神奇的是偶爾有啟動成功的時候!至此開始懵逼了。
單純從啟動紀錄檔start.out
的資訊看,得不到任何有價值的提示,於是又轉到nacos.log
,所幸在這裡得到了一些有價值的異常資訊。
Caused by: com.mysql.cj.exceptions.UnableToConnectException: Public Key Retrieval is not allowed
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:61)
at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:85)
at com.mysql.cj.protocol.a.authentication.CachingSha2PasswordPlugin.nextAuthenticationStep(CachingSha2PasswordPlugin.java:130)
... 160 common frames omitted
於是先Google一下,確實有人也碰到這個問題:Connection Java - MySQL : Public Key Retrieval is not allowed。
解決辦法:在JDBC連線url上設定引數allowPublicKeyRetrieval=true
。
進一步瞭解才知道引數allowPublicKeyRetrieval
的具體用法,官方解釋如下:
大意就是:如果MySQL賬戶使用的認證模式為sha256_password
,則使用者端與伺服器端在傳遞資訊的時候必須要保護密碼,基於一些安全性的原因該引數預設值為false,但是這樣就會導致MySQL使用者端與伺服器端無法正常建立連線。因此,在確保MySQL伺服器在一個安全的網路環境下,不會遭受到中間人攻擊時可以將該引數值設定為true,這樣才能讓使用者端與伺服器端正常連線。
另外,從MySQL伺服器這一側來講,預設提供了2種認證外掛,即:sha256_password
和caching_sha2_password
。
而且,從MySQL 8.0.34之後預設的認證外掛為caching_sha2_password
,這個也可以從MySQL的變數值看出來,如下:
mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.34 |
+-----------+
1 row in set (0.00 sec)
mysql> select @@default_authentication_plugin;
+---------------------------------+
| @@default_authentication_plugin |
+---------------------------------+
| caching_sha2_password |
+---------------------------------+
1 row in set, 1 warning (0.00 sec)
mysql>
根據MySQL官方手冊可以知道,認證外掛caching_sha2_password
的功能實際上是外掛sha256_password
的超集,也是使用sha256_password
模式進行使用者認證,所以這就跟使用者端連線引數allowPublicKeyRetrieval
的用法聯絡在了一起。
至此,問題源頭得到梳理並解決!
我看網上也有人遇到類似的問題,參考:
nacos設定mysql資料來源啟動出現No DataSource set的問題
nacos啟動失敗,No DataSource set
nacos啟動報錯出現no datasource set或者Access denied for user ‘root‘@‘localhost‘ (using password: YES)
雖然從nacos的報錯紀錄檔來看都有一個No DataSource set
的資訊,但是原因卻各自不同,要想找到真正的原因,需要從nacos.log
檔案種去尋找有明確意義的提示資訊。
注意:nacos.log
紀錄檔檔案記錄的資訊會比start.out
記錄的資訊更加詳細,所以在nacos啟動失敗時一定要從nacos.log
分析可能的原因,切記!
最後,如果無法從紀錄檔找到任何線索,就只能手動去debug原始碼啦,參考:IntelliJ IDEA中執行Nacos官方原始碼。
【參考】
Connection Java - MySQL : Public Key Retrieval is not allowed
MySQL .NET Connection String Options
6.4.1.3 SHA-256 Pluggable Authentication
MySQL 8.0.34對其自帶身份驗證標記棄用
作者:程式設計隨筆
出處:http://www.cnblogs.com/nuccch/
宣告:本文版權歸作者和部落格園共有,歡迎轉載,但請在文章頁面明顯位置給出原文連線。