springcloud config 实现将配置存储在数据库并配合eureka实现高可用

背景说明

  1. 公司有十几个服务,预测随着业务的发展,服务数量可能会越来越多,而为了更快的进行服务开发和集中管理,提出将配置抽取到数据库的方案。达到配置和业务剥离又可以集中管理的效果,比如许多服务都会用到像kafka,mysql,redis,hbase等一些配置,这些配置本身其实和业务没有关系,如果将这些配置抽取出来复用,是不是很完美?
  2. 为啥不配合使用git,而是mysql?

技术点

springcloud config + mysql + eureka

实现思路

  1. 各微服务获取配置时经过注册中心
  2. 注册中心分配配置中心服务的某个节点
  3. 分配的节点从数据库获取配置返回

代码实现

搭建配置中心服务

  1. 引入config-server,mysql,jdbc等相关依赖
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-config-server</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>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka</artifactId>
		</dependency>
  1. application.yml配置文件

#基础信息
info:
  service:
    name: ${spring.application.name}
    des: 配置中心服务

spring:
  #数据源配置
  datasource:
    url: jdbc:mysql://你的ip:3306/你的数据库?useSSL=false&serverTimezone=UTC
    username: root
    password: 你的密码
    driver-class-name: com.mysql.jdbc.Driver
    hikari:
      connection-test-query: SELECT 1 FROM DUAL
      connection-timeout: 30000
      maximum-pool-size: 23
      max-lifetime: 1800000
      minimum-idle: 5

#springcloud config 配置
  profiles:
    active: jdbc
  application:
    name: config-server
  cloud:
    config:
      server:
        jdbc: true
spring.cloud.config.server.jdbc.sql: SELECT
                                         t.configuration_key,
                                         t.configuration_value
                                     FROM
                                         (
                                     SELECT
                                         t3.configuration_key,
                                         t3.configuration_value,
                                         t1.NAME,
                                         t1.env,
                                         t1.label
                                     FROM
                                         service_info t1
                                         INNER JOIN service_basis t2 ON t1.id = t2.ser_id
                                         INNER JOIN configuration t3 ON t2.cf_nickname = t3.nickname UNION ALL
                                     SELECT
                                         t2.configuration_key,
                                         t2.configuration_value,
                                         t1.NAME,
                                         t1.env,
                                         t1.label
                                     FROM
                                         service_info t1
                                         INNER JOIN customcf t2 ON t1.id = t2.ser_id
                                         ) t
                                     WHERE
                                         t.`name` = ?
                                         AND t.`env` = ?
                                         AND t.`label` = ?

#注册中心配置
eureka:
  instance:
    instance-id: ${spring.cloud.client.ipAddress}:${server.port}
    prefer-ip-address: true
  client:
    healthcheck:
      enabled: true
    serviceUrl:
      defaultZone: 注册中心地址

#配置中心端口
server:
  port: 18000

  • 这里的sql是根据具体的业务。
@Override
	public Environment findOne(String application, String profile, String label) {
		String config = application;
		if (StringUtils.isEmpty(label)) {
			label = "master";
		}
		if (StringUtils.isEmpty(profile)) {
			profile = "default";
		}
		if (!profile.startsWith("default")) {
			profile = "default," + profile;
		}
		String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
		Environment environment = new Environment(application, profiles, label, null,
				null);
		if (!config.startsWith("application")) {
			config = "application," + config;
		}
		List<String> applications = new ArrayList<String>(new LinkedHashSet<>(
				Arrays.asList(StringUtils.commaDelimitedListToStringArray(config))));
		List<String> envs = new ArrayList<String>(new LinkedHashSet<>(Arrays.asList(profiles)));
		Collections.reverse(applications);
		Collections.reverse(envs);
		for (String app : applications) {
			for (String env : envs) {
				Map<String, String> next = (Map<String, String>) jdbc.query(this.sql,
						new Object[] { app, env, label }, this.extractor);
				if (!next.isEmpty()) {
					environment.add(new PropertySource(app + "-" + env, next));
				}
			}
		}
		return environment;
	}
  • 服务如果启动的时候打断点会进到JdbcEnvironmentRepository类的findOne方法中,其实就是把KEY,VALUE取出来放到Map再放到Environment中。数据库查询操作是通过JdbcTemplate来实现的,所以也就印证了为啥要引入jdbc依赖。
  1. 启动类中加入注解
@SpringBootApplication
@EnableConfigServer
@EnableDiscoveryClient
public class ConfigServerApplication {

	public static void main(String[] args) {
		SpringApplication.run(ConfigServerApplication.class, args);
	}

}

创建表

  • JdbcEnvironmentRepository类中有DEFAULT_SQL,所以新建个PROPERTIES表再加上KEY,VALUE,APPLICATION,PROFILE,LABEL这几个字段完全可以
@ConfigurationProperties("spring.cloud.config.server.jdbc")
public class JdbcEnvironmentRepository implements EnvironmentRepository, Ordered {

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

搭建客户端服务

  1. 引入config,eureka依赖

  2. bootstrap.yml(一定要是bootstrap,加载优先级高)


#配置中心连接配置
spring:
  application:
    name: 你的服务名
  cloud:
    config:
      fail-fast: true
      #应用名
      name: ${spring.application.name}
      #环境 dev test  pro
      profile: test
      #分支
      label: master
      discovery:
        enabled: true
        #高可用
        service-id: config-server

#注册中心配置
eureka:
  instance:
    instance-id: ${spring.cloud.client.ipAddress}:${server.port}
    prefer-ip-address: true
    appname: ${spring.application.name}
  client:
    serviceUrl:
      defaultZone: 注册中心地址
  1. application.yml

#健康检查
#eureka.client.healthcheck.enabled=true should only be set in  application.yml. Setting the value in bootstrap.yml will cause undesirable side effects like registering in eureka with an  UNKNOWN status.
eureka:
  client:
    healthcheck:
      enabled: true

参考文档

  • https://forezp.blog.csdn.net/article/details/87866560
  • https://cloud.spring.io/spring-cloud-config/single/spring-cloud-config.html#_jdbc_backend

源码

https://github.com/forezp/SpringCloudLearning/tree/master/chapter10-5-jdbc

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Cloud Config Server注册到Eureka注册心的步骤如下: 1. 首先需要在pom.xml文件添加Eureka Client的依赖,如下所示: ```xml <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> <version>2.2.1.RELEASE</version> </dependency> ``` 2. 在应用程序的配置文件添加以下配置: ```yaml eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ ``` 其,`defaultZone`指定了Eureka Server的地址。 3. 在Spring Boot应用程序类上添加@EnableEurekaClient注解,以将Config Server注册到Eureka Server上: ```java @EnableConfigServer @EnableDiscoveryClient @SpringBootApplication public class ConfigServerApplication { public static void main(String[] args) { SpringApplication.run(ConfigServerApplication.class, args); } } ``` 4. 运行Config Server应用程序,查看Eureka Server的管理页面(http://localhost:8761)上是否已经注册成功。 5. 客户端应用程序可以通过以下方式从Config Server获取配置: ```yaml spring: application: name: client-service cloud: config: uri: http://localhost:8888 fail-fast: true retry: maxAttempts: 20 multiplier: 1.5 maxInterval: 5000 label: master ``` 其,`cloud.config.uri`指定了Config Server的地址,`spring.application.name`指定了客户端应用程序的名称,`label`指定了Git仓库的分支名称。 6. 运行客户端应用程序,即可从Config Server获取配置

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值