阿毛
It's me !
想你所想

Apollo之快速使用

原先总结的内容,这里迁移过来。
这里主要阐述的是,使用Apollo在本地开发阶段的过程,主要以SpringBoot项目为主。

一、首先,本地可搭建一套简易的Apollo

Apollo作者提供了一个可供快速上手部署的demo。具体操作参照下方链接内容一步步进行即可:Quick-Start
然后进入代码开发。

二、依赖客户端,这里以maven为例

Apollo的客户端jar包已经上传到中央仓库,应用在实际使用时只需要按照如下方式引入即可。

    <dependency>
        <groupId>com.ctrip.framework.apollo</groupId>
        <artifactId>apollo-client</artifactId>
        <version>1.4.0</version>
    </dependency>

三、初始化Apollo中项目配置(appId、namespace等)

创建项目

https://file.blog.humh.cn/2020/06/d2b5ca33bd970f64a6301fa75ae2eb22-4.png

创建后,默认会创建“application” namespace,我们可以进行一些SpringBoot项目的初始化配置,如server.port等。

四、项目代码配置文件

项目使用Apollo有一些必要配置,Apollo客户端依赖于AppId,Apollo Meta Server等环境信息来工作。还有一些可选配置等,同时对于SpringBoot项目特殊的配置方式。

1、appId

这里推荐SpringBoot项目使用“app.properties”配置文件的方式配置appId。具体如下:
确保classpath:/META-INF/app.properties文件存在,并且其中内容形如app.id=YOUR-APP-ID
文件位置如下

https://file.blog.humh.cn/2020/06/d2b5ca33bd970f64a6301fa75ae2eb22-5.png

2、meta server

Apollo支持应用在不同的环境有不同的配置,所以需要在运行提供给Apollo客户端当前环境的Apollo Meta Server信息。默认情况下,meta server和config service是部署在同一个JVM进程,所以meta server的地址就是config service的地址。

为了实现meta server的高可用,推荐通过SLB(Software Load Balancer)做动态负载均衡。Meta server地址也可以填入IP,如http://1.1.1.1:8080,http://2.2.2.2:8080,不过生产环境还是建议使用域名(走slb),因为机器扩容、缩容等都可能导致IP列表的变化。

因为我们这里部署的是Quick-start apollo,所以meta server的地址就是config service的地址,直接指定config-server即可。

推荐这样配置:在Java程序启动脚本中,可以指定-Dapollo.meta=http://config-service-url。

如本地IDEA开发时,在启动Application Main时,配置,如下图

https://file.blog.humh.cn/2020/06/d2b5ca33bd970f64a6301fa75ae2eb22-6.png

3、Environment

这里再配置下可选配置,因为quick-start apollo 默认了环境只有dev,需要客户端连接读取配置时指定。

同样本地开发推荐在Java程序启动脚本中,可以指定-Denv=YOUR-ENVIRONMENT,如上图中的VM options中指定了“-Dev=dev”。

4、最后就是配置项目resources下的“application.yml”或者“application.properties”

SpringBoot除了支持Spring XML集成方式以及Java代码集成方式以外,还支持通过application.properties/bootstrap.properties来配置,该方式能使配置在更早的阶段注入,比如使用@ConditionalOnProperty的场景或者是有一些spring-boot-starter在启动阶段就需要读取配置做一些事情(如dubbo-spring-boot-project),同时因为spring-boot-starter做了很多起步依赖初始化,不同于以往的SSM项目,我们在xml中配置datasource,容器bean配置等直接初始化指定bean。而SpringBoot只需要直接写配置值就行。所以对于Spring Boot环境建议通过以下方式来接入Apollo(需要0.10.0及以上版本)。使用方式很简单,只需要在application.properties/bootstrap.properties中按照如下样例配置即可。

1)、注入默认application namespace的配置示例

    # will inject 'application' namespace in bootstrap phase
    apollo.bootstrap.enabled = true

2)、注入非默认application namespace或多个namespace的配置示例

   apollo.bootstrap.enabled = true
   # will inject 'application', 'FX.apollo' and 'application.yml' namespaces in bootstrap phase
   apollo.bootstrap.namespaces = application,FX.apollo,application.yml

这里我直接将配置放在了“application-dev.yml”中

https://file.blog.humh.cn/2020/06/d2b5ca33bd970f64a6301fa75ae2eb22-7.png

五、代码中读取配置

除了容器启动时会从apollo中读取配置,我们还将经常会在代码通过诸如@Value或者@ConfigurationProperties去读取配置。

所以着重说这两个,以@Value为例,与日常使用无任何差异。不管你配合使用@Component还是@Configuration均可实时更新 只是两个注解本身的区别。同样配置读取也是Spring的规则,多个一样的property key,只加载第一个。对于apollo配置来说,“apollo.bootstrap.namespaces”配置的namespace,哪个namespace在前,就先读取哪个。假设datasource namespace下有key为“name”的配置了,application namespace下也有key为“name”的配置,按上图的中namespace顺序,则只加载application中的,不会再加载datasource中的“name”了。同理如果datasource中没有,则读取application中的。

对于@ConfigurationProperties注解比较特殊,因为apollo没办法配置改变时去实时刷新该bean,这也是由于该注解本身的特性,所以需要进行额外的处理。
@ConfigurationProperties如果需要在Apollo配置变化时自动更新注入的值,需要配合使用EnvironmentChangeEventRefreshScope。相关代码实现,可以参考apollo-use-cases项目中的ZuulPropertiesRefresher.java和apollo-demo项目中的SampleRedisConfig.java以及SpringBootApolloRefreshConfig.java

代码:将@RefreshScope注解标记在@ConfigurationProperties修饰的类上,同时编写apollo监听器,如果监听到该类的配置发生变化,则手动刷新该bean。

@ConfigurationProperties(prefix = "nwpu")
@Component("nwpuDTO")
@RefreshScope
public class NwpuDTO {
 
    /**
     * 学校名
     */
    private String name;
 
    /**
     * 联系电话
     */
    private String url;
 
    /**
     * 邮编
     */
    private int postCode;
 
    /**
     * 学校性质
     */
    private String[] properties;
 
    /**
     * 学校地点
     */
    private String location;
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getUrl() {
        return url;
    }
 
    public void setUrl(String url) {
        this.url = url;
    }
 
    public int getPostCode() {
        return postCode;
    }
 
    public void setPostCode(int postCode) {
        this.postCode = postCode;
    }
 
    public String[] getProperties() {
        return properties;
    }
 
    public void setProperties(String[] properties) {
        this.properties = properties;
    }
 
    public String getLocation() {
        return location;
    }
 
    public void setLocation(String location) {
        this.location = location;
    }
}
@Configuration
public class ApolloConfig {
 
    @Autowired
    private RefreshScope refreshScope;
 
    @ApolloConfigChangeListener(value = "application", interestedKeyPrefixes = "nwpu")
    private void onChangeToApplication(ConfigChangeEvent changeEvent) {
        // 如果@ConfigurationProperties配置发生变化,则需要手动刷新
        refreshScope.refresh("nwpuDTO");
    }
 
}

监听器的内容可参考这个:Apollo 监听器ConfigListener

六、测试

可写接口打印出读取的配置的实例。

七、注意

对于SpringBoot项目,如果指定了apollo.bootstrap.namespaces,哪个namespace在前就先加载。
相当于已经注入环境为apollo,并且namespace开启,所以根据配置文件生效顺序可知,如果apollo中有配置则apollo,只会成功加载一次,如果apollo中没有,则加载本地配置。
如果apollo.bootstrap.namespaces只配置了datasource,那么只有dataSource生效。如果再某个类上标记@EnableApolloConfig,无论在何处标记都表示又开启一个或多个namespace下的配置,默认为application。
那么会先读取datasource下的配置,然后application,再本地。可以理解为apollo.bootstrap.namespaces会注册environment(有且仅有一个,范围为datasource),然后@EnableApolloConfig又会将该environment范围变成
datasource和application,然后配置是从environment中取得。  (源码待研究,内部加载机制)
记住:有且仅有一个environment

配置读取顺序:命令行参数 > java system变量 -D > Apollo > 本地配置文件 

humh

文章作者

站长本人,一个憨批!

发表回复

textsms
account_circle
email

想你所想

Apollo之快速使用
原先总结的内容,这里迁移过来。这里主要阐述的是,使用Apollo在本地开发阶段的过程,主要以SpringBoot项目为主。 一、首先,本地可搭建一套简易的Apollo Apollo作者提供了一个可…
扫描二维码继续阅读
2020-06-01