Spring Cloud 之配置服务器(下)配置刷新

学习目标

本文所讲内容为上一文的后续,我们在上一文中学习了什么是 Spring Cloud 的配置服务器;如何使用两种方式搭建 Spring Cloud Config Server 以及客户端如何连接配置服务器。本文将以问题解答的形式一步步讲解如何刷新配置,所用示例项目仍为上文所用代码:

  • spring-cloud-chapter-3-config-server 端口:9090
  • spring-cloud-chapter-3-config-client 端口:8080

动态配置属性 Bean

当我们的服务发布到了服务器上后,我们想要修改配置文件中的某些配置,我们该怎么办呢?有些小伙伴就会说:“把服务停掉,修改配置文件后重新启动不就解决了”。的确,这是一种解决办法,但是并不是一种好的解决办法,停掉服务器会对用户产生很大的影响,尤其是在单体应用中,你把服务器停掉,别人就无法访问,客户就抓狂了,你的客服同事也会恨死你。那么这里我们就讲解一下如何动态配置,让服务正常运行的同时,修改配置信息。
1)在 spring-cloud-chapter-3-config-client 项目中定义配置属性 Bean User,此处使用了 @ConfigurationProperties(prefix = "xxx") 注解。

package top.alanshelby.springcloudchapter3configclient.domain;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "as.user")
public class User {

    private Long id;

    private String name;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

2)创建 UserController,并使用构造器的方式注入 User 对象,使用 @EnableConfigurationProperties(User.class) 注解。

package top.alanshelby.springcloudchapter3configclient.web.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import top.alanshelby.springcloudchapter3configclient.domain.User;

@RestController
@EnableConfigurationProperties(User.class)
public class UserController {

    private final User user;

    @Autowired
    public UserController(User user) {
        this.user = user;
    }

    @GetMapping("/user")
    public User user() {
        return user;
    }
}

3)将 User 关联配置项,在 application.properties 中进行配置

as.user.id = 1
as.user.name = AlanShelby

通过浏览器访问:http://localhost:8080/env/as.user.*

{
    "as.user.name":"AlanShelby",
    "as.user.id":"1"
}

可以看到我们的配置已经生效了,准备工作一切就绪,那么我们应该如何动态修改配置信息呢?这里我们需要借助 PostMan 工具来进行修改。

4)配置完成后,可以使用 PostMan 发送 POST 请求可动态修改参数信息

修改完成后,重新通过浏览器访问:http://localhost:8080/env/as.user.*,可以看到配置信息已经修改过来了,这样就实现了在不重启服务的前提下修改配置信息。

{
    "as.user.name":"spring-cloud",
    "as.user.id":"2"
}

说到这,不知道小伙伴们有没有什么疑问。我们所讲的内容为微服务方面的知识,也就是说不可能仅仅只有一个服务发布,如果在整个微服务项目中有几十个或者几百个服务实例,难道我们要手动挨个进行修改吗?不存在的,那样我们程序猿们早就撂挑子不干了,所以我们要想一个办法,能够调整所有机器的配置,那我们应该如何做呢?接下来,我们来一起解决这个问题。


问题:如果需要调整所有机器的配置应该如何操做?

解决这个问题前,我们要先搞明白一些事情,在上一文中我们讲了如何搭建 Spring Cloud Config Server,我们讲解了两种方式,这里我们要了解的是配置客户端应用所关联的分布式配置信息,优先于传统的配置信息,如 application.properties (application.yml)或者是 bootstrap.properties (bootstrap.yml),由此可知,要解决这个问题,我们可以对配置服务器配置信息进行调整(blogstemp-prod.properties)。
启动 spring-cloud-chapter-3-config-server 项目,服务端启动完毕后重启 spring-cloud-chapter-3-config-client 项目

注意:blogstemp-prod.properties 为上文中基于远程 git 仓库使用的配置文件,这里依旧使用它作为例子。

1)在 blogstemp-prod.properties 文件中添加如下信息:

as.user.id = 1000
as.user.name = AlanShelbyTest

修改完成后,将代码提交到 GitHub,访问:http://localhost:9090/blogstemp/prod,即可发现服务端配置信息就改过来了。

但是当我们访问客户端时:http://localhost:8080/env,就会发现,客户端并没有及时把服务端的配置信息同步过来,那这个应该如何解决呢?

这里我们可以使用 Spring Cloud 给我们提供的 refresh 端点来进行刷新操作,依旧使用 PostMan 进行操作:

请求完成后,会返回给我们修改的配置 key:

[
  "as.user.id",
  "config.client.version",
  "as.user.name"
]

重新访问 http://localhost:8080/env,就会发现我们刚刚修改的配置已经同步过来了。

chapter3.2-4.png

这样修改的分布式配置信息就可以应用于所有服务实例了,是不是一举多得。
客户端调整所有机器的配置的问题解决了,那么新的问题又出现了。我们刚刚使用了 Spring Cloud 给我们提供的 refresh 端点手动为客户端刷新了远程配置信息,这样很不方便,每次修改完信息后,都要有专门的人员来进行刷新操作,十分不友好,那么我们如何让服务端更新配置信息后,客户端进行感知后自动刷新呢?接下来我们就来解决一下这个问题。


问题:如果服务端更新了,客户端如何感知?

从上面我们已经知道了可以使用 Spring Cloud 给我们提供的 refresh 端点手动进行刷新操作,客户端感知说白了就是客户端定时刷新,所以我们使用一个简易的定时任务就可以解决这个问题,这种方式只是一种解决办法,较为简单、方便,还有很多其他的解决方式(如官方文档中提供的整合 Spring Cloud Bus 和 spring-cloud-config-monitor),这里只是提供解决思路,读者可自行斟酌使用。

1)使用构造器注入的方式将 ContextRefresher 进行注入,使用定时任务每5秒(根据需求自行设定)对上下文进行一次刷新,这里使用了 contextRefresher.refresh() 进行刷新。

package top.alanshelby.springcloudchapter3configclient;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.context.refresh.ContextRefresher;
import org.springframework.scheduling.annotation.Scheduled;

import java.util.Set;

@SpringBootApplication
public class SpringCloudChapter3ConfigClientApplication {

    private final ContextRefresher contextRefresher;

    // 使用构造器注入的方式将 contextRefresher 进行注入
    @Autowired
    public SpringCloudChapter3ConfigClientApplication(ContextRefresher contextRefresher) {
        this.contextRefresher = contextRefresher;
    }

    @Scheduled(fixedRate = 5000L)
    public void update() {
        Set<String> keys = contextRefresher.refresh();

        if (!keys.isEmpty()) {
            System.out.println("本次更新的配置项:" + keys);
        }
    }

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

2)修改 blogstemp-prod.properties 配置文件,并提交到远程 GitHub 仓库

as.user.id = 1001
as.user.name = Shelby

3)查看日志信息,可以看到输入如下信息,表明上下文的刷新操作完成:

本次更新的配置项:[as.user.id, config.client.version, as.user.name]

至此,关于Spring Cloud Config Server(配置服务器)所有内容就讲解完了,这是我的理解,各位看官如果有不同见解或文章中有错误,请不吝指正。
所用代码码云地址:https://gitee.com/AlanShelby/spring-cloud-chapter
知乎专栏地址:https://zhuanlan.zhihu.com/c_200981602
个人微信公众号:AlanShelby(多多关注,感谢~)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342