spring boot微服务场景下apollo加载过程实例分析
本篇内容主要讲解“springboot微服务场景下apollo加载过程实例分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“springboot微服务场景下apollo加载过程实例分析”吧!
集成使用1、添加 gradle 依赖implementation"com.ctrip.framework.apollo:apollo-client:1.6.0"2、配置 application.properties
apollo 自身的配置共包含 9 项,必要配置只有 3 项,其他的都是可选的配置。apollo 在 spring-boot 环境下的配置命名和 System 参数的命名保持了一直,最终 spring 的配置会注入到 System 中,具体的逻辑下文分析。
必须配置#应用的IDapp.id=java-project#apollo的config-service服务发现地址apollo.meta=http://apollo.meta#启用apolloapollo.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加载过程解析
publicclassApolloApplicationContextInitializerimplementsApplicationContextInitializer,EnvironmentPostProcessor,Ordered{publicstaticfinalintDEFAULT_ORDER=0;privatestaticfinalLoggerlogger=LoggerFactory.getLogger(ApolloApplicationContextInitializer.class);privatestaticfinalSplitterNAMESPACE_SPLITTER=Splitter.on(",").omitEmptyStrings().trimResults();privatestaticfinalString[]APOLLO_SYSTEM_PROPERTIES={"app.id",ConfigConsts.APOLLO_CLUSTER_KEY,"apollo.cacheDir","apollo.accesskey.secret",ConfigConsts.APOLLO_META_KEY,PropertiesFactory.APOLLO_PROPERTY_ORDER_ENABLE};privatefinalConfigPropertySourceFactoryconfigPropertySourceFactory=SpringInjector.getInstance(ConfigPropertySourceFactory.class);privateintorder=DEFAULT_ORDER;@Overridepublicvoidinitialize(ConfigurableApplicationContextcontext){ConfigurableEnvironmentenvironment=context.getEnvironment();if(!environment.getProperty(PropertySourcesConstants.APOLLO_BOOTSTRAP_ENABLED,Boolean.class,false)){logger.debug("Apollobootstrapconfigisnotenabledforcontext{},seeproperty:${{}}",context,PropertySourcesConstants.APOLLO_BOOTSTRAP_ENABLED);return;}logger.debug("Apollobootstrapconfigisenabledforcontext{}",context);initialize(environment);}/***InitializeApolloConfigurationsJustafterenvironmentisready.**@paramenvironment*/protectedvoidinitialize(ConfigurableEnvironmentenvironment){if(environment.getPropertySources().contains(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME)){//alreadyinitializedreturn;}Stringnamespaces=environment.getProperty(PropertySourcesConstants.APOLLO_BOOTSTRAP_NAMESPACES,ConfigConsts.NAMESPACE_APPLICATION);logger.debug("Apollobootstrapnamespaces:{}",namespaces);ListnamespaceList=NAMESPACE_SPLITTER.splitToList(namespaces);CompositePropertySourcecomposite=newCompositePropertySource(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME);for(Stringnamespace:namespaceList){Configconfig=ConfigService.getConfig(namespace);composite.addPropertySource(configPropertySourceFactory.getConfigPropertySource(namespace,config));}environment.getPropertySources().addFirst(composite);}/***Tofillsystempropertiesfromenvironmentconfig*/voidinitializeSystemProperty(ConfigurableEnvironmentenvironment){for(StringpropertyName:APOLLO_SYSTEM_PROPERTIES){fillSystemPropertyFromEnvironment(environment,propertyName);}}privatevoidfillSystemPropertyFromEnvironment(ConfigurableEnvironmentenvironment,StringpropertyName){if(System.getProperty(propertyName)!=null){return;}StringpropertyValue=environment.getProperty(propertyName);if(Strings.isNullOrEmpty(propertyValue)){return;}System.setProperty(propertyName,propertyValue);}/****InordertoloadApolloconfigurationsasearlyasevenbeforeSpringloadingloggingsystemphase,*thisEnvironmentPostProcessorcanbecalledJustAfterConfigFileApplicationListenerhassucceeded.***Theprocessingsequencewouldbelikethis:*LoadBootstrappropertiesandapplicationproperties----->loadApolloconfigurationproperties---->InitializeLoggingsystems**@paramconfigurableEnvironment*@paramspringApplication*/@OverridepublicvoidpostProcessEnvironment(ConfigurableEnvironmentconfigurableEnvironment,SpringApplicationspringApplication){//shouldalwaysinitializesystempropertieslikeapp.idinthefirstplaceinitializeSystemProperty(configurableEnvironment);BooleaneagerLoadEnabled=configurableEnvironment.getProperty(PropertySourcesConstants.APOLLO_BOOTSTRAP_EAGER_LOAD_ENABLED,Boolean.class,false);//EnvironmentPostProcessorshouldnotbetriggeredifyoudon'twantApolloLoadingbeforeLoggingSystemInitializationif(!eagerLoadEnabled){return;}BooleanbootstrapEnabled=configurableEnvironment.getProperty(PropertySourcesConstants.APOLLO_BOOTSTRAP_ENABLED,Boolean.class,false);if(bootstrapEnabled){initialize(configurableEnvironment);}}/***@since1.3.0*/@OverridepublicintgetOrder(){returnorder;}/***@since1.3.0*/publicvoidsetOrder(intorder){this.order=order;}}
apollo 在 spring-boot 中的加载逻辑都在如上的代码中了,代码的关键是实现了两个 spring 生命周期的接口,
ApplicationContextInitializer
在被 ConfigurableApplicationContext.refresh()刷新之前初始化 ConfigurableApplicationContext 的回调接口。
EnvironmentPostProcessor
比 ApplicationContextInitializer 的加载时机还要提前,此时 spring-boot 的日志系统还未初始化,
postProcessEnvironment 方法逻辑解析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 里 存在了同名的配置,启动的时候直接覆盖了本地的配置。
到此,相信大家对“springboot微服务场景下apollo加载过程实例分析”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。