分布式环境下的统一配置框架,已经有不少了,比如百度的disconf,阿里的diamand。今天来看下spring cloud对应的解决方案:

如上图,从架构上就可以看出与disconf之类的有很大不同,主要区别在于:

  • 配置的存储方式不同

    • disconf是把配置信息保存在mysql、zookeeper中,而spring cloud config是将配置保存在git/svn上 (即:配置当成源代码一样管理)
  • 配置的管理方式不同
    • spring cloud config没有类似disconf的统一管理界面,既然把配置都当成git之类的源码来看待了,git的管理界面,就是配置的管理界面
  • 配置变化的通知机制不同
    • disconf中配置变化后,依赖zk的事件watcher来通知应用,而spring cloud config则是依赖git每次push后,触发webhook回调,最终触发spring cloud bus(消息总线),然后由消息总线通知相关的应用。

另外,spring cloud config server本身也是一个微服务,跟其它的微服务一样,也可以注册到eureka server上,让其它使用方从注册中心来发现,单纯从解决的问题/场景来看,disconf与spring cloud config server是高度重合的,很难说哪个好,那个差,只是设计哲学不同。

但有一点,从配置变化的通知机制上看,如果有100个应用节点,都依赖于统一配置,如果修改了配置,只想让某几个节点"灰度"更新配置,spring cloud config server更容易做到,这一点相对disconf更灵活(后面会详细讲解)。

使用步骤:

一、在git/svn上创建一个配置项目(用于保存配置文件)

https://github.com/yjmyzz/spring-cloud-config-repository 这个为例,上面就放了几个配置文件(推荐用新的yml格式,对中文支持更好码)。

application.yml里的内容如下:

demo:
title: "default title"  

其它几个文件application_xxx.yml,里面的xxx,代表不同的profile.

二、创建config-server微服务

2.1 添加依赖项

dependencies {
compile 'org.springframework.cloud:spring-cloud-starter-eureka'
compile 'org.springframework.cloud:spring-cloud-config-server'
compile 'org.springframework.boot:spring-boot-starter-actuator'
}  

关键是第2个依赖项

2.2 application.yml

spring:
application:
name: config-server
profiles:
active: server1
cloud:
config:
server:
git:
uri: https://github.com/yjmyzz/spring-cloud-config-repository
# username: *****
# password: ***** eureka:
instance:
prefer-ip-address: true
instance-id: ${spring.application.name}:${server.port}
client:
service-url:
defaultZone: http://yjmyzz:123456@server1:8100/eureka,http://yjmyzz:123456@server2:8200/eureka management:
security:
enabled: false

注意上面的cloud.config.server这段,里面配置了git配置项目的位置。另外:config-server服务本身也需要HA,所以本示例中起了2个实例,分别对应server1、server2 这二个profile,用不同的端口,在本机跑2个实例,以模拟高可用。

application-server1.yml

server:
port: 8004

application-server2.yml

server:
port: 8005

2.3 main入口类

package com.cnblogs.yjmyzz.spring.cloud.study.config;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient; /**
* Created by yangjunming on 2017/7/5.
*/
@SpringBootApplication
@EnableEurekaClient
@EnableConfigServer
public class ConfigServer { public static void main(String[] args) {
SpringApplication.run(ConfigServer.class, args); }
}

关键是@EnableConfigServer 这个注解。 

2.4 跑起来看看

可以看到2个config-server已经注册到eureka上了,然后单独浏览一下: http://localhost:8004/application-dev.yml

已经把git上的application-dev.yml的内容输出了。

三、使用config-server

3.1 在之前的service-provider中添加依赖项

compile 'org.springframework.cloud:spring-cloud-starter-config'

3.2 创建一个简单的配置类

package com.cnblogs.yjmyzz.spring.cloud.study.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component; /**
* Created by yangjunming on 2017/7/5.
*/
@Component
@Data
@ConfigurationProperties(prefix = "demo")
public class DemoConfig { private String title;
}  

 然后找一个示例服务,使用这个配置:

package com.cnblogs.yjmyzz.spring.cloud.study.service.impl;

import com.cnblogs.yjmyzz.spring.cloud.study.api.UserService;
import com.cnblogs.yjmyzz.spring.cloud.study.config.DemoConfig;
import com.cnblogs.yjmyzz.spring.cloud.study.dto.UserDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; @Service("userService")
public class UserServiceImpl implements UserService { @Autowired
DemoConfig config; @Override
public UserDTO findUser(Integer userId) {
UserDTO user = new UserDTO();
user.setUserId(userId);
user.setUserName("菩提树下的杨过(" + config.getTitle() + ")");
return user;
}
}

3.3 添加bootstrap.yml 配置文件

spring:
application:
name: application
cloud:
config:
profile: dev
label: master
discovery:
enabled: true
service-id: config-server eureka:
instance:
prefer-ip-address: true
client:
service-url:
defaultZone: http://yjmyzz:123456@server1:8100/eureka,http://yjmyzz:123456@server2:8200/eureka

注意spring.cloud这一节的内容,里面指定了profile为dev,读取的git配置文件分支为master,同时允许从eureka上自动发现config-server这个实例。另外 spring.applicatin.name 即为配置文件的名称(即:application_xxx.yml) 

3.4 跑起来看看

说明已经从config-server取到了配置。  

 

四、配置更新

4.1 Controller上添加@RefreshScope

@RestController
@RefreshScope
public class UserController { @Autowired
private UserService userService; @GetMapping("/user/{id}")
public UserDTO findUser(@PathVariable Integer id) {
return userService.findUser(id);
}
}

这个注解,根据源码上的说法:Beans annotated this way can be refreshed at runtime and any components that are using them will get a new instance on the next method call, fully initialized and injected with all dependencies. 使用该注解后,可以在运行时直接刷新Bean,并在下次方法调用时,得到一个全新的实例。  

4.2 手动刷新/refresh

可以尝试把git配置项目里的application-dev.yml修改下内容,再浏览刚才的http://localhost:8001/user/1 发现内容并没有变化。

http://localhost:8001/refresh 手动向这个地址,发一个post请求(可以用postman或 curl -d '' http://localhost:8001/refresh),可以看到

说明demo.title这个配置项被刷新了,再浏览http://localhost:8001/user/1  可以看到有变化了

但是这样显然不是个办法,比如有10个service-provider组成的集群,如果要1台台手动刷新,太low了(除了做配置灰度更新,可以先刷新1台这种场景外)

4.3 集成spring cloud bus来批量刷新

spring cloud bus目前仅支持rabbitmq 及 kafka,我们以kafka为例,先在service-provider的application.yml里,加入下面的配置

然后依赖项里,加入:

compile 'org.springframework.cloud:spring-cloud-starter-bus-kafka'

注:关于kafka的环境搭建,网上有很多资料,大家可以参考下。

配置好这些后,本机启动kafka,然后再重启service-provider,就会多出一个/bus/refresh的端点,即:http://xxx:port/bus/refresh ,只要向集群中的任何一台机器的/bus/refresh发起post请求,就会同步刷新其它所有节点。原理大致就是,这台机器会发一条消息到kafka中,然后其它机器都是挂在消息总线上的,也会监听到该消息,然后刷新各自的配置。

最后一个问题:就算有/bus/refresh,也需要有人或系统触发。这个很好解决,github或gitlab上一般都有webhook功能,可以配置在代码push时,触发一些地址的回调。

这样,只要配置的代码提交了,就会触发自动刷新。

注:低版本的spring-cloud-dependencies有一个严重bug,调用/bus/refresh后,会导致所有服务节点,从eureka server的实例列表中永久下线,无法自动恢复,除非再次访问某个服务的/health端点,建议使用Dalston.SR2 或以上版本。

示例源代码: https://github.com/yjmyzz/spring-cloud-demo

spring cloud 学习(5) - config server的更多相关文章

  1. spring cloud 学习(2) - eureka server注册中心高可用及安全认证

    接上节继续,注册中心单点肯定是不牢靠的,可以参考下面的方案做成注册中心集群: 弄成3个节点,每个节点向其它节点注册,这样只要集群中有一个节点正常工作即可.为了方便在本机弄出这种效果,我们先修改下hos ...

  2. Spring Cloud 学习 之 Spring Cloud Eureka(源码分析)

    Spring Cloud 学习 之 Spring Cloud Eureka(源码分析) Spring Boot版本:2.1.4.RELEASE Spring Cloud版本:Greenwich.SR1 ...

  3. spring cloud 学习(9) - turbine stream无法在eureka注册的解决办法

    turbine是啥就不多解释了,初次接触的可以移步spring cloud 学习(4) - hystrix 服务熔断处理 拉到最后看一下,turbine stream默认情况下启动成功后,eureka ...

  4. Spring Cloud 入门 之 Config 篇(六)

    原文地址:Spring Cloud 入门 之 Config 篇(六) 博客地址:http://www.extlight.com 一.前言 随着业务的扩展,为了方便开发和维护项目,我们通常会将大项目拆分 ...

  5. Spring Cloud学习(一):Eureka服务注册与发现

    1.Eureka是什么 Eureka是Netflix开发的服务发现框架,本身是一个基于REST的服务,主要用于定位运行在AWS域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的. Eureka ...

  6. Spring Cloud Netflix之Euraka Server注册中心

    Spring Cloud简介 Spring Cloud是基于Spring Boot的一套实现微服务架构的生态组件.生态组件中包含Spring Cloud NetFlix,Spring Cloud Fe ...

  7. Spring Cloud 系列之 Config 配置中心(二)

    本篇文章为系列文章,未读第一集的同学请猛戳这里:Spring Cloud 系列之 Config 配置中心(一) 本篇文章讲解 Config 如何实现配置中心自动刷新. 配置中心自动刷新 点击链接观看: ...

  8. Spring Cloud 系列之 Config 配置中心(三)

    本篇文章为系列文章,未读前几集的同学请猛戳这里: Spring Cloud 系列之 Config 配置中心(一) Spring Cloud 系列之 Config 配置中心(二) 本篇文章讲解 Conf ...

  9. Spring Cloud Alibaba Nacos Config 实战

    Nacos 提供用于存储配置和其他元数据的 key/value 存储,为分布式系统中的外部化配置提供服务器端和客户端支持.使用 Spring Cloud Alibaba Nacos Config,您可 ...

随机推荐

  1. 【51Nod】1055 最长等差数列 动态规划

    [题目]1055 最长等差数列 [题意]给定大小为n的互不不同正整数集合,求最长等差数列的长度.\(n \leq 10000\). [算法]动态规划 两个数之间的差是非常重要的信息,设\(f_{i,j ...

  2. 第5月第21天 bugly ios证书位置

    1.bugly 一. 本地测试 补丁编写规则参见: JSPatch 将补丁文件main.js拖拽到工程内: 开启 BuglyConfig 中的热更新本地调试模式: BuglyConfig *confi ...

  3. PHP中冒号、endif、endwhile、endfor使用介绍

    我们经常在wordpress一类博客程序的模板里面看到很多奇怪的PHP语法,比如: 复制代码代码如下: <?php if(empty($GET_['a'])): ?> <font c ...

  4. Visual Studio 2013/2015/2017快捷键(转)

    英文原文:19 Must-Know Visual Studio Keyboard Shortcuts 项目相关的快捷键 Ctrl + Shift + B = 生成项目 Ctrl + Alt + L = ...

  5. Springboot 之 自定义配置文件及读取配置文件

    本文章来自[知识林] 读取核心配置文件 核心配置文件是指在resources根目录下的application.properties或application.yml配置文件,读取这两个配置文件的方法有两 ...

  6. activiti主要组件解析

    Activiti内部实现中,各主要部件关系 对外,提供Service服务,它是无状态的. 这些Service包括: protected RepositoryService repositoryServ ...

  7. 洛谷P2613有理数取余

    传送门 #include <iostream> #include <cstdio> #include <cstring> #include <algorith ...

  8. JDK7的新玩具java.util.Objects

    空指针异常这个坑爹的异常是初学开发者最常见的坑,那么今天为大家分享一个jdk的新工具java.util.Objects包.里面有很多工具可以帮我们避免空指针异常让我我们的代码写起来更加优雅.下面我们来 ...

  9. 记一些使用PyQt的问题

    本文自用,日常记录,不断更新 环境 1.使用 PyCharm IDE 2.PyQt5 3. 扩展配置 PyUIC转换后的代码处理 PyUIC 用于 将 QtDesigner 生成的 .ui 文件转换为 ...

  10. Java编程的逻辑 (1) - 数据和变量

    ​本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http: ...