Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

Stella981
• 阅读 621

技术背景

如今微服务架构盛行,在分布式系统中,项目日益庞大,子项目日益增多,每个项目都散落着各种配置文件,且随着服务的增加而不断增多。此时,往往某一个基础服务信息变更,都会导致一系列服务的更新和重启,运维也是苦不堪言,而且还很容易出错。于是,配置中心便由此应运而生了。

目前市面上开源的配置中心有很多,像Spring家族的Spring Cloud Config, Apache的Apache Commons Configuration,淘宝的diamond, 百度的disconf, 360的QConf等等,都是为了解决这类问题。当下Spring体系大行其道,我们当然也优先选择Spring Cloud Config了。

Spring Cloud Config

Spring Cloud Config 是一套为分布式系统中的基础设施和微服务应用提供集中化配置的管理方案,它分为服务端与客户端两个部分。服务端也称为分布式配置中心,它是一个独立的微服务应用,用来连接配置仓库并为客户端提供获取配置信息。客户端则是微服务架构中的各个微服务应用或基础设施,它们通过指定的配置中心来管理服务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息。

Spring Cloud Config对服务端和客户端中的环境变量和属性配置 实现了抽象映射,所以它除了适用于 Spring 应用,也是可以在任何其他语言应用中使用的。Spring Cloud Config 实现的配置中心默认采用 Git 来存储配置信息,所以使用 Spring Cloud Config 构建的配置服务器,天然就支持对微服务应用配置信息的版本管理,并且可以通过 Git 客户端工具非常方便的管理和访问配置内容。当然它也提供了对其他存储方式的支持,比如:SVN 仓库、本地化文件系统等。

实现案例

准备配置文件

 首先在GIT下,新建config-repo目录,用来存放配置文件,如下图所示,分别模拟了三个环境的配置文件。

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

 分别编辑三个文件,配置 comsumer.hello 属性的值为 comsumer.hello=hello, this is xx configurations.

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

服务端实现

新建工程

新建 kitty-conifg 工程,作为配置中心的服务端,负责把GIT仓库的配置文件发布为RESTFul接口。

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

添加依赖

除了Spring Cloud依赖之外,添加配置中心依赖包。

pom.xml

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

<!--spring config-->
<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-config-server</artifactId>
    </dependency>
</dependencies>

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

启动类

启动类添加注解 @EnableConfigServer,开启配置服务支持。

KittyConfigApplication.java

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

package com.louis.kitty.config;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.config.server.EnableConfigServer;

@EnableConfigServer
@EnableDiscoveryClient
@SpringBootApplication
public class KittyConfigApplication {

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

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

配置文件

修改配置文件,添加如下内容。如果是私有仓库需要填写用户名密码,如果是公开仓库,可以不配置密码。

application.yml

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

server:
  port: 8020
spring:
  application:
    name: kitty-config
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        serviceName: ${spring.application.name}    # 注册到consul的服务名称
    config:     label: master  # git仓库分支
      server:
        git:
          uri: https://gitee.com/liuge1988/kitty.git  # 配置git仓库的地址
          search-paths: config-repo  # git仓库地址下的相对地址,可以配置多个,用,分割。
          username: username  # git仓库的账号
          password: password  # git仓库的密码

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

Spring Cloud Config也提供本地存储配置的方式,只需设置属性spring.profiles.active=native,Config Server会默认从应用的src/main/resource目录下检索配置文件。另外也可以通过spring.cloud.config.server.native.searchLocations=file:D:/properties/属性来指定配置文件的位置。虽然Spring Cloud Config提供了这样的功能,但是为了更好的支持内容管理和版本控制,还是比较推荐使用GIT的方式。

测试效果

启动注册中心,配置中心,访问 http://localhost:8020/kitty-consumer/dev,返回结果如下。

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

{
    "name": "kitty-consumer",
    "profiles": ["dev"],
    "label": null,
    "version": "1320259308dfdf438f5963f95cbce9e0a76997b7",
    "state": null,
    "propertySources": [{
        "name": "https://gitee.com/liuge1988/kitty.git/config-repo/kitty-consumer-dev.properties",
        "source": {
            "consumer.hello": "hello, this is dev configurations. "
        }
    }]
}

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

访问 http://localhost:8020/kitty-consumer/pro,返回结果如下。

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

{
    "name": "kitty-consumer",
    "profiles": ["pro"],
    "label": null,
    "version": "1320259308dfdf438f5963f95cbce9e0a76997b7",
    "state": null,
    "propertySources": [{
        "name": "https://gitee.com/liuge1988/kitty.git/config-repo/kitty-consumer-pro.properties",
        "source": {
            "consumer.hello": "hello, this is pro configurations. "
        }
    }]
}

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

上述的返回的信息包含了配置文件的位置、版本、配置文件的名称以及配置文件中的具体内容,说明server端已经成功获取了git仓库的配置信息。

访问:http://localhost:8020/kitty-consumer-dev.properties,返回结果如下。

 Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

修改一下dev配置文件内容如下(末尾加了一个 2):

 Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

再次访问:http://localhost:8020/kitty-consumer-dev.properties,返回结果如下。

 Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

发现读取的是修改后提交的信息,说明服务端会自动读取最新提交的数据。

仓库中的配置文件会被转换成相应的WEB接口,访问可以参照以下的规则:

  • /{application}/{profile}[/{label}]
  • /{application}-{profile}.yml
  • /{label}/{application}-{profile}.yml
  • /{application}-{profile}.properties
  • /{label}/{application}-{profile}.properties

以kitty-consumer-dev.properties为例子,它的application是kitty-consumer,profile是dev。client会根据填写的参数来选择读取对应的配置。

客户端实现

添加依赖

打开kitty-consumer工程,添加相关依赖。

pom.xml

<!-- spring-cloud-config -->
<dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-config</artifactId>
</dependency>

配置文件

添加一个bootstrap.yml配置文件,添加配置中心,并把注册中心的配置移到这里,因为在通过配置中心查找配置时需要通过注册中心的发现服务。

bootstrap.yml

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

spring:
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        serviceName: ${spring.application.name}    # 注册到consul的服务名称
    config:
      discovery:
        enabled: true  # 开启服务发现
        serviceId: kitty-config # 配置中心服务名称
      name: kitty-consumer  # 对应{application}部分
      profile: dev  # 对应{profile}部分
      label: master  # 对应git的分支,如果配置中心使用的是本地存储,则该参数无用

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

配置说明:

  • spring.cloud.config.uri:配置中心的具体地址
  • spring.cloud.config.name:对应{application}部分
  • spring.cloud.config.profile:对应{profile}部分
  • spring.cloud.config.label:对应git的分支。如果配置中心使用的是本地存储,则该参数无用
  • spring.cloud.config.discovery.service-id:指定配置中心的service-id,便于扩展为高可用配置集群。

特别注意:

上面这些与spring cloud相关的属性必须配置在bootstrap.yml中,这样config部分内容才能被正确加载。

因为config的相关配置会先于application.yml,而bootstrap.yml的加载也是先于application.yml文件的。

application.yml

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

server:
  port: 8005
spring:
  application:
    name: kitty-consumer
  boot:
    admin:
      client:
        url: "http://localhost:8000"
  zipkin:
    base-url: http://localhost:9411/
  sleuth:
    sampler:
      probability: 1 #样本采集量,默认为0.1,为了测试这里修改为1,正式环境一般使用默认值
# 开放健康检查接口
management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    health:
      show-details: ALWAYS
#开启熔断器
feign:
  hystrix:
    enabled: true

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

控制器

添加一个 SpringConfigController 控制器, 添加注解 @Value("${comsumer.hello}"),声明hello属性从配置文件读取。

SpringConfigController.java

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

package com.louis.kitty.consumer.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
class SpringConfigController {
    
    @Value("${comsumer.hello}")
    private String hello;

    @RequestMapping("/hello")
    public String from() {
        return this.hello;
    }
}

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

测试效果

启动注册中心、配置中心,访问: http://localhost:8500,确认相关服务启动并注册。

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

访问 http://localhost:8005/hello,返回结果。

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

说明客户端已经成功从服务端读取了配置信息。

现在手动修改一下仓库配置文件的内容,移除末尾数字 2,修改完成并提交。

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

 再次访问 http://localhost:80052/hello,效果如下。

 Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

我们发现返回结果并没有读取最新提交的内容,这是因为Spring Boot项目只有在启动的时候才会获取配置文件的内容,虽然GIT配置信息被修改了,但是客户端并没有重新去获取,所以导致读取的信息仍然是旧配置。那么该如何去解决这个问题呢?这就是我们下一章要讲的 Spring Cloud Bus。

Refresh机制

我们在上面讲到,Spring Boot程序只在启动的时候加载配置文件信息,这样在GIT仓库配置修改之后,虽然配置中心服务器能够读取最新的提交信息,但是配置中心客户端却不会重新读取,以至于不能及时的读取更新后的配置信息。这个时候就需要一种通知刷新机制来支持了。

refresh机制是Spring Cloud Config提供的一种刷新机制,它允许客户端通过POST方法触发各自的/refresh,只要依赖spring-boot-starter-actuator包就拥有了/refresh的功能,下面我们为我们的客户端加上刷新功能,以支持更新配置的读取。

添加依赖

我们的 kitty-consumer 在之前已经添加过actuator依赖,所以这里就不用添加了,如果之前没有添加需要加上。actuator是健康检查依赖包,依赖包里携带了 /refresh 的功能。

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

在使用配置属性的类型加上 @RefreshScope 注解,这样在客户端执行 /refresh 的时候就会刷新此类下面的配置属性了。

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

package com.louis.kitty.consumer.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RefreshScope
@RestController
class SpringConfigController {
    
    @Value("${consumer.hello}")
    private String hello;

    @RequestMapping("/hello")
    public String from() {
        return this.hello;
    }
}

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

修改配置

健康检查接口开放需要在配置文件添加以下内容,开放refresh的相关接口,因为这个我们在之前也配置过了,所以也不需添加了。

management:
  endpoints:
    web:
      exposure:
        include: "*"

通过上面的接口开放配置,以后以post请求的方式访问 http://localhost:8005/actuator/refresh 时,就会更新修改后的配置文件了。

特别注意:

这里存在着版本大坑,1.x跟2.x的配置不太一样,我们用的是2.0+版本,务必注意。

1.安全配置变更

新版本

management.endpoints.web.exposure.include="*"

老版本

management.security.enabled=false

2.访问地址变更

新版本

http://localhost:8005/actuator/refresh

老版本

http://localhost:8005/refresh

这里还是解释一下上面这个配置起到了什么具体作用,其实actuator是一个健康检查包,它提供了一些健康检查数据接口,refresh功能也是其中的一个接口,但是为了安全起见,它默认只开放了health和info接口(启动信息会包含如下图所示信息),而上面的配置就是设置要开放哪些接口, 我们设置成 “*”,是开放所有接口。你也可以指定开发几个,比如: health,info,refresh,而这里因为我们需要用的refresh功能,所以需要把refresh接口开放出来。

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

设置成 “*” 后,启动信息会包含以下信息,而这个叫refresh的post方法,就是我们需要的,上面说的接口地址变更从这里也可以看得出来。

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

测试效果

重新启动服务,访问 http://localhost:8005/hello,返回结果如下。

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

修改仓库配置内容,末尾加个数字 5,如下图所示。

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

再次访问 http://localhost:8005/hello,如我们所料,结果并没有更新,因为我们还没有调refresh方法。

通过工具或自写代码发送post请求 http://localhost:8005/actuator/refresh,刷新配置。

这里通过在线测试网站发送,地址:https://getman.cn/Mo2FX 。

注意:先让你的Chrome支持跨域。设置方法:在快捷方式的target后加上 --disable-web-security --user-data-dir,重启即可。

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

刷新之后,再次访问 http://localhost:8005/hello,返回结果如下。

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

查看返回结果,刷新之后已经可以获取最新提交的配置内容,但是每次都需要手动刷新客户端还是很麻烦,如果客户端数量一多就简直难以忍受了,有没有什么比较好的办法来解决这个问题呢,那是当然的,答案就是:Spring Cloud Bus。

Spring Cloud Bus

Spring Cloud Bus,被大家称为消息总线,它通过轻量级的消息代理来连接各个分布的节点,可以利用像消息队列的广播机制在分布式系统中进行消息传播,通过消息总线可以实现很多业务功能,其中对于配置中心客户端刷新,就是一个非常典型的使用场景。

下面这张图可以很好的解释消息总线的作用流程(图片描述来源:纯洁的微笑:配置中心博文)。

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

Spring Cloud Bus 进行配置更新步骤如下:

  1、提交代码触发post请求给/actuator/bus-refresh

  2、server端接收到请求并发送给Spring Cloud Bus

  3、Spring Cloud bus接到消息并通知给其它客户端

  4、其它客户端接收到通知,请求Server端获取最新配置

  5、全部客户端均获取到最新的配置

安装RabbitMQ

因为我们需要用到消息队列,我们这里选择RabbitMQ,使用Docker进行安装。

拉取镜像

执行以下命令,拉取镜像。

docker pull rabbitmq:management

完成之后执行以下命令查看下载镜像。

docker images

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

创建容器

执行以下命令,创建docker容器。

docker run -d --name rabbitmq -p 5671:5671 -p 5672:5672 -p 4369:4369 -p 25672:25672 -p 15671:15671 -p 15672:15672 rabbitmq:management

启动成功之后,可以执行以下命令查看启动容器。

docker ps

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

登录界面

容器启动之后就可以访问web管理界面了,访问 http://宿主机IP:15672。

系统提供了默认账号。 用户名:guest  密码: guest

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

管理界面

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

客户端实现

添加依赖

打开客户端 kitty-consumer,添加消息总线相关依赖。

pom.xml

<!-- bus-amqp -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>

修改配置

修改配置,添加RebbitMq的相关配置,这样客户端代码就改造完成了。

bootstrap.yml

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

spring:
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        serviceName: ${spring.application.name}    # 注册到consul的服务名称
    config:
      discovery:
        enabled: true  # 开启服务发现
        serviceId: kitty-config # 配置中心服务名称
      name: kitty-consumer  # 对应{application}部分
      profile: dev  # 对应{profile}部分
      label: master  # 对应git的分支,如果配置中心使用的是本地存储,则该参数无用
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

服务端实现

添加依赖

修改 kitty-conifg,添加相关依赖。

pom.xml

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

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

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

修改配置,添加RabbitMq的和接口开放相关配置,这样服务端代码也改造完成了。

application.yml 

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

server:
  port: 8020
spring:
  application:
    name: kitty-config
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        serviceName: ${spring.application.name}    # 注册到consul的服务名称
    config:
      label: master  # git仓库分支
      server:
        git:
          uri: https://gitee.com/liuge1988/kitty.git  # 配置git仓库的地址
          search-paths: config-repo  # git仓库地址下的相对地址,可以配置多个,用,分割。
          username: username  # git仓库的账号
          password: password  # git仓库的密码
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
management:
  endpoints:
    web:
      exposure:
        include: "*"

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

测试效果

1.启动服务端,成功集成消息总线后,启动信息中可以看到如下图中的信息。

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

2.启动客户端,发现居然报错了,网上也找不到相关资料,也没见其他人提过相关问题。猜测是网上教程多是使用Euraka,而这里用的时Consul,瞎鼓捣了好久,反正是不想换回Euraka,2.0停止开发消息出来以后,将来还不定什么情况,只能硬着头皮解决了。

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'configServerRetryInterceptor' available
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:685) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1210) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:204) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE]
    at org.springframework.retry.annotation.AnnotationAwareRetryOperationsInterceptor.getDelegate(AnnotationAwareRetryOperationsInterceptor.java:180) ~[spring-retry-1.2.2.RELEASE.jar:na]
    at org.springframework.retry.annotation.AnnotationAwareRetryOperationsInterceptor.invoke(AnnotationAwareRetryOperationsInterceptor.java:151) ~[spring-retry-1.2.2.RELEASE.jar:na]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.8.RELEASE.jar:5.0.8.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) ~[spring-aop-5.0.8.RELEASE.jar:5.0.8.RELEASE]
    at org.springframework.cloud.config.client.ConfigServerInstanceProvider$$EnhancerBySpringCGLIB$$dd44720b.getConfigServerInstances(<generated>) ~[spring-cloud-config-client-2.0.0.RELEASE.jar:2.0.0.RELEASE]
    at org.springframework.cloud.config.client.DiscoveryClientConfigServiceBootstrapConfiguration.refresh(DiscoveryClientConfigServiceBootstrapConfiguration.java:84) [spring-cloud-config-client-2.0.0.RELEASE.jar:2.0.0.RELEASE]
    at org.springframework.cloud.config.client.DiscoveryClientConfigServiceBootstrapConfiguration.startup(DiscoveryClientConfigServiceBootstrapConfiguration.java:69) [spring-cloud-config-client-2.0.0.RELEASE.jar:2.0.0.RELEASE]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_131]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_131]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_131]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_131]

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

然后就跟踪代码,发现是在下图中的位置找不到相应的Bean,那么答案就比较明显了,要么是程序有BUG,不过可能性不大,那应该是就是缺包了,在缺失的包里有这个Bean。但是这个Bean是在哪个包?排查了半天也没找到,网上也没有想过资料,对比了一下网上消息总线的配置,依赖也没有少加什么。

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

没有办法,最后只能自己上手了,不就是在刷新的时候缺少一个拦截器吗,自己给他弄一个试试呗。

使用就加了一个配置类,并在resources下新建了META-INF目录和一个spring。factories文件。

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

RetryConfiguration.java

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

package com.louis.kitty.consumer;

import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.retry.interceptor.RetryInterceptorBuilder;
import org.springframework.retry.interceptor.RetryOperationsInterceptor;

public class RetryConfiguration {
    @Bean
    @ConditionalOnMissingBean(name = "configServerRetryInterceptor")
    public RetryOperationsInterceptor configServerRetryInterceptor() {
        return RetryInterceptorBuilder.stateless().backOffOptions(1000, 1.2, 5000).maxAttempts(10).build();
    }
}

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

spring.factories

org.springframework.cloud.bootstrap.BootstrapConfiguration=com.louis.kitty.consumer.RetryConfiguration

在这里指定新建的拦截器,这样系统初始化时会加载这个Bean。

然后重启启动,果然没有报错了,还是先别高兴,看看能不能用先。

4.先访问一下 http://localhost:8005/hello,效果如下图所示。

 Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

5.修改仓库配置文件,把数字5改成15,修改完成提交。

 Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

再次访问发现还是旧信息。

6.再用工具发送post请求 http://localhost:8020/actuator/bus-refresh 。

注意这次是向注册中心服务端发送请求,发送成功之后服务端会通过消息总线通知所有的客户端进行刷新。

另外开启消息总线后的请求地址是 /actuator/bus-refresh,不再是refresh了。

Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

7.给服务端发送刷新请求之后,再次访问 http://localhost:8005/hello,结果如下(需要一点刷新时间)。

 Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

我们愉快的发现客户端已经能够通过消息总线获取最新配置了。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Easter79 Easter79
3年前
springcloud eureka.instance
1.在springcloud中服务的 InstanceID默认值是:${spring.cloud.client.hostname}:${spring.application.name}:${spring.application.instance\_id:${server.port}},也就是:主机名:应用名:应用端口。如图1
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这