Spring Cloud学习笔记(十一)Spring Cloud Bus消息总线

简介

在学习配置中心Config之后可以知道,在微服务体系中,把各服务配置信息存放到Config中,通过向Config Server同步即可获得配置文件信息。每次我们存放在Config Server的信息被更改之后,都需要各微服务自行去同步,(比如重启,或者利用一种WebHook的机制刷新,稍后介绍)如果每次都手动同步,当微服务规模成百上千,这种方式显示是不合适的。那么通过刚才提到的WebHook机制(如不了解WebHook,请自行搜素),触发同步操作,借着我们今天学习的主角Spring Cloud Bus来同步发送通知给其它服务更新,看上去会简单很多,如下图,详细流程为:

Spring Cloud Bus将分布式系统的节点与轻量级消息代理连接起来,这可以用于广播状态更改,其本质是利用了MQ的广播机制在分布式系统中传播消息,目前常用的有Kafka和RabbitMQ,配置更改就是其典型应用场景。

根据上图,我们可以利用Spring Cloud Bus做配置更新,步骤如下:

  • 提交配置文件到GIT,触发post请求给Config Client C,发送bus/refresh
  • Config Client C接收到请求从Config Server更新配置并且发送给Spring Cloud Bus
  • Spring Cloud Bus接收到消息并通知给其它Config Client
  • 其它Config Client请求Config Server端获取最新配置

准备工作

首先下载安装RabbitMQ,根据操作系统等选择版本下载安装,我是Windows环境,下载了rabbitmq-server-3.8.2.exe安装版,安装RabbitMQ还需安装Erlang,安装之后可以在Windows服务里启停服务,测试一下,输入地址http://localhost:15672,用户名密码guest,可以正常登录就OK了

改造Config Client

由于Config Client要访问MQ,所以加入其依赖。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.dothwinds</groupId>
        <artifactId>spring-cloud-study-config</artifactId>
        <version>1.0.0</version>
    </parent>
    <groupId>org.dothwinds</groupId>
    <artifactId>spring-cloud-study-config-client</artifactId>
    <version>1.0.0</version>
    <name>spring-cloud-study-config-client</name>

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

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

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

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

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

    </dependencies>

</project>

修改bootstrap.yml,加入相关RabbitMQ、Spring Cloud Bus配置

server:
  port: 12002
spring:
  cloud:
    config:
      uri: http://localhost:12000/  #config server
      profile: dev #读取的配置文件后缀名
    bus:
      enabled: true
      trace:
        enabled: true
  application:
    name: config-client
  profiles:
    active: dev
  rabbitmq: #rabbitmq配置
    host: localhost
    username: guest
    password: guest
    port: 5672

eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka
management:
  endpoints:
    web:
      exposure:
        include: bus-refresh #启用bus-refresh的endpoint

启动类代码加入@RefreshScope

package org.dothwinds.springcloudstudyconfigclient;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
@EnableEurekaClient
@RefreshScope
public class SpringCloudStudyConfigClientApplication {

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

    @Value("${name}")
    private String name;

    @GetMapping("/getName")
    public String getName(){
        return name;
    }
}

测试 

 依次启动Eureka Server、Config Server和Config Client,其中Config Client我们换不同端口启动两次

访问Config Client的URL地址测试http://localhost:12001/getNamehttp://localhost:12002/getName,均返回

接下来,更改GIT上的这个名字,改成如下值

name: test-dothwinds111

接下来,在其中的一个Config Client触发一下/actuator/bus-refresh

curl -X POST http://localhost:12001/actuator/bus-refresh

再次访问,值变了

访问另外一个服务,如下图,成功返回修改后的值。

提示:在springboot2.x的版本中路径为:/actuator/bus-refresh,在springboot1.5.x的版本中刷新路径为:/bus/refresh。 

上述方式的升级改进

上述方式,我们虽然借用了消息总线的方式,手动触发从而达到刷新所有微服务读取配置信息,那么这种方式显然也不是十分合适的,原因如下:

  • 打破了微服务的职责单一性,微服务本身是业务模块,不应该承担配置刷新的职责
  • 破坏了微服务各节点的对等性
  • 如果客户端ip有变化,这时我们就需要修改WebHook的配置

改进方式就是把WebHook的触发放到Config Server中来做,如下图所示

也就是当GIT的更新的时候,触发Config Server的/bus/refresh请求,然后通过Spring Cloud Bus同步更新到各个Config Client

改造Config Server

 改造方式同Config Client,修改POM、配置文件及启动类即可,启动服务,修改GIT上的配置文件为:

name: dothwinds

在Config Server触发一下/actuator/bus-refresh

curl -X POST http://localhost:12000/actuator/bus-refresh

接着在Config Client读取配置文件的值,成功返回

以上WebHook动作都是我们自己手动触发,实际的生产环境,我们可以在GIT上配置WebHook,每当提交代码的时候GIT通过WebHook自动触发bus-refresh动作,如下图配置。

参考资料:https://cloud.spring.io/spring-cloud-static/Greenwich.SR5/single/spring-cloud.html

代码地址:https://gitee.com/dothwinds/Spring-Cloud-Study/tree/master/spring-cloud-study-config  

发布了23 篇原创文章 · 获赞 74 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/Dothwinds/article/details/105225224
今日推荐