J360-cloud SpringCloud系列一:分布式配置服务器ConfigServer

本贴最后更新于 3315 天前,其中的信息可能已经事过境迁

J360-Cloud系列

spring-cloud快速入门工程之j360-cloud-all:(欢迎star、fork

https://github.com/xuminwlt/j360-cloud-all


SpringCloud构建在Springboot基础上,如何使用SpringBoot请转移到

j360-boot

spring-boot入门工程之j360-boot:(欢迎star、fork

https://github.com/xuminwlt/j360-boot

spring-boot官方地址

http://projects.spring.io/spring-boot/


分布式配置

Spring Cloud分布式配置服务由服务器端和客户端共同组成,Server端提供配置信息的存储管理,客户端完成配置信息的调度,工程结构如下

套用一个图来解释该部分在springCloud分布式系统中的结构


上面的图片说明了四个微服务以及各个服务之间的依赖关系。 
configuration service 处于最顶端,黄色标识,而且被其他微服务所依赖。 
discovery service 处于最低端,蓝色标识,同时也被其他服务所依赖。 


- bootstrap.yml

- application.yml

- 【注】建议采用bootstrap+application组合形式,一般bootstrap配置工程不可变参数,且在启动时需要设定的内容,application配置可变参数

J360-cloud-configserver

1、POM依赖

            org.springframework.cloud
            spring-cloud-config-server
        
        
                    org.springframework.cloud
                    spring-cloud-starter-eureka
                

2、注解

- configserver提供了HTTP,为外部资源提供API配置的服务,只需要在Springboot程序中提供@EnableConfigServer注解即可。

    - @EnableConfigServer

    - 增加以下依赖 eureka(可选,作为discover服务器必选)

3、配置文件

bootstrap.properties

spring.application.name=configserver

spring.cloud.config.uri=http://localhost:8888

application.properties

server.port=8888

spring.cloud.config.server.git.uri=https://github.com/xuminwlt/config-repo

4、spring-boot:run

http://localhost:8888/configserver/application.properties

J360-cloud-client

1、POM

            org.springframework.cloud
            spring-cloud-starter-config
        

2、配置

bootstrap.properties

spring.application.name=client
spring.cloud.config.uri=http://localhost:8888

application.properties

server.port=8080

apply.message=local message
user.username=xumin

3、spring-boot:run

4、http://localhost:8080/env 查看环境变量

5、http://localhost:8080/refresh  post方法,更新client中的配置  

【注】环境变量刷新 

    - post -> localhost:8080/refresh

    - 定时

    - 手动


环境变量仓库

默认的环境变量库使用git服务,也可以使用文件系统的服务

1、git服务

https://github.com/xuminwlt/config-repo

2、文件服务

使用 spring.profiles.active=native

环境变量仓库使用3个变量:

- {application} 在客户端映射到"spring.application.name"

- {profile} 在客户端映射到"spring.active.profiles",使用逗号分隔

- {label}这是一个服务器端功能标签“版本”的一组配置文件


自动刷新

当环境变量参数通过git更新后,客户端自动更新:

1:可以使用 post /refresh来执行,客户端调用更新功能,configServer pull git完成后,更新环境变量信息,客户端获取最新的环境变量,并且更新

2:定时器执行:每隔X时间段更新一次

3:根据需要执行:只需要将定时器调用的更新接口暴露成服务形式调用

多客户端更新服务

1:通过Spring Cloud Bus更新

2:其他广播形式调用接口

调用接口:

/**
 * 手动刷新git更新方案,每20S执行一次,可以修改成手动执行,同/refresh
 * @link RefreshEndpoint
 * */
public void refresh() {
    Map before = extract(context.getEnvironment()
            .getPropertySources());
    addConfigFilesToEnvironment();
    Set keys = changes(before,
            extract(context.getEnvironment().getPropertySources())).keySet();
    scope.refreshAll();

    context.publishEvent(new EnvironmentChangeEvent(keys));
}
@Configuration
protected static class Empty {

}

private void addConfigFilesToEnvironment() {
    ConfigurableApplicationContext capture = null;
    try {
        capture = new SpringApplicationBuilder(Empty.class).showBanner(false)
                .web(false).environment(context.getEnvironment()).run();
        MutablePropertySources target = context.getEnvironment().getPropertySources();
        for (PropertySource<?> source : capture.getEnvironment().getPropertySources()) {
            String name = source.getName();
            if (!standardSources.contains(name)) {
                if (target.contains(name)) {
                    target.replace(name, source);
                }
                else {
                    if (target.contains("defaultProperties")) {
                        target.addBefore("defaultProperties", source);
                    }
                    else {
                        target.addLast(source);
                    }
                }
            }
        }
    }
    finally {
        while (capture != null) {
            capture.close();
            ApplicationContext parent = capture.getParent();
            if (parent instanceof ConfigurableApplicationContext) {
                capture = (ConfigurableApplicationContext) parent;
            } else {
                capture = null;
            }
        }
    }
}

private Map<String, Object> changes(Map<String, Object> before,
                                    Map<String, Object> after) {
    Map<String, Object> result = new HashMap<String, Object>();
    for (String key : before.keySet()) {
        if (!after.containsKey(key)) {
            result.put(key, null);
        }
        else if (!equal(before.get(key), after.get(key))) {
            result.put(key, after.get(key));
        }
    }
    for (String key : after.keySet()) {
        if (!before.containsKey(key)) {
            result.put(key, after.get(key));
        }
    }
    return result;
}

private boolean equal(Object one, Object two) {
    if (one == null && two == null) {
        return true;
    }
    if (one == null || two == null) {
        return false;
    }
    return one.equals(two);
}

private Map<String, Object> extract(MutablePropertySources propertySources) {
    Map<String, Object> result = new HashMap<String, Object>();
    for (PropertySource<?> parent : propertySources) {
        if (!standardSources.contains(parent.getName())) {
            extract(parent, result);
        }
    }
    return result;
}

private void extract(PropertySource parent, Map result) {     if (parent instanceof CompositePropertySource) {         try {             for (PropertySource source : ((CompositePropertySource) parent)
                    .getPropertySources()) {
                extract(source, result);
            }
        }
        catch (Exception e) {
            return;
        }
    }
    else if (parent instanceof EnumerablePropertySource) {
        for (String key : ((EnumerablePropertySource<?>) parent).getPropertyNames()) {
            result.put(key, parent.getProperty(key));
        }
    }
}


  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    942 引用 • 1459 回帖 • 31 关注
  • 云计算
    78 引用 • 91 回帖 • 1 关注
  • j360
    3 引用 • 12 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • billho

    请问自动刷新的这段代码是写在 config server 还是 client 的?