在使用springcloud时,一般会采用springcloud configserver来获取配置,配置一般是保存在git中。文件的形式,方便修改和查阅,其实也可以将配置保存在数据库中。
但是最近在使用新华三私有云时发现一个问题。就是该云自带一个微服务引擎,可以自动创建并部署 Eureka 和ConfigServer 以及GateWay 但是在配置ConfigServer时,发现仅支持配置保存到数据库中,也就是需要填写数据库地址。这跟之前的开发方式并不相同。
于是尝试填写了一个数据库地址,点击创建,发现自动创建了一个数据库 h3c_pring_cloud
里面有几张表:
spring_cloud_config
spring_cloud_gateway
spring_cloud_gateway_jwt
spring_cloud_route_subsidiary
spring_cloud_route_to_subsidiary
可以看出spring_cloud_config就是保存配置 的表。表结构如下,
明显可以看出有用的字段是config_key/config_value/application。
因此尝试塞入一条数据,只插入name ,application,config_key,config_value其他的保持为空。
name 设置为 test-app
application设置为test-app-dev
config_key和config_value则是随便设置的
直接使用浏览器访问配置中心。
curl http://localhost:8080/test-app-dev/default/
地址后面跟default的原因是因为不跟的话,会访问不到,即返回错误页面,那为什么要设置成default呢,因为在springboot中如果没有指定spring.profiles.active的话,默认是default
得到结果如下。
没有返回想要的数据。因此在想是不是profile字段的问题,因此将profule字段设置为 default 。这里再设置profile为default时,需要注意
再次执行,还是没有查到任何数据。
这就奇怪了,直接使用sql是可以查到数据的,但是不知道云的自动创建的ConfigServer使用的SQL语句是什么,因为ConfigServer是自动创建的,所以无法查看它的源代码。正在一筹莫展的时候,突然想再让云创建一次数据库,因此,我直接把数据库删除了,然后我在想,这个时候再去访问一次会怎样呢?因此,我再次使用浏览器访问ConfigServer。得到了如下结果。
从返回结果中意外得到了创建的ConfigServer的sql语句,从中发现env_id竟然是一个固定值,经过查找,发现该值是在创建微服务引擎时生成的,然后,我就设置数据中env_id字段为该值。重新使用浏览器发起请求,返回结果。
结果依然没有数据,这就郁闷了,看了看剩下为null的字段只有一个label比较可疑了,可是设什么值比较好呢?
为什么会纠结这个问题,在浏览器上访问很方便更改label,但是主要是平时使用一般都是在spring项目中使用,一般都是master。因此,把label设置成了master。
此时访问
curl http://localhost:8080/test-app-dev/default/
得到了数据。
经过一段时间的探索我大概是知道了它的ConfigServer是怎们写的了,因此。贴如下代码。
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 https://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.5.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>2020.0.3</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-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</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>
application.yml
server:
port: 8080
context-path: /
spring:
profiles:
active: jdbc
application:
name: CONFIG_SERVER
datasource:
url: jdbc:mysql://10.116.67.115:3306/h3c_pring_cloud
password: root
username: root
driver-class-name: com.mysql.jdbc.Driver
cloud:
config:
server:
jdbc:
sql: SELECT config_key ,config_value from spring_cloud_config where env_id = 'asdfrsgt34fgfd' and APPLICATION=? and PROFILE=? and LABEL=?
enabled: true
Application.java
@EnableConfigServer
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
数据库脚本
DROP TABLE IF EXISTS `spring_cloud_config`;
CREATE TABLE `spring_cloud_config` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(100) DEFAULT NULL,
`env_id` varchar(100) DEFAULT NULL,
`application` varchar(100) DEFAULT NULL,
`profile` varchar(100) DEFAULT NULL,
`label` varchar(100) DEFAULT NULL,
`config_key` varchar(100) DEFAULT NULL,
`config_value` varchar(100) DEFAULT NULL,
`config_type` varchar(100) DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`states` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `spring_cloud_config` VALUES (1342953439026266112,'test-app','asdfrsgt34fgfd','test-app-dev','default','master','spring.datasource.url','jbdc:mysql://127.0.0.1:3306/test',NULL,NULL,NULL,NULL);
然后创建数据库。通过浏览器访问,可以实现获取配置,但是当我把数据库删除之后,再次访问。
出现了错误页面。
然后看到控制台也报错了。
可是为啥没出现云创建的ConfigServer出现的页面了,因为在新华三的微服务引擎中是看不到configserver的日志的,想到是不是云创建的ConfigServer使用了spring的全局异常处理,因此尝试添加一个全局异常处理。
GlobalExceptionHandler.java
@ControllerAdvice
public class GlobalExceptionHandler {
@ResponseBody
@ExceptionHandler(Exception.class)
public BaseResult globalException(HttpServletResponse response, Exception ex) {
BaseResult baseResult = new BaseResult();
baseResult.setCode(0);
baseResult.setTotal(0);
baseResult.setMsg(ex.getMessage());
return baseResult;
}
}
BaseResult.java
public class BaseResult {
private int code;
private String msg;
private int total;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
}
再次尝试,发现返回与云创建的configserver的返回结果是一致的
最后可以看一下 configserver 的映射规则
同时经过此次实验,发现使用mysql保存配置文件的方式还是有诸多不便的