菜鸟的springcloud学习总结(六):服务配置

说明

更新时间:2020/10/04 16:12,更新到了Spring Cloud Stream

本文主要对springcloud中的服务配置进行学习与记录,主要偏向于实战,本文会持续更新,不断地扩充

本文仅为记录学习轨迹,如有侵权,联系删除

一、服务配置

在这里插入图片描述
在分布式系统中,由于服务数量巨多,为了方便服务配置文件统一管理,实时更新,所以需要分布式配置中心组件。一个配置中心提供的核心功能,提供服务端和客户端支持,集中管理各环境的配置文件,配置文件修改之后,可以快速的生效,可以进行版本管理,支持大的并发查询,支持各种语言等

二、Spring Cloud Config

Spring Cloud Config项目是一个解决分布式系统的配置管理方案。它包含了Client和Server两个部分,server提供配置文件的存储、以接口的形式将配置文件的内容提供出去,client通过接口获取数据、并依据此数据初始化自己的应用。Spring cloud使用git或svn存放配置文件,默认情况下使用git,我们先以git为例做一套示例。

下面采用git加码云的方式进行演示

前期准备
先在码云上面创建一个仓库,用于存放分布式的配置文件,并且创建对应的几个yml配置文件,config-dev.yml、config-pro.yml、config-test.yml分别表示开发环境、生产环境和测试环境的配置文件

在这里插入图片描述

(1)Config服务端

创建Config服务端对应的子模块cloud-config-server-3344,引入pom坐标依赖

    <dependencies>
        <!--引入公共包-->
        <dependency>
            <groupId>com.zsc</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

        <!--spring cloud config 服务端包-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>


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

        <!--springboot starter启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--单元测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

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


    </dependencies>

重点是spring cloud config 服务端包,然后配置yml文件

server:
  port: 3344

spring:
  application:
    name: cloud-config-server3344
  cloud:
    config:
      server:
        git:
          #码云上面的配置的仓库地址,公有的不用设置密码
          uri: https://gitee.com/strong_rookie/spring-cloud-config.git

          #搜索目录
          search-paths:
            - Spring Cloud Config
      #读取分支
      label: master

#注册进eureka
eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/

主启动类,注意加上EnableConfigServer注解
在这里插入图片描述
之后就可以访问了,由于这里还注册了eureka,所以eureka服务注册中心也得打开
在这里插入图片描述
之后就可以访问了http://localhost:3344/master/config-pro.yml
在这里插入图片描述

(2)仓库上配置文件命名及访问

http请求地址和资源文件映射如下:

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

仓库上的配置文件可以按照上面的任一方式命名,上面的项目用的是第二种命名方式,例如:config-dev.yml

上面的命名方式决定了路径的访问方式,例如:config-dev.yml,访问时则是http://localhost:3344/master/config-dev.yml路径
在这里插入图片描述

(3)Config客户端

创建Config子模块cloud-config-client-3355,引入依赖


    <dependencies>
        <!--引入公共包-->
        <dependency>
            <groupId>com.zsc</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

        <!-- spring cloud config 客户端包 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>

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

        <!--springboot starter启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--单元测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

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


    </dependencies>

重点是spring cloud config 客户端包,然后创建配置文件bootstrap.yml

server:
  port: 3355

spring:
  application:
    name: cloud-config-client3355
  cloud:
    config:
      label: master  #分支名称
      name: config   #配置文件的名称
      profile: dev   #读取后缀名称
      uri: http://localhost:3344/  #配置config中心地址
      #上面的配置解释为:master分支上config-dev.yml的配置文件被读取,http://localhost:3344/master/config-dev.yml


#注册进eureka
eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/

#暴露监控端点,实现配置文件实时更新
management:
  endpoints:
    web:
      exposure:
        include: "*"

这里配置了配置文件实时更新,这样的话假设仓库上的配置文件修改了,也能实现实时的更新,当然,这之间还有一个小步骤

关于bootstrap.yml配置文件
在这里插入图片描述
然后是主启动类
在这里插入图片描述
然后是业务类,客户端通过接口的方式的将获取配置文件的内容,就是以rest风格将配置对外暴露
在这里插入图片描述
代码

@RestController
@RefreshScope//实现配置文件的实时更新
public class ConfigClientController {

    @Value("${server.version}")
    private String serverVersion;

    @GetMapping("/getServerVersion")
    public String getServerVersion(){
        return serverVersion;
    }
}

注意controller里面的类要实现实时的更新配置文件需要在每一个controller类上加一个刷新的注解
在这里插入图片描述
启动项目进行测试
在这里插入图片描述
访问接口http://localhost:3355/getServerVersion,可以获取配置文件的内容
在这里插入图片描述

如何实现实时更新配置文件内容,首先在远程仓库更新一下配置文件
在这里插入图片描述
再访问接口访问接口http://localhost:3355/getServerVersion发现还是version2.0,这是因为还有一个步骤,就是需要先发送一个post请求如下,用于提醒客户端我已经更新了配置文件
在这里插入图片描述
代码

curl -X POST "http://localhost:3355/actuator/refresh"

再访问接口http://localhost:3355/getServerVersion
在这里插入图片描述
当然这种是半自动化配置,虽然当修改完配置文件后,可以用脚本实现自动发送post以达到实时更新的目的

三、Spring Cloud Bus

上面的项目实现了客户端的配置的刷新,但是还有问题,当客户端越来越多的情况下,远程仓库上的配置改变后,客户端要得到最新的配置文件内容,则需要每一个客户端都要发送一个post请求在这里插入图片描述
这样的话,当有三四十个客户端的情况下,就会显得很麻烦,所以下面就有Spring Cloud Bus消息总线,用来实现一次广播,实现所有的客户端刷新

简单介绍Spring Cloud Bus
SpringCloud Bus使用轻量级消息代理将分布式系统的节点连接起来。然后可以使用此代理广播状态更改(例如配置更改)或其他管理指令。本文结合RabbitMQ+码云实现上面Config配置中心的自动刷新。

它的广播方式有两种,这里主要采用下面的广播方式
在这里插入图片描述
远程仓库上的配置文件修改之后,首先由服务端Config服务端发送一个post请求,Spring Cloud Bus接收到后,通过广播的方式将消息发送给所有的Config客户端,客户端实现配置文件的刷新

为什么被称为总线?
在这里插入图片描述
实战
下面直接开始实战,为了能看到广播的效果,必须要再创建一个Config客户端cloud-config-client-3366,内容基本跟cloud-config-client-3355一样,这里还需要先安装mq消息队列,并且可以访问

在这里插入图片描述

(1)Config服务端

在cloud-config-server-3344引入对应的坐标依赖

        <!-- 添加消息总线RabbitMQ支持 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>

修改配置文件,主要增加了mq的配置和bus刷新配置的端点
在这里插入图片描述

代码如下

server:
  port: 3344

spring:
  application:
    name: cloud-config-server3344
  cloud:
    config:
      server:
        git:
          #码云上面的配置的仓库地址,公有的不用设置密码
          uri: https://gitee.com/strong_rookie/spring-cloud-config.git
          #搜索目录
          search-paths:
            - Spring Cloud Config
      #读取分支
      label: master
  #添加mq配置
  rabbitmq:
    host: 39.96.22.34
    port: 5675
    username: guest
    password: guest
    virtual-host: /
#mq相关配置,暴露bus刷新配置的端点
management:
  endpoints:
    web:
      exposure:
        include: 'bus-refresh'


#注册进eureka
eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/

(2)Config客户端

客户端的配置文件修改,以3355项目为例,主要增加下面的坐标
在这里插入图片描述
代码

        <!-- 添加消息总线RabbitMQ支持 -->
        <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>

修改配置文件
在这里插入图片描述
代码

server:
  port: 3355

spring:
  application:
    name: cloud-config-client3355
  cloud:
    config:
      label: master  #分支名称
      name: config   #配置文件的名称
      profile: dev   #读取后缀名称
      uri: http://localhost:3344/  #配置config中心地址
      #上面的配置解释为:master分支上config-dev.yml的配置文件被读取,http://localhost:3344/master/config-dev.yml


#添加mq配置
  rabbitmq:
    host: 39.96.22.34
    port: 5675
    username: guest
    password: guest
    virtual-host: /

#注册进eureka
eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/

#暴露监控端点,实现配置文件实时更新
management:
  endpoints:
    web:
      exposure:
        include: "*"

注意:对3366项目也做同样的操作

启动项目
在这里插入图片描述
访问3355和3366项目,两个项目获取到的配置文件数据都是version3.0
在这里插入图片描述
现在在远程仓库上修改配置文件,改为4.0
在这里插入图片描述
此时所有的服务端和客户端还没有刷新,访问3355和3366项目接口,仍然是3.0
在这里插入图片描述
此时只需要Config服务端发送一个post请求即可通过广播的方式对所有的客户端进行刷新
在这里插入图片描述
代码

curl -X POST "http://localhost:3344/actuator/bus-refresh"

下面重新访问3355和3366项目,发现两个都进行了更新
在这里插入图片描述

此外还可以对某一个客户端进行更新,另一个则不更新,重新修改仓库上的配置文件为5.0
在这里插入图片描述
现在更新3355的配置,3366不更新
在这里插入图片描述
在这里插入图片描述

代码

curl -X POST "http://localhost:3344/actuator/bus-refresh/cloud-config-client3355:3355"

参数:
cloud-config-client3355:3355:3355项目yml配置文件中的spring.application.name,3355为对应端口

在这里插入图片描述

四、Spring Cloud Stream

简介
简单理解一下定义,Spring Cloud Stream 是一个构建消息驱动微服务的框架。应用程序通过 inputs 或者 outputs 来与 Spring Cloud Stream 中binder 交互,通过我们配置来 binding ,而 Spring Cloud Stream 的 binder 负责与消息中间件交互。所以,我们只需要搞清楚如何与 Spring Cloud Stream 交互就可以方便使用消息驱动的方式。

通过使用Spring Integration来连接消息代理中间件以实现消息事件驱动。Spring Cloud Stream 为一些供应商的消息中间件产品提供了个性化的自动化配置实现,引用了发布-订阅、消费组、分区的三个核心概念。目前仅支持RabbitMQ、Kafka。

为什么要用Srpring Cloud Stream
上面的项目已经实现了通过广播的方式实现一个post更新所有的客户端的配置更新功能,但是有一种情况下,假设一个项目里面用很多个微服务,里面用到的消息中间件既有mq,又有kafka,一个项目中有多个消息中间件,对于程序员,因为人员都不友好,这个时候就需要用到Spring Cloud Stream,它就类似jpa,屏蔽底层消息中间件的差异,程序员主要操作Spring Cloud Stream即可,而不需要管底层是kafka还是rabbitMq。

官方架构图
在这里插入图片描述
常用注解和api

组成说明
Middleware中间件,目前只支持RabbitMQ和Kafka
BinderBinder是应用与消息中间件之间的封装,目前实行了Kafka和RabbitMQ的Binder,通过Binder可以很方便的连接中间件,可以动态的改变消息类型(对应于Kafka的topic,RabbitMQ的exchange),这些都可以通过配置文件来实现
@Input注解标识输入通道,通过该输入通道接收到的消息进入应用程序
@Output注解标识输出通道,发布的消息将通过该通道离开应用程序
@StreamListener监听队列,用于消费者的队列的消息接收
@EnableBinding指信道channel和exchange绑定在一起

Spring Cloud Stream的业务流程
在这里插入图片描述

下面开始实战

(1)生产者

创建生产者cloud-stream-rabbitmq-provider8801,引入pom,这里只是使用Stream,所以不引入Eureka和Actutor


    <dependencies>
        <!--web启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

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

        <!--单元测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

配置yml
在这里插入图片描述
代码

server:
  port: 8801
spring:
  application:
    name: cloud-stream-rabbitmq-provider8801

  cloud:
      stream:
        binders: #在此处配置要绑定的rabbitmq的服务信息
          defaultRabbit: # 表示定义的名称。用于binding整合
            type: rabbit #消息组件类型
            environment: #设置rabbitmq的相关环境配置
              spring:
                rabbitmq:
                  host: 39.96.22.34
                  port: 5675
                  username: guest
                  password: guest
        bindings: #服务的整合过程
          output: #这个名字是一个通道的名称
            destination: studyExchange  #表示要使用的Exchange名称定义
            content-type: application/json #设置消息类型,
        binder: defaultRabbit #设置要绑定的消息服务的具体设置

主启动类
在这里插入图片描述
服务层创建生产者
接口

public interface IMessageProvider {
    public String send();
}

对应实现类

@EnableBinding(Source.class)
public class IMessageProviderImpl implements IMessageProvider {

    @Resource
    private MessageChannel output;

    @Override
    public String send() {
        String serial = UUID.randomUUID().toString();
        output.send(MessageBuilder.withPayload(serial).build());
        System.out.println("**********************serial = " + serial);
        return null;
    }
}

controller接口

@RestController
public class SendMessageController {
    @Resource
    private IMessageProvider messageProvider;

    @GetMapping("/sendMessage")
    public String sendMessage(){
        return messageProvider.send();
    }

}

生产者创建成功

(2)消费者

创建消费者模块1cloud-stream-rabbitmq-consumer8802,引入pom文件

    <dependencies>
        <!--web启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--stream rabbit -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>

        <!--单元测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

跟生产者几乎一样的pom,配置yml

server:
  port: 8802
spring:
  application:
    name: cloud-stream-rabbitmq-consumer8802

  cloud:
    stream:
      binders: #在此处配置要绑定的rabbitmq的服务信息
        defaultRabbit: # 表示定义的名称。用于binding整合
          type: rabbit #消息组件类型
          environment: #设置rabbitmq的相关环境配置
            spring:
              rabbitmq:
                host: 39.96.22.34
                port: 5675
                username: guest
                password: guest
      bindings: #服务的整合过程
        input: #这个名字是一个通道的名称2
          destination: studyExchange #表示要使用的Exchange名称定义,指定使用哪个Exchange
          content-type: application/json #设置消息类型,
          binder: defaultRabbit #设置要绑定的消息服务的具体设置
          group: zsc8802  #分组

主启动类
在这里插入图片描述
服务层创建消费者
在这里插入图片描述
代码

@Component
@EnableBinding(Sink.class)
public class ReceiveMessageListener {
    @Value("${server.port}")
    private String port;

    @StreamListener(Sink.INPUT)
    public void input(Message<String> message){
        System.out.println("消费者1号,---->接收到的消息:" + message.getPayload()+"\t port:"+port);
    }
}

创建完再创建一个消费者模块2cloud-stream-rabbitmq-consumer8803,步骤和配置跟上面一样,创建完启动这个3个项目
在这里插入图片描述
查看rabbitmq
在这里插入图片描述
点进对应的交换机,发现里面有俩个用户,一个属于zsc8802分组,一个属于zsc8803分组
在这里插入图片描述
此时发送8801生产者发送两条消息,两个消费者均消费了两条消息
在这里插入图片描述
如果将8802和8803项目分组分成同一个组,那么两条消息,会采用轮询的方式一人消费一条
在这里插入图片描述
重启项目,生成者再发送两条消息,则会一人一条
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值