文章目录

  • Spring Boot整合Apollo
  • 下载编译Apollo源码
  • 使用IDE打开Apollo
  • 准备工作
  • 配置数据库
  • 修改配置文件
  • 启动Apollo
  • 客户端获取配置
  • 总结


Spring Boot整合Apollo

因为Spring Cloud Config需要配置一些东西才能热加载配置,而且没有图形界面,也没有灰度发布,诸多原因再加上Apollo开源了,所以很多公司还是比较青睐Apollo,所以今天花了半天时间研究了一下,试了一下本地模式,感觉还是挺不错的,废话不多说了。官网传送门

下载编译Apollo源码

当前最新版本为Apollo 1.6.1-Release,老规矩找个喜欢的文件夹clone。

// clone source code
git clone https://github.com/ctripcorp/apollo.git

// compile source code
cd apollo/
mvn install -Dmaven.test.skip=true
mvn idea:idea
或
mvn eclipse:eclipse

使用IDE打开Apollo

spring bot 整合pulsar spring整合apollo_spring

准备工作

想让Apollo跑起来需要配置最基础的3个模块,config、admin、portal,配置数据库信息和apollo-meta,我是用的本地MySQL 5.7。

配置数据库

在script下面的sql文件夹有两个sql文件,分别是config和portal需要用到的表,直接打开客户端运行脚本就可以了,不用多做介绍,执行完之后准备下一步,修改配置文件。

spring bot 整合pulsar spring整合apollo_配置文件_02

修改配置文件

3个工程的配置文件需要修改加上数据库配置

spring bot 整合pulsar spring整合apollo_客户端_03

# application.yml
datasource:
  url: jdbc:mysql://localhost:3306/apolloconfigdb?characterEncoding=utf8
  username: root
  password: 888888
# apollo-env.properties因为我只配置了dev,所以把其他的注释掉了
local.meta=http://localhost:8080
dev.meta=http://localhost:8080
#dev.meta=${dev_meta}
#fat.meta=${fat_meta}
#uat.meta=${uat_meta}
#lpt.meta=${lpt_meta}
#pro.meta=${pro_meta}
启动Apollo
  1. 启动服务:修改完配置之后就可以启动Apollo了,按顺序启动服务config -> admin -> portal,启动完成之后就可以通过localhost:8070访问Apollo控制台了。
  2. 创建项目:AppId要唯一,需要配置到客户端,应用名称填写客户端ApplicationName。
  3. 新增配置:key就是我们用@Value(“key”),所用到的,value就是我们配置值可以添加备注,然后我们默认选择DEV。
  4. 发布:点击发布按钮即可完成发布

客户端获取配置

源码中有demo部分,但不是我们常用的形式,所以就不以源码demo说了,我们IDEA创建一个最最最基础的Spring Boot project,添加上spring-boot-starter-web,和apollo-client,比较直观。

  1. 添加maven依赖
<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.6.0</version>
</dependency>
  1. 添加application.yml:添加application.yml配置,注意application-name和app-id,要与apollo保持一致。虽然application-name不一致也不影响,但是还是建议统一一下比较好。因为Apollo使用了8080,所以我这里改成8888。
server:
  port: 8888

spring:
  application:
    name: ddd-demo

apollo:
  bootstrap:
    eagerLoad:
      enabled: true
    enabled: true
    namespaces: application
  meta: http://localhost:8080
app:
  id: ddd

配置文件中的namespaces与下图对应,可以添加多个以英文逗号隔开。

spring bot 整合pulsar spring整合apollo_客户端_04

  1. 编写配置类:我这边用了两种方式来获取配置,一种是直接在需要的地方@Value,另一种是配置类。
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

import lombok.Data;

@Data
@Configuration
public class TestApolloConfig {

    @Value("${apollo}")
    private String apollo;

}
  1. 编写Controller:然后写了一个Controller,方便测试
@RestController
@RequestMapping("apollo")
public class ApolloController {

    @Value("${apollo}")
    private String apollo;

    @Resource
    private TestApolloConfig testApolloConfig;

    @GetMapping("test")
    public String test() {
        String apollo1 = testApolloConfig.getApollo();
        return "TestApolloConfig:" + apollo1 + ";@Value:" + this.apollo;
    }

}
  1. 启动完成
  2. 开始访问:http://localhost:8888/apollo/test
  3. 结果是对的,现在修改一下看会不会实时生效。修改配置项 -> 保存 -> 重新发布
  4. 刷新一下http://localhost:8888/apollo/test,成功。

总结

最简单的实践完成了,看了一下客户端更新配置的源码,远程获取配置的核心类RemoteConfigRepository,在构造的时候启动了schedulePeriodicRefresh,周期性获取,默认间隔实践是2s,在ConfigUtil中默认。
private long longPollingInitialDelayInMills = 2000;//2 seconds 后面专门再写一篇博客简单分析一下原理,Apollo配置动态加载的核心思路还是比较清晰的。

// 构造时初始化了一堆东西
public RemoteConfigRepository(String namespace) {
  m_namespace = namespace;
  m_configCache = new AtomicReference<>();
  m_configUtil = ApolloInjector.getInstance(ConfigUtil.class);
  m_httpUtil = ApolloInjector.getInstance(HttpUtil.class);
  m_serviceLocator = ApolloInjector.getInstance(ConfigServiceLocator.class);
  remoteConfigLongPollService = ApolloInjector.getInstance(RemoteConfigLongPollService.class);
  m_longPollServiceDto = new AtomicReference<>();
  m_remoteMessages = new AtomicReference<>();
  m_loadConfigRateLimiter = RateLimiter.create(m_configUtil.getLoadConfigQPS());
  m_configNeedForceRefresh = new AtomicBoolean(true);
  m_loadConfigFailSchedulePolicy = new ExponentialSchedulePolicy(m_configUtil.getOnErrorRetryInterval(),
      m_configUtil.getOnErrorRetryInterval() * 8);
  gson = new Gson();
  this.trySync();
  this.schedulePeriodicRefresh();
  this.scheduleLongPollingRefresh();
}