什么是分布式配置中心?
在分布式系统中,由于服务数量巨多,为了方便服务配置文件统一管理,实时更新,所以需要分布式配置中心组件。在Spring Cloud中,有分布式配置中心组件spring cloud config ,它支持配置服务放在配置服务的内存中(即本地),也支持放在远程Git仓库中。在spring cloud config 组件中,分两个角色,一是config server,二是config client。
遇到的问题:
①配置中心服务去git仓库读取不到配置文件(已解决,本篇文章下面会提到)
②消费者在去配置中心服务消费时,本身的端口被读取回来的配置文件覆盖,但是读取到的配置文件未配置端口(待解决)
推荐博客:github入门教程之搭建Spring Cloud Config配置中心
一、建立服务配置中心
1、修改pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
完整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.cloud</groupId>
<artifactId>serverconfig</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>serverconfig</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.2.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>Finchley.RC1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</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>
<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>
2、在程序的入口Application类加上@EnableConfigServer注解开启配置服务器的功能
package com.cloud.serverconfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
@SpringBootApplication
@EnableConfigServer
@EnableEurekaClient
public class ServerconfigApplication {
public static void main(String[] args) {
SpringApplication.run(ServerconfigApplication.class, args);
}
}
3、修改配置文件如果
Git仓库为公开仓库,可以不填写用户名和密码,如果是私有仓库需要填写
- spring.cloud.config.server.git.uri:配置git仓库地址
- spring.cloud.config.server.git.searchPaths:配置仓库路径
- spring.cloud.config.label:配置仓库的分支
- spring.cloud.config.server.git.username:访问git仓库的用户名
- spring.cloud.config.server.git.password:访问git仓库的用户密码
spring.application.name=config-server
server.port=8763
#eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
spring.cloud.config.server.git.uri=https://github.com/zjh746140129/test-config/
#spring.cloud.config.server.git.searchPaths=eureka
spring.cloud.config.server.git.searchPaths=/**
spring.cloud.config.label=master
spring.cloud.config.server.git.username=admin
spring.cloud.config.server.git.password=admin
4、启动访问证明配置服务中心可以从远程程序获取配置信息
http请求地址和资源文件映射如下:
- /{application}/{profile}[/{label}]
- /{application}-{profile}.yml
- /{label}/{application}-{profile}.yml
- /{application}-{profile}.properties
- /{label}/{application}-{profile}.properties
5、访问不到配置文件解决方案:
配置中心文件如图:
错误信息:
java.lang.StringIndexOutOfBoundsException: String index out of range: -1
at java.lang.String.substring(String.java:1967) ~[na:1.8.0_161]
解决方案:
把Spring Cloud版本由Finchley.RC2改为Finchley.RC1。
导致原因(查阅度娘):
Finchley.RC2版本下java.lang.StringIndexOutOfBoundsException: String index out of range: -1报错应该是这个版本的一个BUG。 在此版本有个HttpClientConfigurableHttpConnectionFactory这个类(1.4.3没有),lookupHttpClientBuilder方法中,第69行报错, 分析了一下,在substring的时候,获取File.separator的值为反斜杠"\",这可能是个BUG? 那么之所以走到这里是因为第67行获取到的HttpClientBuilder对象为null,反推这个HttpClientBuilder是哪来的时,发现是在前面通过MultipleJGitEnvironmentProperties传入的, 好吧,再去找MultipleJGitEnvironmentProperties这个傻缺从哪来的,发现是在EnvironmentRepositoryConfiguration.DefaultRepositoryConfiguration内自动注入了一个Bean(205行),有传入MultipleJGitEnvironmentProperties对象; 调试发现,里面的uri为null,所以在将HttpClientBuilder对象放入httpClientsByUri中的时候(HttpClientConfigurableHttpConnectionFactory(line:59))没有put进去; 我在调试MultipleJGitEnvironmentProperties注册成Bean的时候,uri是的的确确有被赋值。
修改完后再次读取配置文件:
此时已经可以读取到了
圈起来部分就是从git仓库检出到本地到配置文件
本地查看从git仓库读取到到文件
到这里从git仓库读取不到配置文件到问题就解决了。
二、建立服务中心消费者
1、修改pom.xml
<!-- 引入spring-cloud-starter-config,不要引入spring-cloud-config-server,否则会报错误 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
完整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.cloud</groupId>
<artifactId>configclient</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>configclient</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.2.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>Finchley.RC2</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!-- 引入spring-cloud-starter-config,不要引入spring-cloud-config-server,否则会报错误 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<!--<dependency>-->
<!--<groupId>org.springframework.cloud</groupId>-->
<!--<artifactId>Spring-cloud-config-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>
<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>
2、编写Controller测试从配置服务中心读取
package com.read;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ShowConfigController {
@Value("${version}")
String show;
@RequestMapping("/show")
@ResponseBody
public String show(){
return show;
}
}
3、修改启动类
package com.cloud.configclient;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan("com.*")
public class ConfigclientApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigclientApplication.class, args);
}
}
4、修改配置文件 需要把application.properties改为bootstrap.properties
spring.cloud.config.label 指明远程仓库的分支
spring.cloud.config.uri= http://localhost:8763/ 指明配置服务中心的网址
spring.cloud.config.profile 指定选择那个配置文件
dev开发环境配置文件
test测试环境
pro正式环境
server.port=8888
spring.application.name=config-client
spring.cloud.config.label=master
spring.cloud.config.profile=test
spring.cloud.config.uri= http://localhost:8763/
#eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
5、打开网址访问:http://localhost:8761/show
这个时候就可以看到服务中心消费者从服务中心提供者那取到配置文件了
配置中心流程说明:
1、服务消费者去配置中心服务消费
2、配置中心服务去git仓库获取配置
3、配置中心服务会缓存取到到配置文件供消费者使用
三、Spring Boot与Spring Cloud学习使用可参看笔者博客
①Spring Cloud入门教程之服务注册与发现Eureka
②Spring Cloud入门教程之服务消费者 Ribbon
⑥Spring Cloud入门教程之分布式配置中心 Spring Cloud Config