SpringCloud系列教程 | 第七篇:Spring Cloud Config 配置中心高可用和refresh

Springboot: 2.1.6.RELEASE

SpringCloud: Greenwich.SR1

如无特殊说明,本系列教程全采用以上版本

1. 引言

上一篇我们聊了Spring Cloud Config 配置中心,并且和Github做了集成,我们的Server端是单机版的,任何单机版的服务都只能使用与测试环境或者自己做Demo测试,生产环境严禁使用单机服务,配置中心在整个微服务体系中都是及其重要的一个节点,尤其是在DevOps中自动扩容,如果配置中心宕机,那么所有的自动扩容都会失败。

所以这一篇我们聊聊配置中心的高可用,说到高可用,在springcloud体系中,是有注册中心的,那么,我们的配置中心也是一个服务,可不可以使用Eureka做服务的注册与发现呢?

答案是肯定的。

2. Serve端

我们将上一篇的Serve端Copy到新的目录中,增加Eureka-client的依赖,使得Config-Serve可以注册到Eureka上。

2.1 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.springcloud</groupId>
<artifactId>config-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>config-server</name>
<description>Demo project for Spring Boot</description> <properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies> <dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> </project>

2.2 配置文件application.yml

server:
port: 8080
spring:
application:
name: spring-cloud-config-server
cloud:
config:
server:
git:
uri: https://github.com/meteor1993/SpringCloudLearning
search-paths: chapter6/springcloud-config
username: username
password: password
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/

增加eureka的地址配置

2.3 启动类

启动类增加@EnableEurekaClient激活对注册中心的支持

package com.springcloud.configserver;

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; @SpringBootApplication
@EnableConfigServer
@EnableEurekaClient
public class ConfigServerApplication { public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
} }

这样Server注册端我们就修改完成了。先启动Eureka,再启动Serve,在浏览器中访问http://localhost:8761/,就可以看到我们的Serve端已经注册到注册中心了,接下来我们开始改造Client端。

3. Client端

首先还是将上一篇的Client端Copy过来,和Server端一样,增加Eureka-client的依赖,使得Config-Client可以从注册中心上发现服务。

3.1 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.springcloud</groupId>
<artifactId>config-client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>config-client</name>
<description>Demo project for Spring Boot</description> <properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies> <dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> </project>

3.2 bootstrap.properties

这里我们需要先清空application.yml,所有的配置全都转移到bootstrap.properties中。

spring.application.name=spring-cloud-config-client
server.port=8081 spring.cloud.config.name=springcloud-config
spring.cloud.config.profile=dev
spring.cloud.config.label=master
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.serviceId=spring-cloud-config-server eureka.client.service-url.defaultZone=http://localhost:8761/eureka/

主要是去掉了spring.cloud.config.uri直接指向server端地址的配置,增加了最后的三个配置:

  • spring.cloud.config.discovery.enabled :开启Config服务发现支持
  • spring.cloud.config.discovery.serviceId :指定server端的name,也就是server端spring.application.name的值
  • eureka.client.serviceUrl.defaultZone :指向注册中心的地址

3.3 启动类

启动类增加@EnableEurekaClient激活对注册中心的支持

package com.springcloud.configclient;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication
@EnableEurekaClient
public class ConfigClientApplication { public static void main(String[] args) {
SpringApplication.run(ConfigClientApplication.class, args);
} }

4. 高可用

现在我们来模拟生产环境。

首先,顺次启动Eureka,Server,Client。

在idea启动两个config-serve,我们修改idea配置启动配置,换到8000端口启动config-serve。

先访问http://localhost:8761/,可以看到两个config-serve都正常注册到注册中心。

如上图就可发现会有两个server端同时提供配置中心的服务,防止某一台down掉之后影响整个系统的使用。

我们访问client端的链接:http://localhost:8081/hello, 可以看到页面正常显示:hello dev update1,刷新几次,显示都没问题,现在我们随机停掉一个端口的config-serve服务,再去刷新页面,可以发现,页面依然可以正常显示:hello dev update1。

至此,我们高可用的目的已经达到,但是,不知道各位有没有映像,我们上一篇留了一个坑,服务启动后,我们修改远端github上的配置时,这个配置并不会实时被客户端端所获取到,下面我们来聊一聊有关Spring Cloud Config 刷新的问题。

5. refresh

我们的客户端并不能主动去感知Git或者Svn的配置变化,从而主动获取最新的配置。那么,客户端如何去主动获取新的配置信息呢?springcloud已经给我们提供了解决方案,每个客户端通过POST方法触发各自的/refresh。

修改config-client项目已到达可以refresh的功能。

5.1 添加依赖pom.xml

在我们原有的config-client项目的pom.xml的基础增加新的依赖

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

增加了spring-boot-starter-actuator包,spring-boot-starter-actuator是一套监控的功能,可以监控程序在运行时状态,其中就包括/refresh的功能。

5.2 开启更新机制

需要给加载变量的类上面加载@RefreshScope,在客户端执行/refresh的时候就会更新此类下面的变量值。

package com.springcloud.configclient.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; /**
* @Author: shiyao.wei
* @Date: 2019/7/4 16:19
* @Version: 1.0
* @Desc:
*/
@RestController
@RefreshScope // 使用该注解的类,会在接到SpringCloud配置中心配置刷新的时候,自动将新的配置更新到该类对应的字段中。
public class HelloController { @Value("${springcloud.hello}")
private String hello; @RequestMapping("/hello")
public String from() {
return this.hello;
}
}

5.3 配置文件bootstrap.properties

spring.application.name=spring-cloud-config-client
server.port=8081 spring.cloud.config.name=springcloud-config
spring.cloud.config.profile=dev
spring.cloud.config.label=master
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.serviceId=spring-cloud-config-server eureka.client.service-url.defaultZone=http://localhost:8761/eureka/ management.security.enabled=false
management.endpoints.web.exposure.include=*
  • management.security.enabled: springboot 1.5.X 以上默认开通了安全认证,所以需要添加这个配置
  • management.endpoints.web.exposure.include: springboot 2.x 默认只开启了info、health的访问,*代表开启所有访问

5.4 测试

我们先访问客户端的测试连接:http://localhost:8081/hello, 这时,页面的显示是:hello dev update1,我们修改github上的信息,修改为:hello dev update,现在访问http://localhost:8081/hello,得到的信息还是:hello dev update1,现在我们刷新一下客户端,通过cmd命令行执行:curl -X POST http://localhost:8081/actuator/refresh,可以看到命令行上有显示:["springcloud.hello","config.client.version"],意味着springcloud.hello这个配置已经刷新,这时,我们再去刷新一下页面,可以看到,页面上得到的信息已经变为了:hello dev update,这时我们refresh成功。

每次手动刷新客户端还是很麻烦,有没有什么办法只要提交代码就自动调用客户端来更新呢,github的webhook是一个好的办法。

6. webhook

WebHook是当某个事件发生时,通过发送http post请求的方式来通知信息接收方。Webhook来监测你在Github.com上的各种事件,最常见的莫过于push事件。如果你设置了一个监测push事件的Webhook,那么每当你的这个项目有了任何提交,这个Webhook都会被触发,这时Github就会发送一个HTTP POST请求到你配置好的地址。

如此一来,你就可以通过这种方式去自动完成一些重复性工作,比如,你可以用Webhook来自动触发一些持续集成(CI)工具的运作,比如Travis CI;又或者是通过 Webhook 去部署你的线上服务器。下图就是github上面的webhook配置。

  • Payload URL: 触发后回调的URL
  • Content type: 数据格式,两种一般使用json
  • Secret: 用作给POST的body加密的字符串。采用HMAC算法
  • events: 触发的事件列表
events事件类型 描述
push 仓库有push时触发。默认事件
create 当有分支或标签被创建时触发
delete 当有分支或标签被删除时触发

这样我们就可以利用hook的机制去触发客户端的更新,但是当客户端越来越多的时候hook支持的已经不够优雅,另外每次增加客户端都需要改动hook也是不现实的。其实Spring Cloud给了我们更好解决方案,我们在下一篇接着聊。

示例代码-Github

跟我学SpringCloud | 第七篇:Spring Cloud Config 配置中心高可用和refresh的更多相关文章

  1. Spring Cloud Config 配置中心高可用

    详细参见 <Spring Cloud 与 Docker微服务架构实战> p163-9.10 Spring Cloud Config 与 Eureka 配合使用 p163-9.12 Conf ...

  2. 微服务SpringCloud之Spring Cloud Config配置中心服务化

    在前面两篇Spring Cloud Config配置中心的博客中都是需要指定配置服务的地址url:spring.cloud.config.uri,客户端都是直接调用配置中心的server端来获取配置文 ...

  3. 微服务SpringCloud之Spring Cloud Config配置中心Git

    微服务以单个接口为颗粒度,一个接口可能就是一个项目,如果每个项目都包含一个配置文件,一个系统可能有几十或上百个小项目组成,那配置文件也会有好多,对后续修改维护也是比较麻烦,就和前面的服务注册一样,服务 ...

  4. 微服务SpringCloud之Spring Cloud Config配置中心SVN

    在回来的路上看到一个个的都抱着花,吃了一路的狗粮,原本想着去旁边的工业园里跑跑步呢,想想还是算了,人家过七夕,俺们过巴西.上一博客学习了Spring Cloud Config使用git作为配置中心,本 ...

  5. SpringCloud学习笔记(7):使用Spring Cloud Config配置中心

    简介 Spring Cloud Config为分布式系统中的外部化配置提供了服务器端和客户端支持,服务器端统一管理所有配置文件,客户端在启动时从服务端获取配置信息.服务器端有多种配置方式,如将配置文件 ...

  6. Spring Cloud Config 配置中心 自动加解密功能 jasypt方式

    使用此种方式会存在一种问题:如果我配置了自动配置刷新,则刷新过后,加密过后的密文无法被解密.具体原因分析,看 SpringCloud 详解配置刷新的原理 使用  jasypt-spring-boot- ...

  7. Spring Cloud Config 配置中心实践过程中,你需要了解这些细节!

    本文导读: Spring Cloud Config 基本概念 Spring Cloud Config 客户端加载流程 Spring Cloud Config 基于消息总线配置 Spring Cloud ...

  8. Spring Cloud Config 配置中心

    请将远程配置文件的格式写对: 比如使用 *.yml 或者 *.properties yml: testconfig: testvalue properties: testconfig=testvalu ...

  9. Spring Cloud Config 配置中心 自动加解密功能 JCE方式

    1.首先安装JCE JDK8的下载地址: http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.h ...

随机推荐

  1. nginx-1.8.0 rpm包制作

    1.安装rpm-build # yum install rpm-build 2.创建制作RPM包目录 # cat /root/.rpmmacros %_topdir /root/rpmbuild %_ ...

  2. ZOJ3802 Easy 2048 Again (状压DP)

    ZOJ Monthly, August 2014 E题 ZOJ月赛 2014年8月 E题 http://acm.zju.edu.cn/onlinejudge/showProblem.do?proble ...

  3. JavaScript toFixed()使用的注意事项

    以下是w3school的定义: 定义和用法 toFixed() 方法可把 Number 四舍五入为指定小数位数的数字. 语法 NumberObject.toFixed(num) 参数 描述 num 必 ...

  4. 按要求编写一个Java应用程序: (1)定义一个类,描述一个矩形,包含有长、宽两种属性,和计算面积方法。 (2)编写一个类,继承自矩形类,同时该类描述长方体,具有长、宽、高属性, 和计算体积的方法。 (3)编写一个测试类,对以上两个类进行测试,创建一个长方体,定义其长、 宽、高,输出其底面积和体积。

    package jvxing; public class Jvxing { //成员变量 private double width; private double chang; public doub ...

  5. Java网络编程注意事项3

    如何使用POST请求和GET请求Web网站发送请求,下面的参考代码: import java.io.BufferedReader; import java.io.InputStream; import ...

  6. 洛谷P1608路径统计

    题目 这个提示一个简单的最短路计数,除了用数组存上最短路的个数的做法以外,还有可以在得出最短路之后,搜索加剪枝的方法来通过该题. 可以反向搜索用A*的方法来通过,但是这个题的去重十分的恶心,需要一些玄 ...

  7. Node.js实战项目学习系列(3) CommonJS 模块化规范

    前言 想开始编写Node.js代码,那么我们就必须先熟悉它的模块化规范CommonJS,本文将详细讲解CommonJS规范 本文代码 >>> github 地址 CommonJS N ...

  8. html canvas 的宽高以及像素限制

    canvas 宽高设置不合适的话,是画不出东西出来的 https://stackoverflow.com/questions/6081483/maximum-size-of-a-canvas-elem ...

  9. 基于NIO的同步非阻塞编程完整案例,客户端发送请求,服务端获取数据并返回给客户端数据,客户端获取返回数据

    这块还是挺复杂的,挺难理解,但是多练几遍,多看看研究研究其实也就那样,就是一个Selector轮询的过程,这里想要双向通信,客户端和服务端都需要一个Selector,并一直轮询, 直接贴代码: Ser ...

  10. Spring依赖注入构造器注入(通过构造函数注入)

    在src目录下建立applicationContext.xml   (Spring 管理 bean的配置文件) <?xml version="1.0" encoding=&q ...