如题,本篇我们介绍下Spring Cloud 中分布式配置中心Spring Cloud config。
什么是SpringCloud Config配置中心?
在分布式系统中,每一个功能模块都能拆分成一个独立的服务,一次请求的完成,可能会调用很多个服务协调来完成,为了方便服务配置文件统一管理,更易于部署、维护,所以就需要分布式配置中心组件了,在spring cloud中,有分布式配置中心组件spring cloud config,它支持配置文件放在在配置服务的内存中,也支持放在远程Git仓库里。引入spring cloud config后,我们的外部配置文件就可以集中放置在一个git仓库里,再新建一个config server,用来管理所有的配置文件,维护的时候需要更改配置时,只需要在本地更改后,推送到远程仓库,所有的服务实例都可以通过config server来获取配置文件,这时每个服务实例就相当于配置服务的客户端config client,为了保证系统的稳定,配置服务端config server可以进行集群部署。
搭建config-server工程 sim-configServer :
1、pom.xml中引入
<!-- config-server 起步依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
2 、application.yml
server:
port: 8888
context-path: /
spring:
application:
name: sim-configServer
#spring cloud config
cloud:
config:
label: master
server:
git:
uri: https://gitee.com/mmxl/sim-git-config
# searchPaths: repos /**
search-paths: /**
username: mmxl
password: xxxxxxx
eureka:
instance:
hostname: localhost #eureka客户端主机实例名称
prefer-ip-address: true
client:
service-url:
defaultZone: http://localhost:8761/eureka
3、springboot启动类上添加@EnableConfigServer、@EnableEurekaClient注解
package com.tingcream.simConfigServer;
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 SimConfigServerApp {
public static void main(String[] args) {
SpringApplication.run(SimConfigServerApp.class, args);
}
}
搭建config-client工程sim-serviceC :
1、pom.xml中引入
<!-- config client 起步依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
2、bootstrap.yml配置
server:
port: 6004
spring:
application:
name: sim-serviceC
profiles:
active: prod,prodFtp
cloud:
config:
label: master
#profile: dev
#uri: http://localhost:8888/
discovery:
enabled: true
serviceId: sim-configServer
eureka:
instance:
hostname: localhost #eureka客户端主机实例名称
prefer-ip-address: true
client:
service-url:
defaultZone: http://localhost:8761/eureka
3、springboot启动类
package com.tingcream.simServiceC;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@EnableEurekaClient
@SpringBootApplication
public class SimServiceCApp {
public static void main(String[] args) {
SpringApplication.run(SimServiceCApp.class, args);
}
}
SpringStartupListener.java
package com.tingcream.simServiceC.common;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import com.tingcream.simServiceC.ftp.FTPConfigBean;
@Component
public class SpringStartupListener implements ApplicationListener<ContextRefreshedEvent> {
@Value("${app.msg}")
private String appMsg;
@Value("${ftp.username}")
private String ftpUsername;
@Autowired
private FTPConfigBean fTPConfigBean;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
System.out.println("========SpringStartupListener 初始化=========");
System.out.println("appMsg: "+appMsg);
System.out.println("ftpUsername: "+ftpUsername);
System.out.println(fTPConfigBean.toString());
}
}
FTPConfigBean.java
package com.tingcream.simServiceC.ftp;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix="ftp")
public class FTPConfigBean {
private String host ;
private int port ;
private String username;
private String password;
private int connectTimeOut;
private String controlEncoding;
private int bufferSize;
private int fileType;
private int dataTimeout;
private boolean useEPSVwithIPv4;
private boolean passiveMode;
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getConnectTimeOut() {
return connectTimeOut;
}
public void setConnectTimeOut(int connectTimeOut) {
this.connectTimeOut = connectTimeOut;
}
public String getControlEncoding() {
return controlEncoding;
}
public void setControlEncoding(String controlEncoding) {
this.controlEncoding = controlEncoding;
}
public int getBufferSize() {
return bufferSize;
}
public void setBufferSize(int bufferSize) {
this.bufferSize = bufferSize;
}
public int getFileType() {
return fileType;
}
public void setFileType(int fileType) {
this.fileType = fileType;
}
public int getDataTimeout() {
return dataTimeout;
}
public void setDataTimeout(int dataTimeout) {
this.dataTimeout = dataTimeout;
}
public boolean isUseEPSVwithIPv4() {
return useEPSVwithIPv4;
}
public void setUseEPSVwithIPv4(boolean useEPSVwithIPv4) {
this.useEPSVwithIPv4 = useEPSVwithIPv4;
}
public boolean isPassiveMode() {
return passiveMode;
}
public void setPassiveMode(boolean passiveMode) {
this.passiveMode = passiveMode;
}
@Override
public String toString() {
return "FTPConfigBean [host=" + host + ", port=" + port + ", username=" + username + ", password=" + password
+ ", connectTimeOut=" + connectTimeOut + ", controlEncoding=" + controlEncoding + ", bufferSize="
+ bufferSize + ", fileType=" + fileType + ", dataTimeout=" + dataTimeout + ", useEPSVwithIPv4="
+ useEPSVwithIPv4 + ", passiveMode=" + passiveMode + "]";
}
}
依次启动sim-eureka 、sim-configServer 、sim-serviceC ,查看sim-serivceC的控制台的输出
========SpringStartupListener 初始化=========
appMsg: 你好,这是生产环境配置信息
ftpUsername: 生产ftp用户
FTPConfigBean [host=192.168.100.200, port=21, username=生产ftp用户, password=123456, connectTimeOut=5000, controlEncoding=UTF-8, bufferSize=1024, fileType=2, dataTimeout=120000, useEPSVwithIPv4=false, passiveMode=true]
ok,说明了sim-serviceC工程中从config-server获取到了git上配置文件。
如果是测试环境,bootstrap.yml中,可切换为 spring.profiles.active=test,testFtp ;开发环境可切换为spring.profiles.active=prod,prodFtp
注意bootstrap.yml 和application.yml是不同的,bootstrap.yml先于application.yml加载,在应用启动时先加载bootstrap.yml,再从git远程仓库获取更多配置信息,故sim-serviceC中应使用bootstrap.yml 配置。
----------------------
注:
1 、https://gitee.com/mmxl/sim-git-config ,这是笔者在码云上搭建的一个开源git仓库,用来存放整个sim项目的应用的配置文件。
2 sim-serviceC工程中的 spring.profiles.active 配置的值可为一个字符串,或者字符串数组(集合)。当为数组(集合)时,可以配置为一行中间用逗号隔开,或者配置为 -开头的多个元素项。springcloud中如果同时激活了多个profile,则多个profile中配置的key/value 对最终会进行合并,如果多个profile中含有同名的key,则列表中后面的profile配置会覆盖前面的。当然,如果不配置spring.profiles.active=dev,devFtp,使用spring.cloud.config.profile=dev,devFtp 配置也是可以的。
3 、sim-configServer中可访问的请求路径,如下:
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
4、 关于spring cloud config 的更多信息,可参照 http://projects.spring.io/spring-cloud/spring-cloud.html#_spring_cloud_config