1.为什么要使用分布式配置中心技术
场景1:例如某一个服务里面的一个常量,公司名称是“保定221科技有限公司”,有一天公司名称变更为“河北221科技有限公司”,但是这个服务应用量非常大,现在要改变此名称,运维工程师得等到凌晨三四点流量非常少的时候停掉服务,变更配置文件,然后重新启动服务,这个是常规的流程,如果是集群式的,那就更麻烦了,需要一个个的服务关掉重启,这个费时费力,影响业务。
Springcloud config可以很简单的实现上面需求,直接变更文件中的公司名称值,刷新服务或者使用服务注册中心的自动通知就完成了,不需要关掉重启服务这些操作,也不会影响业务。
场景2:服务一般有多个环境:开发,测试,上线,灰度等等,那么这些环境的配置是如何隔离和方便切换的呢,一般我们是把不同的配置文件进行拷贝进行物理替换,这种操作容易出错,造成配置混乱。
Springcloud config可以很简单的实现上面需求,在git上面存放多个版本的配置文件,在本地配置文件只需要改动一个配置就可以在多个版本的环境中切换,非常方便。
#指定dev开发环境配置文件 dev开发环境配置文件
spring.cloud.config.profile=dev
场景3:分布式部署中,其中一个服务有10个节点,那么配置文件也有10分,并且是完全一致的,其中一个参数需要更新,那么我们需要去更新10分配置文件,实际情况如果真的是这样就非常麻烦了。
Springcloud config可以很好的解决此问题,将配置文件中的配置放到git上面,这样10个节点用的是同一个项目配置文件,发生更新时只需要在线上更新一份配置文件即可,然后使用刷新服务来通知客户端服务完成刷新(有些配置需要重启服务,例如mysql的连接信息)。
2.分布式配置中心的基本架构原理
git 上存放我们的远程配置文件
config-server 连接到 git
config-client 连接到config-server
当我们启动config-client 服务的时候,client 会通过连接的 config-server 拿到远程git 上面的配置文件,然后通过 Spring 加载到对象中。
3.使用springcloud config + git实现分布式配置中心
开发工具:springboot ,码云(git,内部项目不能做测试使用,码云比较方便做测试)
4.分布式配置文件服务器(git)
注册一个码云账号,然后新建一个项目,然后添加1个个文件:测试客户端正式配置文件
demo-config-dev.properties
notify=222
# 服务端口
server.port=8888
#mysql数据库连接地址
spring.datasource.url=jdbc:mysql://localhost:3306/blog?useUnicode=true&characterEncoding=utf8&autoReconnect=true&serverTimezone=GMT
# spring.datasource.url=jdbc:mysql://123.207.70.170:3306/nodetest?useUnicode=true&characterEncoding=utf8&autoReconnect=true&serverTimezone=GMT
#mysql数据用户名称
spring.datasource.username=root
#mysql数据库密码
spring.datasource.password=123456
# spring.datasource.password=TSF-qcloud1
5.实现springcloud config- server
finish
看一下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>
<groupId>com.sun</groupId>
<artifactId>configserver</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>configserver</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.M1</spring-cloud.version>
</properties>
<dependencies>
<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>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
对配置文件进行配置application.properties
spring.application.name=config-server
server.port=5555
#配置git仓库地址
spring.cloud.config.server.git.uri=https://gitee.com/sunhuansheng/springcloud-config.git
#主分支
spring.cloud.config.label=master
#访问git仓库的用户名
#spring.cloud.config.server.git.username=
#访问git仓库的用户密码
#spring.cloud.config.server.git.password=
然后在入口类上添加注解
@EnableConfigServer
@PropertySource("classpath:application.properties")
package com.sun.configserver;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.config.server.EnableConfigServer;
import org.springframework.context.annotation.PropertySource;
@SpringBootApplication
@EnableConfigServer
@PropertySource("classpath:application.properties")
public class ConfigserverApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigserverApplication.class, args);
}
}
如此,springcloud config-server已经实现,运行看一下效果
启动服务成功后进行查看一下,是否可以获取git上的配置文件
可以通过接口访问到git上面的配置文件信息,说明分布式配置中心的服务端已经可以正常运行了。
6.实现springcloud config-client
finish
pom.xm
<?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>
<groupId>com.sun</groupId>
<artifactId>democonfig</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>democonfig</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.M1</spring-cloud.version>
</properties>
<dependencies>
<!--实现刷新配置-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--可以访问暴露的修改/刷新配置的接口-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--暴露修改/刷新配置的接口-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--添加数据库依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</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>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
创建并修改配置文件
bootstrap的优先级比application要高,所以程序运行是加载bootstrap配置文件的。我们是要实现客户端操作mysql数据库,包括查询一张表来验证我们功能的实现,看下面的配置文件,是没有mysql的相关配置,包括数据库名称,用户名密码等信息,这些信息是通过服务端到git上获取配置文件demo-config-dev.properties内的配置信息
application.properties
spring.application.name=demo-config
bootstrap.properties
#分支
spring.cloud.config.label=master
#指定dev开发环境配置文件 dev开发环境配置文件
spring.cloud.config.profile=dev
#指定配置文件名字 config-client,此名字对应git中的配置文件的名字
spring.cloud.config.name=demo-config
#配置服务地址,执行我们上一章的ConfigServer服务地址
spring.cloud.config.uri=http://localhost:5555/
#暴露接口
#(1)env接口,可以获取配置(GET),也可以修改配置(POST)
#(2)refresh接口,可以刷新配置(POST),使得@RefreshScope标注的value可以重新注入。
management.endpoints.web.exposure.include=env,refresh
在控制层创建接口
package com.sun.democonfig.configtest;
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;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.PathVariable;
@RestController
@RefreshScope
public class test {
@Autowired
private JdbcTemplate jdbcTemplate;
@Value("${spring.datasource.url}") //从配置中取值
private String url;
@RequestMapping("/hello")
public String hello(){
return url;
}
@RequestMapping("/getUsers")
public List<Map<String, Object>> getDbType(){
String sql = "select * from user ";
List<Map<String, Object>> list = jdbcTemplate.queryForList(sql);
for (Map<String, Object> map : list) {
Set<Entry<String, Object>> entries = map.entrySet( );
if(entries != null) {
Iterator<Entry<String, Object>> iterator = entries.iterator( );
while(iterator.hasNext( )) {
Entry<String, Object> entry =(Entry<String, Object>) iterator.next( );
Object key = entry.getKey( );
Object value = entry.getValue();
System.out.println(key+":"+value);
}
}
}
return list;
}
}
修改git上面的配置文件post提交(为了测试方便,我直接在git页面上修改文件)
springcloud config-client刷新
刷新服务再测试客户端服务,发现获取的数据已经发生了变化,采用的是新的数据库连接