扫一扫下方二维码,关注本站官方公众号
获取永久解锁本站全部文章的验证码
还能不定期领现金红包

springboot2.0整合使用Apollo配置中心-Go语言中文社区

springboot2.0整合使用Apollo配置中心


springboot 版本:2.1.9.RELEASE

Apollo 版本:1.4.0

一、背景

对于传统的单体应用,通常使用配置文件管理所有配置。比如Spring Boot开发的单体应用,配置内容可以放在application.yml文件,需要切换环境的话可以设置多个Profile并在启动应用时指定spring.pfofiles.active={profile}。

然而,在微服务架构中,配置管理一般有以下需求

  • 集中管理配置:一个使用微服务架构的应用系统可能会包含成千上万个微服务,因此集中管理配置是非常有必要的。
  • 不同环境不同配置:例如,数据源配置在不同的环境(开发、测试、预发布、生产等)中是不同的。
  • 运行期间可动态调整:例如,可根据各个微服务的负载情况,动态调整数据源连接池大小或熔断阈值,并且在调整配置时不停止微服务。
  • 配置修改后可自动更新。如配置内容发生变化,微服务能够自动更新配置。

所以,对于微服务架构而言,一个通用的配置管理机制是必不可少的,常见做法是使用配置服务器管理配置。

不管你的微服务项目是否使用Spring Cloud,相对于Spring Cloud Config,Apollo都是更好的选择。

二、Apollo简介

Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。

服务端基于Spring Boot和Spring Cloud开发,打包后可以直接运行,不需要额外安装Tomcat等应用容器。

Java客户端不依赖任何框架,能够运行于所有Java运行时环境,同时对Spring/Spring Boot环境也有较好的支持。

更多介绍,请到GitHub了解:https://github.com/ctripcorp/apollo

 三、Apollo配置中心服务端

本文的重点在于Apollo在客户端的使用,所以Apollo服务端使用的是官网提供的 Quick Start(针对本地测试使用)。如果要部署到生产环境,还请另行参考分布式部署指南

1、准备工作

1)Java

服务端要求1.8+,客户端要求1.7+。由于Quick Start会在本地同时启动服务端和客户端,所以需要在本地安装Java 1.8+。

2)MySQL

Apollo的表结构对timestamp使用了多个default声明,所以需要5.6.5以上版本。

3)下载Apollo项目

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

4)创建数据库

创建以下两个数据库并导入初始化数据:

  • ApolloConfigDB
  • ApolloPortalDB

ApolloConfigDB 所在的文件目录:

${your_file_directory}apolloscriptssqlapolloconfigdb

ApolloPortalDB

${your_file_directory}apolloscriptssqlportaldb

在MySQL数据库中执行这两个SQL文件,完成数据库的创建和数据的初始化操作。

打包项目(build package)

将下载下来的 apollo 源码导入到idea中,我们需要关注的几个项目:

apollo-configserviceapollo-adminserviceapollo-protal
配置服务(meta server、eureka)配置管理服务apollo管理UI

找到 /apollo/scripts/build.bat(Linux 是 bulid.sh)

@echo off

rem apollo config db info
set apollo_config_db_url="jdbc:mysql://localhost:3306/ApolloConfigDB?characterEncoding=utf8"
set apollo_config_db_username="root"
set apollo_config_db_password=""

rem apollo portal db info
set apollo_portal_db_url="jdbc:mysql://localhost:3306/ApolloPortalDB?characterEncoding=utf8"
set apollo_portal_db_username="root"
set apollo_portal_db_password=""

rem meta server url, different environments should have different meta server addresses
set dev_meta="http://localhost:8080"
set fat_meta="http://someIp:8080"
set uat_meta="http://anotherIp:8080"
set pro_meta="http://yetAnotherIp:8080"

set META_SERVERS_OPTS=-Ddev_meta=%dev_meta% -Dfat_meta=%fat_meta% -Duat_meta=%uat_meta% -Dpro_meta=%pro_meta%

rem =============== Please do not modify the following content =============== 
rem go to script directory
cd "%~dp0"

cd ..

rem package config-service and admin-service
echo "==== starting to build config-service and admin-service ===="

call mvn clean package -DskipTests -pl apollo-configservice,apollo-adminservice -am -Dapollo_profile=github -Dspring_datasource_url=%apollo_config_db_url% -Dspring_datasource_username=%apollo_config_db_username% -Dspring_datasource_password=%apollo_config_db_password%

echo "==== building config-service and admin-service finished ===="

echo "==== starting to build portal ===="

call mvn clean package -DskipTests -pl apollo-portal -am -Dapollo_profile=github,auth -Dspring_datasource_url=%apollo_portal_db_url% -Dspring_datasource_username=%apollo_portal_db_username% -Dspring_datasource_password=%apollo_portal_db_password% %META_SERVERS_OPTS%

echo "==== building portal finished ===="

pause

更改数据库连接配置
 

rem apollo config db info
set apollo_config_db_url="jdbc:mysql://localhost:3306/ApolloConfigDB?characterEncoding=utf8"
set apollo_config_db_username="root"
set apollo_config_db_password="root"

rem apollo portal db info
set apollo_portal_db_url="jdbc:mysql://localhost:3306/ApolloPortalDB?characterEncoding=utf8"
set apollo_portal_db_username="root"
set apollo_portal_db_password="root"

更改 meta server(apollo-configservice/apollo-erueka) 地址

set dev_meta="http://localhost:8080"
set fat_meta="http://someIp:8080"
set uat_meta="http://anotherIp:8080"
set pro_meta="http://yetAnotherIp:8080"

修改完上面的配置之后,执行build.bat 批处理命令文件进行编译打包,在执行的过程中可能会出现一些异常(一般是maven依赖异常),自行百度解决之后,再重新执行。

打包成功之后,找到 apollo-configservice、apollo-adminservice、apollo-portal 下的 target 目录(build是执行 maven 的 package 命令),找到已经打好的三个jar包,copy 出来放到一个单独的目录(方便启动)。

进入jar 的当前目录,==依次==启动apollo-configservice、apollo-adminservice、apollo-portal 三个服务。

java -jar apollo-configservice-1.8.0-SNAPSHOT.jar
java -jar apollo-adminservice-1.8.0-SNAPSHOT.jar
java -jar apollo-portal-1.8.0-SNAPSHOT.jar

全部启动完成之后,打开浏览器输入:

http://localhost:8070 如果出现apollo 的登录界面,说明已经启动成功(登录名/密码:apollo/admin)。

http://localhost:8080 如果出现eureka 的管理界面,说明服务启动正常。

四 Apollo配置中心使用

1、创建项目,其中appid为springboot项目需要配置对应的 ,这个ID是应用的唯一标识

 

2、添加配置,此时添加的配置未发布 发布后生效。也可以回滚至上一个设置结果

 

五、Apollo配置中心客户端

 

1添加依赖

 <!-- https://mvnrepository.com/artifact/com.ctrip.framework.apollo/apollo-client -->
    <dependency>
      <groupId>com.ctrip.framework.apollo</groupId>
      <artifactId>apollo-client</artifactId>
      <version>1.4.0</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.ctrip.framework.apollo/apollo-core -->
    <dependency>
      <groupId>com.ctrip.framework.apollo</groupId>
      <artifactId>apollo-core</artifactId>
      <version>1.4.0</version>
    </dependency>

2、项目启动类添加@EnableApolloConfig    // 开启Apollo客户端

3、application.yml添加配置信息

可通过设置enable为false关闭热加载功能

app:
  # 应用ID(在Apollo服务端新增项目添加的应用ID)
  id: test001
apollo:
  # apollo-config-service地址
  meta: http://localhost:8080
  bootstrap:
    namespaces: application
    #apollo针对@ConfigurationProperties属性配置不进行热部署  enabled默认为false不开启热部署配置(@value形式自动热部署)
    enabled: true

4、添加热加载功能


import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigService;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
import org.springframework.cloud.context.scope.refresh.RefreshScope;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

/**
 * @author : xifanzhou
 * @Description :
 */
@Configuration
@ConditionalOnClass(ConfigService.class)
@ConditionalOnProperty(prefix = ApolloConfig.APOLLO_CONFIG_PREFIX, name = "enabled",
        havingValue = "true")
public class ApolloConfig implements ApplicationContextAware {
    private static final Logger logger = LoggerFactory.getLogger(ApolloConfig.class);
    public static final String APOLLO_CONFIG_PREFIX = "apollo.bootstrap";

    @Value("${apollo.bootstrap.namespaces}")
    private String[] namespaces;


    /**
     * spring控制器
     */
    private ApplicationContext applicationContext;

    /**
     * 热加载控制器
     */
    private final RefreshScope refreshScope;

    public ApolloConfig(RefreshScope refreshScope) {
        this.refreshScope = refreshScope;
    }

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

    /**
     * 单个namespace配置方式
     * "application"为apollo的namespace
     * @param changeEvent 更新内容
     */
//    @ApolloConfigChangeListener("application")
//    //@ApolloConfigChangeListener({"application","application.yml"}) //监听多个namespace
//    private void configChangeListter(ConfigChangeEvent changeEvent) {
//        logger.info("**************Apollo动态修改配置**************");
//        for (String changedKey : changeEvent.changedKeys()) {
//            logger.info("changedKey :{}",changedKey);
//            logger.info("changedValue :{}",changeEvent.getChange(changedKey));
//        }
//        refreshGatewayProperties(changeEvent);
//    }

    /**
     * 多个namespace配置方式
     * 启动时增加监听
     */
    @PostConstruct
    public void addRefreshListener() {
        for (String namespace : namespaces) {
            Config config = ConfigService.getConfig(namespace);
            //对namespace增加监听方法
            config.addChangeListener(changeEvent -> {
                for (String key : changeEvent.changedKeys()) {
                    logger.info("changedKey :{}",key);
                    logger.info("changedValue :{}",changeEvent.getChange(key));
                }
                //将变动的配置刷新到应用中
                refreshGatewayProperties(changeEvent);
            });
        }
    }


    /**
     * 更新SpringApplicationContext对象,
     *
     * @param changeEvent 更新内容
     */
    private void refreshGatewayProperties(ConfigChangeEvent changeEvent) {
        try {
            //更新配置
            this.applicationContext.publishEvent(new EnvironmentChangeEvent(changeEvent.changedKeys()));

            logger.info("**************Apollo动态修改配置成功**************");
        }catch (Exception e){
            logger.error("**************Apollo动态修改配置失败**************",e);
        }
    }


}

 

版权声明1:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/zhou_fan_xi/article/details/109649725
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2021-12-12 00:45
  • 阅读 ( 795 )

0 条评论

请先 登录 后评论

官方社群