您好,登錄后才能下訂單哦!
本篇內容主要講解“spring boot微服務場景下apollo加載過程實例分析”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“spring boot微服務場景下apollo加載過程實例分析”吧!
implementation "com.ctrip.framework.apollo:apollo-client:1.6.0"
apollo 自身的配置共包含 9 項,必要配置只有 3 項,其他的都是可選的配置。apollo 在 spring-boot 環境下的配置命名和 System 參數的命名保持了一直,最終 spring 的配置會注入到 System 中,具體的邏輯下文分析。
#應用的ID app.id = java-project # apollo 的 config-service 服務發現地址 apollo.meta = http://apollo.meta # 啟用 apollo apollo.bootstrap.enabled = true
# 在日志系統初始化前加載 apollo 配置 apollo.bootstrap.eagerLoad.enabled=true # 加載的命名空間,默認加載 application ,多個以逗號隔開 apollo.bootstrap.namespaces = application # apollo 的安全拉取 secret 配置 apollo.accesskey.secret = xx # 集群配置 apollo.cluster = hk # 緩存路徑 apollo.cacheDir = /opt # 是否保持和 apollo 配置頁面的配置順序一致 apollo.property.order.enable = true
public class ApolloApplicationContextInitializer implements ApplicationContextInitializer, EnvironmentPostProcessor, Ordered { public static final int DEFAULT_ORDER = 0; private static final Logger logger = LoggerFactory.getLogger(ApolloApplicationContextInitializer.class); private static final Splitter NAMESPACE_SPLITTER = Splitter.on(",").omitEmptyStrings().trimResults(); private static final String[] APOLLO_SYSTEM_PROPERTIES = {"app.id", ConfigConsts.APOLLO_CLUSTER_KEY, "apollo.cacheDir", "apollo.accesskey.secret", ConfigConsts.APOLLO_META_KEY, PropertiesFactory.APOLLO_PROPERTY_ORDER_ENABLE}; private final ConfigPropertySourceFactory configPropertySourceFactory = SpringInjector.getInstance(ConfigPropertySourceFactory.class); private int order = DEFAULT_ORDER; @Override public void initialize(ConfigurableApplicationContext context) { ConfigurableEnvironment environment = context.getEnvironment(); if (!environment.getProperty(PropertySourcesConstants.APOLLO_BOOTSTRAP_ENABLED, Boolean.class, false)) { logger.debug("Apollo bootstrap config is not enabled for context {}, see property: ${{}}", context, PropertySourcesConstants.APOLLO_BOOTSTRAP_ENABLED); return; } logger.debug("Apollo bootstrap config is enabled for context {}", context); initialize(environment); } /** * Initialize Apollo Configurations Just after environment is ready. * * @param environment */ protected void initialize(ConfigurableEnvironment environment) { if (environment.getPropertySources().contains(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME)) { //already initialized return; } String namespaces = environment.getProperty(PropertySourcesConstants.APOLLO_BOOTSTRAP_NAMESPACES, ConfigConsts.NAMESPACE_APPLICATION); logger.debug("Apollo bootstrap namespaces: {}", namespaces); ListnamespaceList = NAMESPACE_SPLITTER.splitToList(namespaces); CompositePropertySource composite = new CompositePropertySource(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME); for (String namespace : namespaceList) { Config config = ConfigService.getConfig(namespace); composite.addPropertySource(configPropertySourceFactory.getConfigPropertySource(namespace, config)); } environment.getPropertySources().addFirst(composite); } /** * To fill system properties from environment config */ void initializeSystemProperty(ConfigurableEnvironment environment) { for (String propertyName : APOLLO_SYSTEM_PROPERTIES) { fillSystemPropertyFromEnvironment(environment, propertyName); } } private void fillSystemPropertyFromEnvironment(ConfigurableEnvironment environment, String propertyName) { if (System.getProperty(propertyName) != null) { return; } String propertyValue = environment.getProperty(propertyName); if (Strings.isNullOrEmpty(propertyValue)) { return; } System.setProperty(propertyName, propertyValue); } /** * * In order to load Apollo configurations as early as even before Spring loading logging system phase, * this EnvironmentPostProcessor can be called Just After ConfigFileApplicationListener has succeeded. * * * The processing sequence would be like this: * Load Bootstrap properties and application properties -----> load Apollo configuration properties ----> Initialize Logging systems * * @param configurableEnvironment * @param springApplication */ @Override public void postProcessEnvironment(ConfigurableEnvironment configurableEnvironment, SpringApplication springApplication) { // should always initialize system properties like app.id in the first place initializeSystemProperty(configurableEnvironment); Boolean eagerLoadEnabled = configurableEnvironment.getProperty(PropertySourcesConstants.APOLLO_BOOTSTRAP_EAGER_LOAD_ENABLED, Boolean.class, false); //EnvironmentPostProcessor should not be triggered if you don't want Apollo Loading before Logging System Initialization if (!eagerLoadEnabled) { return; } Boolean bootstrapEnabled = configurableEnvironment.getProperty(PropertySourcesConstants.APOLLO_BOOTSTRAP_ENABLED, Boolean.class, false); if (bootstrapEnabled) { initialize(configurableEnvironment); } } /** * @since 1.3.0 */ @Override public int getOrder() { return order; } /** * @since 1.3.0 */ public void setOrder(int order) { this.order = order; } }
apollo 在 spring-boot 中的加載邏輯都在如上的代碼中了,代碼的關鍵是實現了兩個 spring 生命周期的接口,
ApplicationContextInitializer
在被 ConfigurableApplicationContext.refresh()刷新之前初始化 ConfigurableApplicationContext 的回調接口。
EnvironmentPostProcessor
比 ApplicationContextInitializer 的加載時機還要提前,此時 spring-boot 的日志系統還未初始化,
1、初始化 System 的配置,將 spring 上下文中的配置(環境變量、System 參數、application.properties) 拷貝到 System 配置中, 如果 System 已經存在同名的配置則跳過,保證了 -D 設置的 System 參數的最高優先級。但是也帶來了一個隱含的問題,默認,apollo 的配置設計支持從環境變量中取值,也遵循了環境變量大寫的規范,將 System 參數的 "." 換成 "_" 拼接,然后變成大寫。 比如 apollo.meta 對應環境變量的 APOLLO_META。但是在 spring-boot 的環境下,因為 spring 的配置系統默認也會加載環境變量的配置,最終在環境變量里配置 apollo.meta 也會生效。甚至比正確配置的 APOLLO_META 環境變量值的優先級還高。
2、根據 apollo.bootstrap.eagerLoad.enabled 和 apollo.bootstrap.enabled 的配置來判斷是否在這個階段初始化 apollo。 postProcessEnvironment() 執行的時候, 此時日志系統并未初始化,在這個階段加載 apollo,可以解決將日志配置托管到 apollo 里直接生效的問題。 帶來的問題是, 假如在這個階段的 apollo 加載出現問題,由于日志系統未初始化,看不到 apollo 的加載日志,不方便定位 apollo 的加載問題。 所以博主建議,如果有托管日志配置的場景,可以先不啟用 apollo.bootstrap.eagerLoad.enabled 的配置,等 apollo 集成完成后在啟用。
1、根據 apollo.bootstrap.enabled 的配置來判斷,是否在這個階段初始化 apollo ,如果此時 spring 上下文中已經包含了 apollo 的 PropertySources,代表 apollo 已經 初始化過,則直接 return 掉
2、根據 apollo.bootstrap.namespaces 的配置,默認不配置為 "application" ,依次獲取對應的 namespace 的配置, 并將配置使用 addFirst() 具有最高優先級屬性源的設置方法, 添加到了 spring 的配置上下文中。這里解釋了為什么 apollo 的配置的優先級最高,比 application.properties 中直接配置都要高, 這個優先級的問題會經常鬧烏龍,在本地開發調試階段,會直接在 application.properties 里調試配置,然后怎么改都不生效,因為 apollo 里 存在了同名的配置,啟動的時候直接覆蓋了本地的配置。
到此,相信大家對“spring boot微服務場景下apollo加載過程實例分析”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。