SpringCloud(三)配置中心和消息总线

在SpringCloud的微服务架构中,随着服务的不断迭代增加,为了方便管理,使用配置中心使所有服务能够被集中管理。在SpringCloud的配置中心,有两个角色:其一是ConfigServer,是从github、gitee、gitlab等网络管理资源中取出配置。其二是ConfigClient,也就是各个服务,他们是配置的实际使用者。

1、ConfigServer

新建一个Config的modular项目,并加入依赖(如下所示),spring-cloud-config-server是ConfigServer的依赖。它也是一个服务,我直接将它注册到服务中心中。

<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>

然后在启动类上加入注解@EnableConfigServer,表示这是一个配置中心的Server项目

@SpringBootApplication
@EnableEurekaClient
@EnableConfigServer
public class ConfigApplication {

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

}

最后是配置文件

eureka:
  client:
    service-url:
      defaultZone: http://root:root@localhost:1001/eureka/
spring:
  application:
    name: config
  cloud:
    config:
      server:
        git:
          uri: https://github.com/XXXXXXXX/config-cloud
          username:
          password:
          basedir: /config/basedir
          search-paths: repos
server:
  port: 2002

uri: git项目的仓库地址
username、password: 如果git项目是公开的,这两个值不需要输入
basedir:使用基于VCS的后端(git,svn)文件被检出或克隆到本地文件系统。 默认情况下,它们放在系统临时目录中,前缀为config-repo-。 在linux上,例如可以是/tmp/config-repo- <randomid>。 一些操作系统会定期清除临时目录。 这可能会导致意外的行为,例如缺少属性。 为避免此问题,请通过将spring.cloud.config.server.git.basedir或spring.cloud.config.server.svn.basedir设置为不驻留在系统临时结构中的目录来更改Config Server所使用的目录。
search-paths: 在git项目下,如果配置文件存储的位置不是在根目录下而是一些文件夹下面,那么则使用该配置指定文件夹路径,配置文件在该仓库的search-paths路径下

接下来是配置的读取
启动项目可以看到这样一些信息

我们可以通过一些系统给我们提供的接口去访问配置信息的内容
格式如下:

"{[/{name}-{profiles}.properties],methods=[GET]}"
"{[/{name}-{profiles}.yml || /{name}-{profiles}.yaml],methods=[GET]}"
"{[/{name}/{profiles:.*[^-].*}],methods=[GET]}" 
"{[/{label}/{name}-{profiles}.yml || /{label}/{name}-{profiles}.yaml],methods=[GET]}"
"{[/{name}/{profiles}/{label:.*}],methods=[GET]}" 
"{[/{name}-{profiles}.json],methods=[GET]}" 
"{[/{label}/{name}-{profiles}.properties],methods=[GET]}"
"{[/{label}/{name}-{profiles}.json],methods=[GET]}"
"{[/{name}/{profile}/{label}/**],methods=[GET],produces=[application/octet-stream]}"
"{[/{name}/{profile}/{label}/**],methods=[GET]}"
"{[/{name}/{profile}/**],methods=[GET],params=[useDefaultLabel]}"

其实说白了也没有那么复杂,我们可以根据上面的任意一种格式去读取信息,其中有三个值是供我们填写的
name 文件名: 配置文件的抬头名
profiles 环境: 即dev、test、prod
label 分支: 不填的话默认是master分支
例如 product-dev.proties中,name为product,profiles为dev,具体实践如下

下面是几种不同请求的结果


yml

json结尾

properties结尾

注意:在设置文件的时候,如果一个配置文件叫做order.yml,那么我们光使用localhost:2002/order.json或localhost:2002/order.properties是不能访问到信息的,我们必须输入一个profiles,这个时候profiles可以是任意值代替,它读取的内容都一样。


2、ConfigClient

服务是作为配置的具体使用者,也就是Client端,他们从ConfigServer中读取对应的配置文件,接下来我将对之前的两个服务product和order的配置文件进行改造。(这里只写order服务)

在order的modular项目中加入依赖

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

下面这一段很重要
在配置文件改造之前,需要提前bootstrap.yml和application.yml的加载顺序以及相关的其他信息,bootstrap.yml是在加载上下文阶段就读取的系统配置。
在加入上面的依赖后,ConfigClient项目启动过程中,会自动取加载ConfigServer从github中读取的配置,这个地方需要我们将注册服务和连接ConfigServer的配置放置在bootstrap.yml中。必须要提前装载,因为如果放置在application.yml中,服务会从默认配置中心默认的8888端口中读取服务,而不是我这个项目之前设定的2002端口。
除非我是用的ConfigServer的端口也是8888,那么就也可以放在application.yml中了。



所以我把之前application.yml改造成了bootstrap.yml

eureka:
  client:
    service-url:
      defaultZone: http://root:root@localhost:1001/eureka/

spring:
  application:
    name: order
  cloud:
    config:
      discovery:
        enabled: true
        service-id: config
      label: master
      profile: test

配置的过程就是将{name}/{profile}/{label}解析的过程
与之前ConfigServer读取配置文件一样,我们的spring.application.name 就是我们要读取的文件的 name,这个很重要。
discovery.enabled:true 表明使用配置中心读取配置
discovery.service-id:config 使用服务中的ConfigServer的service-id
label 分支
profile 环境

按照我上面的配置,意义就是在配置中心中找到名为config的服务,将它读取github的配置中的名为 order-test.yml(properties)的配置读取出来并加载到当前项目。

3、消息总线

到目前为止还存在这么一个问题:如果github的配置被修改提交了,它实际上没有立即加载到ConfigServer上,按照以往的项目经验。如果一些静态内容改动了,尝试刷新一些缓存。那如果底层配置文件改了呢,我们需要先重启ConfigServer,再重启ConfigClient项目。要是只能这样的话岂不是我们做了半天只将一些配置整合到了一起而已,看起来作用并不大。

因此SpringCloud还提供给了我们一个工具(Spring Cloud Bus)。它的定位是 Spring Cloud 体系内的消息总线,使用 message broker 来连接分布式系统的所有节点。它的主要作用是在git中的配置文件修改了之后,主动去通知使用配置中心的节点并更新配置。

我这儿使用了rabbitMQ作为承载消息的中间件,也可以选择别的kafka、activeMQ等。我选择rabbitMQ的原因是我只会这个emmmm

首先在config 、order、product三个modular项目中都加入了依赖(如下),并在order、product中配置rabbitMQ的配置信息

<dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
spring:
  rabbitmq:
    host: xxxx 
    port: 5672
    username: guest 
    password: guest

在项目启动后,会发现在rabbitMQ中自动增加了三个随机命名的队列(config、order、product)。当服务关闭之后,对应服务的队列会自动消失。

Queues
测试消息总线
spring cloud bus 的实际上在ConfigServer配置中心内使用了一个POST方式提交的bus-refresh的接口去推送和刷新配置信息,这个接口并没有直接暴露给我们,需要我们去配置下面这个内容才能使用
management:
  endpoints:
    web:
      exposure:
        include: "*"

重启order项目之后就可以看到暴露了bus-refresh接口

bus-refresh



再接下来,我使用在order服务中的雪花算法的配置文件作为修改点进行消息总线的测试。原来的配置是这样

snowflake:
  datacenterId: 3
  machineId: 4

通过在Order中写入一个测试方法去读取
这里的Controller上必须加入一个 @RefreshScope 注解

@Value("${snowflake.machineId}")
Long machineId;

@Value("${snowflake.datacenterId}")
Long datacenterId;

@GetMapping("getSnowFlake")
public void getSnowFlake( ){
   log.info("datacenterId : {}",datacenterId);
   log.info("machineId : {}",machineId);
}

第一次读取内容的结果是


result

现在我设置新的值为

snowflake:
  datacenterId: 7
  machineId: 8

再次执行测试方法,执行结果是:

可以看到结果并没有按照预想的一样,变成了7和8,这个时候需要我们去ConfigServer项目(我这儿端口是2002)执行post的/actuator/bus-refresh接口

postman

执行结果,可以看到rabbitMQ执行了消息的传递

rabbitMQ



最新执行结果,修改后的值已经被刷新到了order服务中

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