最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

spring?boot微服務(wù)場景下apollo加載過程解析

 更新時(shí)間:2022年02月21日 11:34:50   作者:kl  
apollo?是一個(gè)開源的配置中心項(xiàng)目,功能很強(qiáng)大,apollo?本身的配置項(xiàng)并不復(fù)雜,但是因?yàn)榕渲玫穆窂教貏e多,非常容易搞混了,?所以本文試圖聚焦?spring-boot?的場景,在?spring-boot?微服務(wù)場景下,搞清楚?apollo-client的加載過程

集成使用

1、添加 gradle 依賴

implementation "com.ctrip.framework.apollo:apollo-client:1.6.0"

2、配置 application.properties

apollo 自身的配置共包含 9 項(xiàng),必要配置只有 3 項(xiàng),其他的都是可選的配置。apollo 在 spring-boot 環(huán)境下的配置命名和 System 參數(shù)的命名保持了一直,最終 spring 的配置會(huì)注入到 System 中,具體的邏輯下文分析。

必須配置

#應(yīng)用的ID
app.id = java-project
# apollo 的 config-service 服務(wù)發(fā)現(xiàn)地址
apollo.meta = http://apollo.meta
# 啟用 apollo
apollo.bootstrap.enabled = true

可選配置

# 在日志系統(tǒng)初始化前加載 apollo 配置
apollo.bootstrap.eagerLoad.enabled=true
# 加載的命名空間,默認(rèn)加載 application ,多個(gè)以逗號(hào)隔開
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 中的加載邏輯都在如上的代碼中了,代碼的關(guān)鍵是實(shí)現(xiàn)了兩個(gè) spring 生命周期的接口,

  • ApplicationContextInitializer

在被 ConfigurableApplicationContext.refresh()刷新之前初始化 ConfigurableApplicationContext 的回調(diào)接口。

  • EnvironmentPostProcessor

比 ApplicationContextInitializer 的加載時(shí)機(jī)還要提前,此時(shí) spring-boot 的日志系統(tǒng)還未初始化,

postProcessEnvironment 方法邏輯解析

1、初始化 System 的配置,將 spring 上下文中的配置(環(huán)境變量、System 參數(shù)、application.properties) 拷貝到 System 配置中, 如果 System 已經(jīng)存在同名的配置則跳過,保證了 -D 設(shè)置的 System 參數(shù)的最高優(yōu)先級(jí)。但是也帶來了一個(gè)隱含的問題,默認(rèn),apollo 的配置設(shè)計(jì)支持從環(huán)境變量中取值,也遵循了環(huán)境變量大寫的規(guī)范,將 System 參數(shù)的 "." 換成 "_" 拼接,然后變成大寫。 比如 apollo.meta 對(duì)應(yīng)環(huán)境變量的 APOLLO_META。但是在 spring-boot 的環(huán)境下,因?yàn)?spring 的配置系統(tǒng)默認(rèn)也會(huì)加載環(huán)境變量的配置,最終在環(huán)境變量里配置 apollo.meta 也會(huì)生效。甚至比正確配置的 APOLLO_META 環(huán)境變量值的優(yōu)先級(jí)還高。

2、根據(jù) apollo.bootstrap.eagerLoad.enabled 和 apollo.bootstrap.enabled 的配置來判斷是否在這個(gè)階段初始化 apollo。 postProcessEnvironment() 執(zhí)行的時(shí)候, 此時(shí)日志系統(tǒng)并未初始化,在這個(gè)階段加載 apollo,可以解決將日志配置托管到 apollo 里直接生效的問題。 帶來的問題是, 假如在這個(gè)階段的 apollo 加載出現(xiàn)問題,由于日志系統(tǒng)未初始化,看不到 apollo 的加載日志,不方便定位 apollo 的加載問題。 所以博主建議,如果有托管日志配置的場景,可以先不啟用 apollo.bootstrap.eagerLoad.enabled 的配置,等 apollo 集成完成后在啟用。
 

initialize 方法邏輯解析

1、根據(jù) apollo.bootstrap.enabled 的配置來判斷,是否在這個(gè)階段初始化 apollo ,如果此時(shí) spring 上下文中已經(jīng)包含了 apollo 的 PropertySources,代表 apollo 已經(jīng) 初始化過,則直接 return 掉

2、根據(jù) apollo.bootstrap.namespaces 的配置,默認(rèn)不配置為 "application" ,依次獲取對(duì)應(yīng)的 namespace 的配置, 并將配置使用 addFirst() 具有最高優(yōu)先級(jí)屬性源的設(shè)置方法, 添加到了 spring 的配置上下文中。這里解釋了為什么 apollo 的配置的優(yōu)先級(jí)最高,比 application.properties 中直接配置都要高, 這個(gè)優(yōu)先級(jí)的問題會(huì)經(jīng)常鬧烏龍,在本地開發(fā)調(diào)試階段,會(huì)直接在 application.properties 里調(diào)試配置,然后怎么改都不生效,因?yàn)?apollo 里 存在了同名的配置,啟動(dòng)的時(shí)候直接覆蓋了本地的配置。博主也犯過幾次這個(gè)錯(cuò)誤

結(jié)語

上面列出的 9 項(xiàng) apollo 配置,只有三項(xiàng)配置(apollo.bootstrap.enabled、apollo.bootstrap.eagerLoad.enabled、apollo.bootstrap.namespaces)是在 spring-boot 啟動(dòng)過程中用到的,其他的配置都被透傳到 System ,供 apollo 底層 sdk 使用。 基于此而發(fā)現(xiàn)了一個(gè) apollo 初始化配置時(shí)的小彩蛋,在 spring-boot 應(yīng)用里,如果使用環(huán)境變量來驅(qū)動(dòng) apollo 的配置項(xiàng),則帶 "." 風(fēng)格的配置(apollo.meta)和 "_" 風(fēng)格的大寫配置(APOLLO_META)的效果是等價(jià)的,并且如果兩個(gè)配置同時(shí)存在環(huán)境變量中,前者的優(yōu)先級(jí)要高于后者

以上就是spring boot微服務(wù)場景下apollo加載過程解析的詳細(xì)內(nèi)容,更多關(guān)于spring-boot下apollo加載過程的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Spring Cloud Gateway層限流實(shí)現(xiàn)過程

    Spring Cloud Gateway層限流實(shí)現(xiàn)過程

    這篇文章主要介紹了Spring Cloud Gateway層限流實(shí)現(xiàn)過程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • SpringCloud zookeeper作為注冊(cè)中心使用介紹

    SpringCloud zookeeper作為注冊(cè)中心使用介紹

    ZooKeeper由雅虎研究院開發(fā),是Google Chubby的開源實(shí)現(xiàn),后來托管到Apache,于2010年11月正式成為Apache的頂級(jí)項(xiàng)目。ZooKeeper是一個(gè)經(jīng)典的分布式數(shù)據(jù)一致性解決方案,致力于為分布式應(yīng)用提供一個(gè)高性能、高可用,且具有嚴(yán)格順序訪問控制能力的分布式協(xié)調(diào)服務(wù)
    2022-11-11
  • Java ArrayList類的基礎(chǔ)使用講解

    Java ArrayList類的基礎(chǔ)使用講解

    數(shù)組的長度是固定的,無法適應(yīng)數(shù)據(jù)變化的需求。為了解決這個(gè)問題,Java提供了另一個(gè)容器 java.util.ArrayList集合類,讓我們可以更便捷的存儲(chǔ)和操作對(duì)象數(shù)據(jù)。本文就將通過示例聊聊ArrayList類的基礎(chǔ)使用,感興趣的可以了解一下
    2022-10-10
  • java同步開篇入門簡單介紹

    java同步開篇入門簡單介紹

    java中的CountDownLatch、Semaphore、CyclicBarrier這些類又不屬于鎖,它們和鎖又有很多共同點(diǎn),都是為了協(xié)同多線程的執(zhí)行,都是一種同步器,所以這里就借用同步來取名字了,也就是“同步系列”的來源。下面小編來簡單介紹下
    2019-05-05
  • java項(xiàng)目中的絕對(duì)路徑和相對(duì)路徑用法說明

    java項(xiàng)目中的絕對(duì)路徑和相對(duì)路徑用法說明

    這篇文章主要介紹了java項(xiàng)目中的絕對(duì)路徑和相對(duì)路徑用法說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • SpringCloud之Feign遠(yuǎn)程接口映射的實(shí)現(xiàn)

    SpringCloud之Feign遠(yuǎn)程接口映射的實(shí)現(xiàn)

    這篇文章主要介紹了SpringCloud之Feign遠(yuǎn)程接口映射的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • Java編程使用卡片布局管理器示例【基于swing組件】

    Java編程使用卡片布局管理器示例【基于swing組件】

    這篇文章主要介紹了Java編程使用卡片布局管理器,結(jié)合實(shí)例形式分析了java基于swing組件的卡片布局管理器具體實(shí)現(xiàn)與使用技巧,需要的朋友可以參考下
    2018-01-01
  • Spring Boot 在啟動(dòng)時(shí)進(jìn)行配置文件加解密的方法詳解

    Spring Boot 在啟動(dòng)時(shí)進(jìn)行配置文件加解密的方法詳解

    這篇文章主要介紹了Spring Boot 在啟動(dòng)時(shí)進(jìn)行配置文件加解密的方法,本文通過實(shí)例給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-06-06
  • spring?boot項(xiàng)目中如何使用nacos作為配置中心

    spring?boot項(xiàng)目中如何使用nacos作為配置中心

    這篇文章主要介紹了spring?boot項(xiàng)目中如何使用nacos作為配置中心問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • 通過openOffice將office文件轉(zhuǎn)成pdf

    通過openOffice將office文件轉(zhuǎn)成pdf

    這篇文章主要介紹了通過openOffice將office文件轉(zhuǎn)成pdf,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-11-11

最新評(píng)論

象山县| 揭阳市| 安庆市| 华坪县| 大港区| 福建省| 南川市| 濮阳市| 攀枝花市| 青神县| 石河子市| 霍州市| 岳普湖县| 昭平县| 重庆市| 吐鲁番市| 青神县| 政和县| 福清市| 安龙县| 绥棱县| 普安县| 高阳县| 五家渠市| 武穴市| 临西县| 富蕴县| 兴国县| 洛扎县| 金乡县| 客服| 岑巩县| 临西县| 潜山县| 新化县| 曲松县| 棋牌| 石城县| 峨边| 太仆寺旗| 乡城县|