“...)
解決項目啟動報java.lang.NullPointerException: Cannot invoke com.alibaba.nacos.client.naming.backups.FailoverDataSource.getSwitch() because the return value of com.alibaba.nacos.client.naming.backups.FailoverReactor.access$000(com.alibaba.nacos.client.naming.backups.FailoverReactor) is null問題發現問題解決排查方式一在本地或者測試環境模擬生產環境排查方式二使用命令java -jar執行一下生產的包問題發現最近在生產環境啟動時報了一個錯誤束手無策因為本地和測試環境都沒有出現這個問題。完整的錯誤信息如圖環境如下Nacos版本Nacos2.2.3SpringCloud版本Spring Cloud 2023.0.13JDK版本17問題解決本來以為baidu能給我答案最后發現根本搜不到有關該錯誤的文章。然后就開始了苦逼的排查之路。排查方式一在本地或者測試環境模擬生產環境然后我本地搭建了一個和生產環境一模一樣的Nacos版本然后將配置文件改成本地的地址示例代碼如下spring:cloud:nacos:config:server-addr:127.0.0.1:8848discovery:server-addr:127.0.0.1:8848然后啟動項目未發現異常情況。排查方式二使用命令java -jar執行一下生產的包找到從生產上下載的包打開cmd窗口執行命令java-jarxxx.jar然后發現問題出現了后來我又陸續切換了好幾個分支打包后重試均出現該問題。神奇的很命令啟動有這個問題Idea啟動就沒這個問題。只要能復現問題就好辦然后就開始定位問題我把該項目的所有代碼全刪了然后打包重新運行發現正常啟動沒有異常錯誤。然后就一個類一個類的刪最后定位到一個初始化Bean的方法上面示例代碼如下RestControllerpublicclassAppControllerimplementsInitializingBean{ResourceprivateEchoServiceechoService;OverridepublicvoidafterPropertiesSet()throwsException{echoService.echo(hello);}}當我把afterPropertiesSet()方法中的代碼注釋打包后啟動依舊沒有發現問題。最終定位在RPC接口的問題上。回過頭去看日志你會發現在日志中第一次出現錯誤的位置結合上下文基本上可以定位問題所在位置。然后再來分析為什么會出現這種情況在Spring Bean的afterPropertiesSet()初始化階段訪問了Nacos客戶端相關資源Nacos服務發現來獲取服務地址間接依賴Nacos但此時Nacos客戶端尚未完成初始化導致依賴的FailoverReactor等組件為null最終觸發空指針異常。雖然Nacos沒有注冊完成那為什么RPC接口卻成功響應結果了呢Nacos服務發現的核心功能已臨時可用但內部故障轉移Failover組件的初始化滯后導致首次調用成功后后續的故障轉移檢查觸發空指針異常。為什么該錯誤不會影響項目正常運行Nacos客戶端的FailoverReactor故障轉移組件屬于輔助功能其初始化異常通常發生在獨立的異步線程Nacos內部的定時任務線程每5秒執行一次所以導致日志不斷增長為什么Idea啟動正常使用命令啟動就有問題兩種運行環境下的初始化時序、類加載機制或線程調度存在差異導致Nacos客戶端在IDEA中 “僥幸” 先于異步Feign調用完成初始化而打包后這種時序平衡被打破。IDEA運行默認會添加一些調試相關的JVM參數如-agentlib:jdwp用于調試這些參數可能會減慢JVM啟動速度或禁用某些類加載 / 初始化優化如提前編譯、類加載并行化知道問題所在和原因就可以很快解決這個問題我們可以等待所有Bean初始化完成后再去執行對應的方法這樣就不會出現容器未初始化完成的情況示例代碼如下RestControllerpublicclassAppController{ResourceprivateEchoServiceechoService;EventListener(ContextRefreshedEvent.class)// 指定監聽的事件類型publicvoidhandleContextRefreshed(){echoService.echo(hello);System.out.println(容器就緒處理后續操作...);}}ContextRefreshedEvent是Spring框架中一個重要的容器事件當Spring應用上下文ApplicationContext完成初始化或刷新時觸發。它標志著容器內所有Bean已完成創建、依賴注入和初始化包括PostConstruct方法執行完畢是監聽容器初始化完成的核心事件。如果你的錯誤并不是該問題導致的就需要考慮是否是依賴導致檢查依賴版本或者升級Nacos客戶端解決該問題。