目录

  • 一、简介
  • 二、数据库
    • 2.1、应用表
    • 2.2、属性表
    • 2.3、视图
    • 2.4、初始化数据
  • 三、配置
    • 3.1、pom.xml
    • 3.2、application.properties
    • 3.3、主类
    • 3.4、应用的默认日志配置
    • 3.5、应用属性切面

一、简介

  Spring Cloud Config 包含以下两个部分:

  • Config Server :一般称为分布式配置中心,是一个独立运行的微服务应用,它通过连接数据服务(git,db等)为客户端提供获取配置信息、加密信息和解密信息的访问接口
  • Config Client :一般是微服务架构中的各个微服务,它们通过 Config Server 的接口获取和加载配置信息

  本文中的配置中心的 数据是保存在mysql数据库中 ,并且可以 给客户端提供统一的日志管理

二、数据库

  在实际中,我们的服务有很多,每个服务都有很多的配置,并且有很多配置是一样的,有很多又不是一样的,基于这种情况,我们创建一个数据库config_center,然后新建两个表和一个视图(根据自己需要,你也可以连表查询)。分别是应用表,对应客户端应用,属性表对应每个应用的配置项。

2.1、应用表

CREATE TABLE `tb_app` (`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',`app_name` varchar(30) NOT NULL DEFAULT '' COMMENT '应用名',`priority` int unsigned NOT NULL DEFAULT '1' COMMENT '优先级',`remark` varchar(45) NOT NULL DEFAULT '' COMMENT '备注',PRIMARY KEY (`id`),UNIQUE KEY `app_name_UNIQUE` (`app_name`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='应用表';

  实际工作中会有很多的工程,我们把它叫应用,可以通过后台去添加这些应用。

2.2、属性表

CREATE TABLE `tb_property` (`id` int NOT NULL AUTO_INCREMENT COMMENT '主键',`app_id` int NOT NULL COMMENT '应用id',`config_key` varchar(200)  NOT NULL DEFAULT '' COMMENT '键',`config_value` varchar(500) NOT NULL DEFAULT '' COMMENT '值',`enabled` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否启用',`refreshable` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否可动态刷新',`remark` varchar(200) NOT NULL DEFAULT '' COMMENT '备注',`profile` varchar(10) CHARACTER SET utf8 NOT NULL DEFAULT 'default' COMMENT 'profile',`label` varchar(10) CHARACTER SET utf8 NOT NULL DEFAULT 'master' COMMENT 'label',PRIMARY KEY (`id`),UNIQUE KEY `property_un` (`app_id`,`config_key`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='配置表';

  一个应用会有很多的属性,我们也可以去把每个应用的属性管理起来。

2.3、视图

CREATE VIEW `v_app_properties` (`id` , `appName` , `configKey` , `configValue` , `PROFILE` , `label`, `priority`) ASSELECT `tp`.`id` AS `id`,`ta`.`app_name` AS `appName`,`tp`.`config_key` AS `configKey`,`tp`.`config_value` AS `configValue`,`tp`.`profile` AS `profile`,`tp`.`label` AS `label`,`ta`.`priority` AS `priority`FROM`tb_property` `tp`LEFT JOIN `tb_app` `ta` ON `tp`.`app_id` = `ta`.`id`WHERE`tp`.`enabled` = 1

  为什么要创建一个视图呢?实际是可以通过应用表和属性表连查得到结果,但是我们这些应用及属性是一个数量有限的,并且数据增长不会很快,为了便于观察和查询,我觉得此处使用视图,可能效果会更好。当然你也可以不用,就使用我上面的连接查询也行。

2.4、初始化数据

  两个截图!!!(这样看起来结构清晰)

三、配置

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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>cn.alian.microservice</groupId><artifactId>parent</artifactId><version>1.0.0-SNAPSHOT</version></parent><artifactId>config-service</artifactId><version>1.0.0-SNAPSHOT</version><packaging>jar</packaging><name>config-service</name><description>配置中心</description><dependencies><!--自定义的db starter--><dependency><groupId>cn.alian.microservice</groupId><artifactId>common-db</artifactId><version>1.0.0-SNAPSHOT</version></dependency><!--配置中心服务--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-config-server</artifactId></dependency><!--注册中心--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><!--打印sql执行--><dependency><groupId>com.googlecode.log4jdbc</groupId><artifactId>log4jdbc</artifactId></dependency><!--mysql--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!--日志--><dependency><groupId>org.zalando</groupId><artifactId>logbook-spring-boot-starter</artifactId><version>2.0.0</version></dependency></dependencies></project>

  需要注意的是

<!--自定义的db starter-->
<dependency><groupId>cn.alian.microservice</groupId><artifactId>common-db</artifactId><version>1.0.0-SNAPSHOT</version>
</dependency>

  是我上一篇文章自定义的starter,不知道的,可以查看上一篇文章,所以我这里就不用再手动引入ebean相关的依赖了,是不是很简洁方便?当然我这里的配置中心也注册到了Eureka了。

3.2、application.properties

#应用名
spring.application.name=config-service
#后定义的bean会覆盖之前定义的相同名称的bean
spring.main.allow-bean-definition-overriding=true
#端口
server.port=6666#数据库配置(生产可以换其他的)
spring.datasource.driver-class-name=net.sf.log4jdbc.DriverSpy
spring.datasource.url=jdbc:log4jdbc:mysql://10.130.3.99:3306/config_center?autoReconnect=true&useSSL=false
spring.datasource.username=alian
spring.datasource.password=Alian1223
spring.datasource.hikari.connection-timeout=5000
spring.datasource.hikari.maximum-pool-size=10#配置采用数据库存储
spring.profiles.active=jdbc
#配置中心默认profile
spring.cloud.config.server.default-profile=default
#配置中心默认label
spring.cloud.config.server.default-label=master
#查询配置中心配置的语句
spring.cloud.config.server.jdbc.sql=SELECT configKey,configValue FROM v_app_properties WHERE appName=? AND profile=? AND label=? ORDER BY priority;
#优先级配置(jdbc大于native)
spring.cloud.config.server.jdbc.order=0#日志配置文件
#app.logback.dir=/microservice/config-service/logback
app.logback.dir=C:/workspace/study/spring-cloud-microservices/config-service/logback#部署时
#logging.config=file:config/logback.xml

  我们着重关注下这个

#查询配置中心配置的语句
spring.cloud.config.server.jdbc.sql=SELECT configKey,configValue FROM v_app_properties
WHERE appName=? AND profile=? AND label=? ORDER BY priority;

  我这里就是查询我们之前创建的那个视图,因为如果你没有设置这个语句,那么默认查询就是

private static final String DEFAULT_SQL = "SELECT KEY, VALUE from PROPERTIES"+ " where APPLICATION=? and PROFILE=? and LABEL=?";

  不过你就得按照它的要求去减表和字段了。从这里你就知道我们自定义sql的灵活的优势了,尤其是对于微服务来说。不管怎么样,默认的和自定义的都会有这三个参数:

  • APPLICATION
  • PROFILE
  • LABEL

  对这个地方每个人的看法都不一样,也没有谁对谁错。我就讲下我的理解,第一个APPLICATION是应用的名称(spring.application.name),基本也就固定了,后面两个可以自由发挥;第二个当做环境变量,比如开发(dev)还是测试(test),反正别扯蛋说生产了,谁会生产和测试在一个环境乱搞啊;第三个就当做代码版本配置,比如主干和分支,在没有特别大团队的情况下,一般改动第二个就可以了。含义没有绝对的要求,只要能满足你的查询需求即可。

3.3、主类

ConfigServiceApplication.java

package cn.alian.microservice.configService;import cn.alian.microservice.configService.config.AppProperties;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.config.server.EnableConfigServer;@EnableConfigServer
@EnableConfigurationProperties({AppProperties.class})
@SpringBootApplication
public class ConfigServiceApplication {public static void main(String[] args) {SpringApplication.run(ConfigServiceApplication.class, args);}}

注意这里使用注解 @EnableConfigServer

3.4、应用的默认日志配置

LogbackController

package cn.alian.microservice.configService.controller;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ResponseBody;import java.io.File;
import java.io.FileReader;@Controller
public class LogbackController {private static final Logger log = LoggerFactory.getLogger(LogbackController.class);@Value("${app.logback.dir}")private String logbackDir;@GetMapping({"/logback/{appName}.xml"})@ResponseBodypublic String logback(@PathVariable("appName") String appName) throws Exception {log.info("logback appName = [" + appName + "]");try {if (!(new File(this.logbackDir + "/" + appName + ".xml")).exists()) {log.info("指定日志配置【{}】不存在,使用默认配置", appName);appName = "default";}return FileCopyUtils.copyToString(new FileReader(this.logbackDir + "/" + appName + ".xml"));} catch (Exception e) {log.error(null, e);throw e;}}
}

  日志配置文件: C:/workspace/study/spring-cloud-microservices/config-service/logback/default.xml

default.xml

<!--scan:为true时,配置文件如果发生改变,将会被重新加载,默认为true-->
<!--scanPeriod:当scan为true时,监测配置文件是否有修改的时间间隔。如果没有给出时间单位,默认单位是毫秒。默认时间间隔1分钟。英文不要写错了second minute hour-->
<!--debug:为true时,可打印出logback内部日志信息。默认为false-->
<configuration scan="true" scanPeriod="30 seconds" debug="false"><property name="appName" value="app"/><!--定义日志路径--><property name="log.path" value="logs"/><!--定义控制台日志输出格式--><property name="console.pattern" value="%d{yyyy-MM-dd HH:mm:ss SSS} [%thread] %level %method %line:%m%n"/><!--定义控制台日志输出格式--><property name="file.pattern" value="%d{yyyy-MM-dd HH:mm:ss SSS} [%thread] %level %method %line:%m%n"/><!--控制台日志输出--><appender name="Console" class="ch.qos.logback.core.ConsoleAppender"><!--字符串值System.out或System.err之一。默认目标是System.out--><Target>System.out</Target><!--只配置最底级别,控制台输出的日志级别大于或等于此级别的日志信息--><filter class="ch.qos.logback.classic.filter.ThresholdFilter"><level>debug</level></filter><!--编码器--><encoder><!-- 输出日志信息格式 --><pattern>${console.pattern}</pattern><!-- 设置字符集 --><charset>UTF-8</charset></encoder></appender><!--文件滚动追加器(基于时间滚动策略按日滚动,最多保存90天历史记录,总文档大小不超过20GB)--><appender name="File" class="ch.qos.logback.core.rolling.RollingFileAppender"><!--日志文件命名--><File>logs/${appName}.log</File><!--基于时间滚动策略--><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!--按日滚动--><fileNamePattern>logs/${appName}.%d{yyyy-MM-dd}.log</fileNamePattern><!--按小时滚动--><!--<fileNamePattern>logs/app.%d{yyyy-MM-dd_HH}.log</fileNamePattern>--><!--按分钟滚动--><!--<fileNamePattern>logs/app.%d{yyyy-MM-dd_HH-mm-ss}.log</fileNamePattern>--><!--日志保留份数--><MaxHistory>10</MaxHistory><!--日志文件最大的大小--><totalSizeCap>20GB</totalSizeCap></rollingPolicy><!--文件追加到末尾--><Append>true</Append><!--编码器--><encoder><!-- 输出日志信息格式 --><pattern>${file.pattern}</pattern><!-- 设置字符集 --><charset>UTF-8</charset></encoder><!--只配置最底级别,控制台输出的日志级别大于或等于此级别的日志信息--><filter class="ch.qos.logback.classic.filter.ThresholdFilter"><level>info</level></filter></appender><logger name="cn.alian" level="debug"/><logger name="io.swagger" level="error"/><logger name="jdbc.sqlonly" level="ERROR" additivity="false"><appender-ref ref="File"/></logger><logger name="jdbc.audit" level="ERROR" additivity="false"><appender-ref ref="File"/></logger><logger name="jdbc.resultset" level="ERROR" additivity="false"><appender-ref ref="File"/></logger><logger name="jdbc.connection" level="ERROR" additivity="false"><appender-ref ref="File"/></logger><logger name="jdbc.sqltiming" level="info" additivity="false"><appender-ref ref="File"/></logger><root level="info"><appender-ref ref="Console"/><appender-ref ref="File"/></root>
</configuration>

  我们这个日志有什么用呢,实际就是当应用通过配置方式请求到配置中心的日志接口时,如

#日志配置,通过配置中心获取
logging.config=${spring.cloud.config.uri}/logback/${spring.application.name}.xml

  我们就可以把这个默认的日志提供给应用,这样可以通过配置中心达到统一日志格式。

3.5、应用属性切面

AppPropertiesAspect

package cn.alian.microservice.configService.config;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.config.environment.Environment;
import org.springframework.cloud.config.environment.PropertySource;
import org.springframework.stereotype.Component;import java.util.List;
import java.util.Map;
import java.util.Set;@Component
@Aspect
public class AppPropertiesAspect {private static final Logger log = LoggerFactory.getLogger(AppPropertiesAspect.class);@Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")public void requestMapping() {}@Around("requestMapping()")public Object printAppProperties(ProceedingJoinPoint point) throws Throwable {Object object = point.proceed();if (object instanceof Environment) {List<PropertySource> propertySources = ((Environment) object).getPropertySources();for (PropertySource propertySource : propertySources) {String sourceName = propertySource.getName();Map<String, Object> source = (Map<String, Object>) propertySource.getSource();Set<Map.Entry<String, Object>> entrySet = source.entrySet();for (Map.Entry<String, Object> entry : entrySet) {log.info("sourceName={}, key={}, value={}", sourceName, entry.getKey(), entry.getValue());}}}return object;}}

  通过切面我们可以可以打印出每个应用获取的属性配置,便于开发调试时查找问题。其实到这里我们的配置中心服务端就弄好了。主要有两个功能,一个是提供配置,一个是提供日志,接下里我们准备通过订单服务去搭建配置中心客户端吧。

(六)Alian 的 Spring Cloud Config 配置中心(服务端)相关推荐

  1. (七)Alian 的 Spring Cloud Config 配置中心(客户端)

    目录 一.背景 二.maven依赖 三.配置文件 四.验证 一.背景   通过上一篇文章,我们已经搭建了配置中心了,接下里我们继续改造我们的订单服务了,之前我们的订单服务的数据库配置还是写在配置文件中 ...

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

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

  3. Spring Cloud Config 配置中心

    1.构建config-server 创建一个pom.xml <?xml version="1.0" encoding="UTF-8"?> <p ...

  4. Spring Cloud Config配置中心的使用

    一.概述 1. 为什么使用? 1> 配置文件太多,不方便维护 2> 配置文件一般都保存这各种明文显示的密码,无法保证配置内容的安全性,也无法做到按权限分配给个人 3> 更新配置项目需 ...

  5. git在clone时需要输入密码Enter passphrase for key 导致spring cloud config 配置中心无法拉取配置文件的解决方法

    前几天把系统从win7换到了win10 重装了开发环境 一直没什么问题 今天在调试spring cloud 时 发现无论如何都拉取不到配置文件, 通过微服务日志提示 Could not locate ...

  6. 【SpringCloud】Spring Cloud Config 配置中心

    文章目录 1.概述 1.1 是什么 1.2 怎么玩 1.3 怎么用 3.案例 3.1 案例1 3.1.1 配置 3.1.2 主类 3.1.3 Git信息 3.1.4 访问 4. 例子 5.客户端 5. ...

  7. Spring Cloud Config配置中心使用(草稿版)

    服务端搭建: cli:

  8. (十九)Alian 的 Spring Cloud Config 集群配置

    目录 一.简介 1.1.第一步 二.maven依赖 三.配置 3.1.application.properties 3.2.主类 四.客户端修改(支付系统) 4.1 maven依赖 4.2 支付系统主 ...

  9. 玩转Spring Cloud之配置中心(config server config client)

    玩转Spring Cloud之配置中心(config server &config client)  本文内容导航: 一.搭建配置服务中心(config server) 1.1.git方式 1 ...

最新文章

  1. 跟我学Spring Cloud(Finchley版)-16-Zuul
  2. empty怎么发音_empty,怎么读,解答要读出来,empty怎么读慢一点,清楚一点!
  3. 过去一个月发生了什么,C++再次真香了吗?
  4. python类型-python基础之五大标准数据类型
  5. 模态框在IE下的问题,即position:fixed在IE下不兼容的处理方式
  6. docker中部署Tomcat
  7. boost::graph模块实现分布式压缩稀疏行图类型的测试
  8. poj1673 EXOCENTER OF A TRIANGLE
  9. audiorecord怎么释放_Android 开发 AudioRecord音频录制
  10. 使用tcpdump,adb进行手机抓包
  11. linux保存编辑信息,linux系统编辑神器 -vim用法大全
  12. 《菜菜的机器学习sklearn课堂》学习笔记 + 课件
  13. Zabbix 3.0入门到企业实战阅读目录
  14. C语言谭浩强第三版例题及课后题汇总
  15. 工作中ibatis中的连表查询及in()的使用案例
  16. idea中自动生成Java类图和时序图
  17. 11.7 项目:下载所有 XKCD 漫画
  18. 【Docker】MySQL 主从配置(一主一从)
  19. 冯雪 手术机器人的应用_智能手术机器人及其应用_谢俊祥.
  20. BERT模型的结构,特点和实践

热门文章

  1. 快来一起拼团,惠购EasyRecovery
  2. 基于springboot开发的国际物流管理系统
  3. 微信小程序多文件上传(docx,ppt,pdf,zip,jpg···)
  4. 初二因式分解奥数竞赛题_[2018初二奥数因式分解练习题] 因式分解练习题
  5. mysql毫秒转分钟_[MYSQL]时间毫秒数转换
  6. SWD下载调试接口原理深度剖析
  7. Extjs grid 合并行
  8. 为什么我们要使用std::alloctor
  9. 达梦数据库查询与操作
  10. 如何在CSDN获取更多的铁粉?