前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >TSE的Apollo配置中心托管上线了!Java 代码教学

TSE的Apollo配置中心托管上线了!Java 代码教学

原创
作者头像
Yagr Xu
修改2021-12-04 21:29:46
8730
修改2021-12-04 21:29:46
举报

配置中心是大部分服务的强需求。自己运维一套会各种踩坑。现在云上的TSE已经支持了Apollo的托管,一键部署~ 还不心动么?这篇文章,我来介绍一下如何使用Java Spring Framework接入Apollo

入门教学Demo

场景描述

  1. 从Apollo读取简单的Key-Value配置
  2. 从Apollo读取给予yaml/yml格式的Key-Value配置
  3. 从Apollo读取Key-Value配置,并映射到Java Class的属性中

Apollo配置中心状态

请在Apollo配置中心做如下配置:

  1. 在默认namespace - "application"下 创建简单的Key-Value配置
  2. 在同一个App.ID下创建另一个私有的namespace 并且是yaml/yml格式。并写一个简单的yaml/yml格式的Key-Value配置

Pom 依赖列表

代码语言:javascript
复制
      <dependencies>
            <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                  <groupId>com.ctrip.framework.apollo</groupId>
                  <artifactId>apollo-client</artifactId>
                  <version>1.8.0</version>
            </dependency>
            <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-configuration-processor</artifactId>
                  <optional>true</optional>
            </dependency>
            <dependency>
                  <groupId>org.projectlombok</groupId>
                  <artifactId>lombok</artifactId>
                  <optional>true</optional>
            </dependency>
            <dependency>
                  <groupId>com.ctrip.framework.apollo</groupId>
                  <artifactId>apollo-mockserver</artifactId>
                  <version>1.8.0</version>
                  <scope>test</scope>
            </dependency>
            <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-test</artifactId>
                  <scope>test</scope>
            </dependency>
      </dependencies>

spring.properties 属性文件内容

代码语言:javascript
复制
app.id=100001
apollo.meta=http://172.17.16.14:8080
apollo.cluster=default
apollo.bootstrap.enabled=true
apollo.bootstrap.namespaces = name.yaml
# namespace application will always be loaded by default

创建测试程序运行时的环境变量配置

代码语言:javascript
复制
export ENV=dev
export APOLLO_ACCESSKEY_SECRET=**************ac407c7

代码片段

  1. 直接用@Value读取Key-Value配置,和Spring Framework的标准玩法一致。
代码语言:javascript
复制
// Java Config
@Configuration
@EnableApolloConfig
public class ApolloConfig {

@Value("${app.key01:unknown}")
    String hello01;
    @Value("${app.key02:unknown}")
    String hello02;
    @Value("${app.key03:unknown}")
    String hello03;
    @Value("${app.key04:unknown}")
    String hello04;

    @PostConstruct // after the values are initialized, print their values
    void print() {
        System.out.println(this.getClass().getName() + " - " + hello01);
        System.out.println(this.getClass().getName() + " - " + hello02);
        System.out.println(this.getClass().getName() + " - " + hello03);
        System.out.println(this.getClass().getName() + " - " + hello04);
    }
}
  1. 使用Bean的方式,并且用@Value对属性进行注入
代码语言:javascript
复制
@Component
@RefreshScope
public class ValuesDemoBean {

@Value("${app.key01:unknown}")
    String hello01;
    @Value("${app.key02:unknown}")
    String hello02;
    @Value("${app.key03:unknown}")
    String hello03;
    @Value("${app.key04:unknown}")
    String hello04;

    @PostConstruct // after the values are initialized, print their values
    void print() {
        System.out.println(this.getClass().getName() + " - " + hello01);
        System.out.println(this.getClass().getName() + " - " + hello02);
        System.out.println(this.getClass().getName() + " - " + hello03);
        System.out.println(this.getClass().getName() + " - " + hello04);
    }
}
  1. 映射到Java Class的属性里
代码语言:javascript
复制
@Component
@RefreshScope
@ConfigurationProperties(prefix = "app") // map object to keys with prefix
public class ObjectDemoBean {

private String key01;
    private String key02;
    private String key03;
    private String key04;

    public void setKey01(String key01) {
        this.key01 = key01;
    }

    public void setKey02(String key02) {
        this.key02 = key02;
    }

    public void setKey03(String key03) {
        this.key03 = key03;
    }

    public void setKey04(String key04) {
        this.key04 = key04;
    }

    @PostConstruct // after the values are initialized, print their values
    void print() {
        System.out.println(this.getClass().getName() + " - " + key01);
        System.out.println(this.getClass().getName() + " - " + key02);
        System.out.println(this.getClass().getName() + " - " + key03);
        System.out.println(this.getClass().getName() + " - " + key04);
    }

}

代码效果

所有的键值都拿到了~ Voila!

从多个App ID获取配置信息

配置服务需要允许一个服务同时从多个AppID(配置源)获取配置信息, 比如通用信息. DNS 服务器地址, 数据库连接地址. 在下面的案例中,我们演示如何从多个AppID获取配置信息。

准备一个Global可见的namespace

  1. 首先在另外一个AppID(100002)下,创建一个叫global-demo的namespace

  1. 关联新创建的namespace到之前已经存在AppID(100001)下

  1. 之后切换到100001 AppID的界面,可以看到配置已经被显示出来了

私有Namespace vs 公有Namespace

私有的Namespace只能对当前的AppID可见,而公有的Namespace可以被关联到多个AppID下。所以生命周期是不同的。

改进排期

请注意

  1. 公有namespace当前还不支持yaml/json/properties等格式,只有最基础的Key-Value Pair格式。近期会排期支持。
  2. @ApolloConfigChangeListener 这个Annotation必须列出所有相关的Namespace。 比如: @ApolloConfigChangeListener({ "name.yaml", "application", "TEST1.global-demo" })

代码片段

代码语言:javascript
复制
@Component
@RefreshScope
@ConfigurationProperties(prefix = "global.url")
public class GlobalConfigDemoBean {

    private String mysql;
    private String dns;

    public void setMysql(String mysql) {
        this.mysql = mysql;
    }

    public void setDns(String dns) {
        this.dns = dns;
    }

    @PostConstruct // after the values are initialized, print their values
    void print() {
        System.out.println(this.getClass().getName() + " - " + mysql);
        System.out.println(this.getClass().getName() + " - " + dns);
    }
}

代码效果

就出来了!Fantastic!

配置自动刷新

@Value Annotation

基于@Value注入的消息会被自动更新,比如下面这个代码

代码语言:javascript
复制
@Configuration
@EnableApolloConfig
public class HelloConfig {

      @Value("${app.key01:unknown}")
      String hello01;
      @Value("${app.key02:unknown}")
      String hello02;

      @PostConstruct // after the values are initialized, print their values
      void print() {
            System.out.println(this.getClass().getName() + " - " + hello01);
            System.out.println(this.getClass().getName() + " - " + hello02);
      }
}

@ConfigurationProperties注入的代码

  1. 需要添加一个新的依赖
代码语言:javascript
复制
<dependency>
<groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-context</artifactId>
      <version>2.0.3.RELEASE</version>
</dependency>
  1. 然后在Bean的定义添加@RefreshScope注释
代码语言:javascript
复制
@Component
@RefreshScope
@ConfigurationProperties(prefix = "global.url")
  1. 添加如下的代码(@ApolloConfigChangeListener)
代码语言:javascript
复制
@Configuration
public class ApolloConfigRefreshBean implements ApplicationContextAware {

private ApplicationContext applicationContext;

    @Autowired
    RefreshScope refreshScope;

    // all related namespaces
    @ApolloConfigChangeListener({ "name.yaml", "application", "TEST1.global-demo" })
    private void someChangeHandler(ConfigChangeEvent changeEvent) {
        System.out.println("Apollo Auto-refresh Started");

        for (String changedKey : changeEvent.changedKeys()) {

            ConfigChange configChange = changeEvent.getChange(changedKey);
            String oldValue = configChange.getOldValue();
            String newValue = configChange.getNewValue();
            System.out.printf("[changedKey:%s,oldValue=%s, newValue:%s]", changedKey, oldValue, newValue);
        }

        refreshProperties(changeEvent);

        System.out.println("Apollo Auto-refresh done");
    }

    public void refreshProperties(ConfigChangeEvent changeEvent) {
        //all refreshScoped and annotated with @ConfigurationProperties
        this.applicationContext.publishEvent(new EnvironmentChangeEvent(changeEvent.changedKeys()));
        refreshScope.refreshAll();
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

代码效果

键值也自动刷新了 - Ja, voll!

如何运行这个Demo

手动配置项

  1. 使用正确的用户名密码登录Apollo
  2. 创建app.id 100001。
  3. 创建app.id 100002。
  4. 在100001 appid下创建key-value键值对,比如:app.key01:hey01 - 注意创建之后,需要发布才会生效
  5. 创建一个叫 "name"的私有namespace,并使用yaml格式。写一些yaml格式的内容,如下。
代码语言:javascript
复制
app:
  key01: hello01
  key02: hello02
  1. 在appid 100002下创建一个叫"global-demo"的公有 namespace,并且把它关联到appid 100001。

启动Java程序

下面的配置会加载所有在app.id 100001的namespace application下的键值。

代码语言:javascript
复制
app.id=100001
apollo.meta=http://[apollo-meta-server]:8080
apollo.cluster=default
apollo.bootstrap.enabled=true

如果你想加载更多的namespace,比如yaml等,需要写如下的配置 apollo.bootstrap.namespaces = name.yaml,TEST1.global-demo

代码语言:javascript
复制
app.id=100001
apollo.meta=http://[apollo-meta-server]:8080
apollo.cluster=default
apollo.bootstrap.enabled=true
apollo.bootstrap.namespaces = name.yaml,TEST1.global-demo
# 这里关联namespace格式是[original-app.id].[namespace]

如何Mock本地Unit Test

使用这个文档 来构建Mock Unit Test

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 入门教学Demo
    • 场景描述
      • Apollo配置中心状态
        • Pom 依赖列表
          • spring.properties 属性文件内容
            • 创建测试程序运行时的环境变量配置
              • 代码片段
                • 代码效果
                • 从多个App ID获取配置信息
                  • 准备一个Global可见的namespace
                    • 私有Namespace vs 公有Namespace
                      • 改进排期
                        • 代码片段
                          • 代码效果
                          • 配置自动刷新
                            • @Value Annotation
                              • 用@ConfigurationProperties注入的代码
                                • 代码效果
                                • 如何运行这个Demo
                                  • 手动配置项
                                    • 启动Java程序
                                      • 如何Mock本地Unit Test
                                      相关产品与服务
                                      微服务引擎 TSE
                                      微服务引擎(Tencent Cloud Service Engine)提供开箱即用的云上全场景微服务解决方案。支持开源增强的云原生注册配置中心(Zookeeper、Nacos 和 Apollo),北极星网格(腾讯自研并开源的 PolarisMesh)、云原生 API 网关(Kong)以及微服务应用托管的弹性微服务平台。微服务引擎完全兼容开源版本的使用方式,在功能、可用性和可运维性等多个方面进行增强。
                                      领券
                                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档