問題描述
Apollo報錯,找不到apoll.meta,但是明明配置了apollo-env.properties到apollo-client內了。
apollo-env.properties
pro.meta=http://apollo.xxxx.com:81
問題分析
因公司內部使用的 ctrip Apollo用了較早的版本,期間經過一次升級,而我算是Apollo的忠實用戶,使用時間超過兩年。
因此,我恰好知道,Apollo稍早的版本,沒有將Apollo-client發布到 中央倉庫,因為 Apollo-client的內部包含了編譯期間指定的apollo-env.properties文件,
而為了發布到中央倉庫,不能使用此方式將自己公司的meta地址放入其中,因此Apollo增加了一種配置方式:通過JVM參數等方式指定 apollo 的meta Server地址。
公司Maven倉庫內的apollo-client內是含有apollo-env.properties。因此原則上Apollo不需要再配置。
而為什么報錯呢?
問題原因
Apollo的 Meta 地址獲取邏輯,采用JAVA的SPI實現
package com.ctrip.framework.apollo.core.spi;
import com.ctrip.framework.apollo.core.enums.Env;
/**
* @since 1.0.0
*/
public interface MetaServerProvider extends Ordered {
/**
* Provide the Apollo meta server address, could be a domain url or comma separated ip addresses, like http://1.2.3.4:8080,http://2.3.4.5:8080.
* <br/>
* In production environment, we suggest using one single domain like http://config.xxx.com(backed by software load balancers like nginx) instead of multiple ip addresses
*/
String getMetaServerAddress(Env targetEnv);
}
而該接口有兩個實現
默認實現:
public class DefaultMetaServerProvider implements MetaServerProvider
第二個實現:(舊版本)
public class LegacyMetaServerProvider implements MetaServerProvider
正常情況下,apollo應該使用二者之一的Provider。
如果JVM啟動的時候,使用了DefaultMetaServerProvider,這種情況沒有配置JVM參數 apollo.meta,那么將報錯,找不到meta server。
那為什么公司的倉庫內 apollo-client 有apollo-env.properties 但是沒有使用LegacyMetaServerProvider ?
問題解決
因為踩坑次數多了,自然想到去jar包內看看,經過檢查發現 jar內的META-INF確實有apollo-env.properties。
問題就出在,apollo-core-1.3.0-xxx.jar!/META-INF/services/com.ctrip.framework.apollo.core.spi.MetaServerProvider內是:
com.ctrip.framework.apollo.internals.DefaultMetaServerProvider
而
apollo-client-1.3.0-xxx.jar!/META-INF/services/com.ctrip.framework.apollo.core.spi.MetaServerProvider內是:
com.ctrip.framework.apollo.core.internals.LegacyMetaServerProvider
最終原因在於,maven打包工具有 maven-jar-plugin,maven-assembly-plugin, maven-shaded-plugin。
如果使用spring-boot-maven-plugin,雖然內置有maven-shaded-plugin,但是他根本不知道apollo的。
這些情況最終導致了不確定性,JVM加載的Jar包順序不一樣,或者打包的順序,導致一個SPI文件被另一個文件覆蓋掉了,因此丟失了一個provider實現。
但是只有maven-shaded-plugin,可以經過配置TRANSFORMER,將這兩種合並到一個com.ctrip.framework.apollo.core.spi.MetaServerProvider文件內。
最終解決方案
保持apollo-client和apollo-core包內 的/META-INF/services/com.ctrip.framework.apollo.core.spi.MetaServerProvider
有兩個Provider,分別寫一行。
或者聯系相關人員,將這兩個文件的內容保持一致,並給出適用的使用方案。例如jar包內附帶了pro.meta等變量的時候,提供LegacyMetaServerProvider。
如果沒有附帶,則要求使用人員自行配置 apollo.meta。
剛好這篇文章解決了我另一篇同樣是關於Apollo和Dubbo集成的文章中遇到的問題。
解決Dubbo 2.7.3版本使用ConfigCenterConfig集成Apollo No Provider found的問題
