前言

对于微服务而言配置本地化是个很大的鸡肋,不可能每次需要改个配置都要重新把服务重新启动一遍,因此最终的解决方案都是将配置外部化,托管在一个平台上达到不用重启服务即可一次修改多处生效的目的。

但是对于单体应用的Spring Boot项目而言,动态刷新显然是有点多余,反正就一个服务,改下重启不就行了?

然而在某些特殊的场景下还是必须用到动态刷新的,如下:

  1. 添加数据源:对接某个第三方平台的时候,你不可能每次添加一个数据源都要重启下服务
  2. 固化的对接:大量的固定对接方式,只是其中的某个固定的代码段不同,比如提供视图中的字段不同,接口服务中字段不同等情况。

当然以上列举的两种场景每个公司都有不同的解决方案,这里不做深究。

微服务下有哪几种主流的方案?

微服务下的动态配置中心有三种主流的方式,如下图:

上图中的三种配置中心方案可以说是现在企业中使用率最高的,分别是:

  1. Nacos:阿里巴巴的最近开源的项目,这个家伙很牛逼,一个干掉了Eureka(停更)和Config+Bus,既能作为配置中心也能作为注册中心,并且有自己的独立的 管理平台,可以说是现在最主流的一种。

  2. Config+Bus:早期在用的微服务配置中心,可以依托GitHub管理微服务的配置文件,这种现在也是有不少企业在用,但是需要自己独立部署一个微服务,和Nacos相比逊色了不少。

  3. Apollo:携程开源项目Apollo,这个也是不少企业在用,陈某了解的不多,有兴趣的可以深入研究下。

针对Spring Boot 适用的几种方案?

其实上述三种都可以在Spring Boot项目中适配,但是作为单体应用有些重了,下面作者简单的介绍两种可用的方案。

Spring Boot+Nacos(不推荐)

不得不说阿里巴巴确实挺有野心,阿里要做其实是一个微服务生态,Nacos不仅仅可以作为Spring Cloud的配置和注册中心,也适配了Dubbo、K8s,官方文档中对于如何适配都做了详细的介绍,作者 这里就不再详细介绍了,如下图:

当然Nacos对Spring、Spring Boot 项目同样适用。

如何使用呢?这里作者只提供下思路,不做过多的深究,这篇在作者下个专栏Spring Cloud 进阶会详细介绍:

  1. 下载对应版本的Nacos,启动项目,访问http://localhost:8848进入Nacos的管理界面;

  2. Spring Boot 项目引入Nacos的配置依赖nacos-config-spring-boot-starter,配置Nacos管理中心的地址。

  3. @NacosPropertySource@NacosValue两个注解结合完成。

  • @NacosPropertySource:指定配置中心的dataId,和是否自动刷新
  • @NacosValue替代@Value注解完成属性的自动装配
  1. 如果公司项目做了后台管理,则可以直接调用Nacos开放的API修改对应配置的值(替代了Nacos管理界面的手动操作),API的地址:https://nacos.io/zh-cn/docs/open-api.html

此种方案虽说可以实现配置的动态刷新,但是还要集成Nacos,启动一个Nacos的服务,完全是有点大材小用了,实际项目中不推荐使用。

Spring Boot+Config+actuator(推荐)

此种方案实际使用的是Config配置中心,但是不像Nacos那般重,完全适用于单体应用的SpringBoot项目,只需要做小部分的更改即可达到效果。

方案一(不推荐)

  1. 添加Config的依赖,如下:
  1. <!-- springCloud的依赖-->
  2. <dependencyManagement>
  3. <dependencies>
  4. <dependency>
  5. <groupId>org.springframework.cloud</groupId>
  6. <artifactId>spring-cloud-dependencies</artifactId>
  7. <version>Hoxton.SR3</version>
  8. <type>pom</type>
  9. <scope>import</scope>
  10. </dependency>
  11. </dependencies>
  12. </dependencyManagement>
  13. <!-- config的依赖-->
  14. <dependency>
  15. <groupId>org.springframework.cloud</groupId>
  16. <artifactId>spring-cloud-starter-config</artifactId>
  17. </dependency>
  18. <!-- actuator的依赖-->
  19. <dependency>
  20. <groupId>org.springframework.boot</groupId>
  21. <artifactId>spring-boot-starter-actuator</artifactId>
  22. </dependency>
  1. 配置文件中暴露Spring Boot的端点,如下:
  1. management.endpoints.web.exposure.include=*
  1. 配置文件中新增三个属性配置:
  1. config.version=22
  2. config.app.name=dynamic-project
  3. config.platform=mysql
  1. 结合@RefreshScope注解动态刷新,写个Controller,如下:
  1. @RestController
  2. //@RefreshScope该注解必须标注,否则无法完成动态更新
  3. @RefreshScope
  4. public class DynamicConfigController {
  5. @Value("${config.version}")
  6. private String version;
  7. @Value("${config.app.name}")
  8. private String appName;
  9. @Value("${config.platform}")
  10. private String platform;
  11. @GetMapping("/show/version")
  12. public String test(){
  13. return "version="+version+"-appName="+appName+"-platform="+platform;
  14. }
  1. 启动项目测试,浏览器访问http://localhost:8080/show/version,返回信息如下图:

  1. 修改target目录下的配置文件,如下:
  1. config.version=33
  2. config.app.name=dynamic-project
  3. config.platform=ORACLE
  1. POST请求http://localhost:8080/actuator/refresh接口,手动刷新下配置(必须,否则不能自动刷新)

  2. 浏览器再次输入http://localhost:8080/show/version,结果如下图:

可以看到,配置已经自动修改了,结束。

方案二(推荐)

看到了方案一觉得如何?是不是有点鸡肋了

第一个问题:为什么还要调用一次手动刷新呢?

第二个问题:只能手动的在配置文件中改吗?如果想在后台管理系统改怎么办?

想要解决上述两个问题还是要看下Config的源码,代码关键部分在org.springframework.cloud.context.refresh.ContextRefresher#refresh()方法中,如下图:

因此只需要在修改属性之后调用下ContextRefresher#refresh()(异步,避免一直阻塞等待)方法即可。

为了方便测试,我们自己手动写一个refresh接口,如下:

  1. @GetMapping("/show/refresh")
  2. public String refresh(){
  3. //修改配置文件中属性
  4. HashMap<String, Object> map = new HashMap<>();
  5. map.put("config.version",99);
  6. map.put("config.app.name","appName");
  7. map.put("config.platform","ORACLE");
  8. MapPropertySource propertySource=new MapPropertySource("dynamic",map);
  9. //将修改后的配置设置到environment中
  10. environment.getPropertySources().addFirst(propertySource);
  11. //异步调用refresh方法,避免阻塞一直等待无响应
  12. new Thread(() -> contextRefresher.refresh()).start();
  13. return "success";
  14. }

上述代码中作者只是手动设置了配置文件中的值,实际项目中可以通过持久化的方式从数据库中读取配置刷新。

下面我们测试看看,启动项目,访问http://localhost:8080/show/version,发现是之前配置在application.properties中的值,如下图:

调用refresh接口:http://localhost:8080/show/refresh重新设置属性值;

再次调用http://localhost:8080/show/version查看下配置是否修改了,如下图:

从上图可以发现,配置果然修改了,达到了动态刷新的效果。

总结

本文从微服务的配置中心介绍到Spring Boot 搭建简易的配置中心,详细介绍了几种可行性的方案,作者强力推荐最后一种方案,简化版的Config,完全适用于单体应用。

如何让Spring Boot 的配置动起来?的更多相关文章

  1. 玩转spring boot——properties配置

    前言 在以往的java开发中,程序员最怕大量的配置,是因为配置一多就不好统一管理,经常出现找不到配置的情况.而项目中,从开发测试环境到生产环境,往往需要切换不同的配置,如测试数据库连接换成生产数据库连 ...

  2. Spring Boot 属性配置和使用

    Spring Boot 属性配置和使用 Spring Boot 允许通过外部配置让你在不同的环境使用同一应用程序的代码,简单说就是可以通过配置文件来注入属性或者修改默认的配置. Spring Boot ...

  3. Spring Boot 属性配置和使用(转)

    Spring Boot 属性配置和使用 Spring Boot 允许通过外部配置让你在不同的环境使用同一应用程序的代码,简单说就是可以通过配置文件来注入属性或者修改默认的配置. Spring Boot ...

  4. Sping Boot入门到实战之入门篇(四):Spring Boot自动化配置

    该篇为Sping Boot入门到实战系列入门篇的第四篇.介绍Spring Boot自动化配置的基本原理与实现.   Spring Boot之所以受开发者欢迎, 其中最重要的一个因素就是其自动化配置特性 ...

  5. Springboot 系列(三)Spring Boot 自动配置原理

    注意:本 Spring Boot 系列文章基于 Spring Boot 版本 v2.1.1.RELEASE 进行学习分析,版本不同可能会有细微差别. 前言 关于配置文件可以配置的内容,在 Spring ...

  6. 转:spring boot log4j2配置(使用log4j2.yml文件)---YAML 语言教程

    转:spring boot log4j2配置(使用log4j2.yml文件) - CSDN博客http://blog.csdn.net/ClementAD/article/details/514988 ...

  7. Spring Boot自动配置与Spring 条件化配置

    SpringBoot自动配置 SpringBoot的自动配置是一个运行时(应用程序启动时)的过程,简化开发时间,无需浪费时间讨论具体的Spring配置,只需考虑如何利用SpringBoot的自动配置即 ...

  8. Spring Boot自动配置原理、实战

    Spring Boot自动配置原理 Spring Boot的自动配置注解是@EnableAutoConfiguration, 从上面的@Import的类可以找到下面自动加载自动配置的映射. org.s ...

  9. Spring Boot 揭秘与实战 附录 - Spring Boot 公共配置

    Spring Boot 公共配置,配置 application.properties/application.yml 文件中. 摘自:http://docs.spring.io/spring-boot ...

随机推荐

  1. TinyML-TVM如何驯服TinyML

    TinyML-TVM如何驯服TinyML 低成本,以人工智能为动力的消费类设备的激增,导致机器学习研究人员和从业人员对"裸机"(低功耗,通常没有操作系统)设备产生了广泛的兴趣.尽管 ...

  2. Vue项目开发环境搭建

    初步学习vue.js相关知识,下面是我搭建环境中一些经验总结,希望可以帮到有需要的同学.首选先安装好以下的工具和环境. 一.软件安装 1.WebStorm官网下载地址:https://www.jetb ...

  3. SQL注入问题------JDBC编写简单登录代码

    一.什么是sql注入 sql注入:用户输入的内容, 有一些sql的特殊关键字参与字符串的拼接,完成了一条逻辑发生变化的新的SQL语句 !用代码举个例子简单说明一下: package cn.zhbit. ...

  4. centos7 安装 bbr加速

    脚本安装 1 查看内核版本 # [root@os]# uname -a Linux os 3.10.0-1127.13.1.el7.x86_64 x86_64 x86_64 x86_64 GNU/Li ...

  5. 【渗透实战】记一次艰难的内网漫游第四期_蹭我WIFI?看我如何利用组合拳日进蹭网者内网

    /文章作者:Kali_MG1937 CSDN博客ID:ALDYS4 QQ:3496925334/ 内网漫游系列第三期:[渗透实战]记一次艰难的内网漫游第三期_我是如何利用APT攻击拿到内网最高权限的 ...

  6. teprunner重磅更新Git打通PyCharm与测试平台

    经过Python测试交流群的小伙伴群策群力,teprunner添加了一个重要功能,把PyCharm中的代码,通过Git同步到测试平台中,生成测试用例.这样,teprunner就成了一个名副其实的pyt ...

  7. docker安装nextcloud私人网盘,开启https配置证书

    docker安装nextcloud私人网盘 之前一直用的百度网盘最近svip超级会员到期了,续费要¥199元,对于一个打工人的我来说有点儿贵.作为技术人的一员,我就来发挥发挥自己的长处,来搭建一个私人 ...

  8. 学习响应式编程 Reactor (1) - 响应式编程

    响应式编程 命令式编程(Imperative Programing),是一种描述计算机所需做出的行为的编程范式.详细的命令机器怎么(How)去处理以达到想要的结果(What). 声明式编程(Decla ...

  9. Java核心API-日期时间

    java.util.Date Date类用来表示时间点. 时间是用距离一个固定时间点的毫秒数表示的,这个时间点就是纪元. UTC时间是为表示这个纪元的科学标准时间,从1970年1月1日0时开始.另一种 ...

  10. Redis高并发快的3大原因详解

    1. Redis的高并发和快速的原因 1.redis是基于内存的,内存的读写速度非常快: 2.redis是单线程的,省去了很多上下文切换线程的时间: 3.redis使用多路复用技术,可以处理并发的连接 ...