Spring Cloud Config 为微服务架构中的微服务提供集中化的外部配置支持,配置服务器为各个不同微服务应用的所有环境提供了一个中心化的外部配置。

 特点:

  • 集中管理配置文件
  • 不同环境不同配置,动态化的配置更新,分环境部署。
  • 运行期间动态调整配置,不再需要在每个服务器上编写配置文件,服务会向配置中兴统一拉取配置自己的信息。
  • 当配置发生变动时,服务不需要重启即可感知到配置的变化并应用到新的配置。
  • 将配置信息以REST接口的形式暴露

与Github整合配置,由于SpringCloudConfig默认使用Git来存储配置文件(也有其他方式如:SVN和本地文件),但最推荐的还是Git,而且使用的是http/https访问的方式。

在github新建仓库,然后再将仓库克隆到本地。

新建配置中心模块

1,POM文件

    <dependencies>
        <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>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

2,YML文件

server:
  port: 3001

eureka:
  instance:
    instance-id: config3001
    prefer-ip-address: true
    lease-renewal-interval-in-seconds: 30
    lease-expiration-duration-in-seconds: 90
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka
    fetch-registry: true
    register-with-eureka: true

spring:
  application:
    name: config-eureka-client  #对应的application
  cloud:
    config:
      server:
        git:
          uri: https://github.com/flygoldfish/cloud2020-config.git
          search-paths: config #目录
          default-label: main  #分支

3,主启动类

@SpringBootApplication
@EnableEurekaClient
@EnableConfigServer
public class ConfigCenter3001Main {
    public static void main(String[] args) {
        SpringApplication.run(ConfigCenter3001Main.class,args);
    }
}

然后用http://localhost:3001/config-single-client-dev.yml即可访问到github上的内容,当github上仓库的内容发生变更,请求的结果也会跟着变更。

application.yml和bootstrap.yml

application.yml是用户级的资源配置文件;bootstrap.yml是系统级的,优先级更高。

Spring Cloud 会创建一个“Bootstrap Context”,作为Spring的应用的Application Context的父上下文。初始化的时候,"Bootstrap Context"负责从外部源加载配置属性并解析配置。这两个上下文共享一个从外部获取的“Environment”。

“Bootstrap”属性有高优先级,默认情况下,它们不会被本地配置覆盖。“Bootstrap Context”和"Application Context"有着不同的约定,所以新增了一个bootstrap.yml文件,保证Bootstrap Context和Application Context配置的分离。

因为bootstrap.yml是比application.yml先加载的。bootstrap.yml优先级高于application.yml。

Config客户端需要配置bootstrap.yml文件。

Config客户端配置

1,新建项目

2,POM文件

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    </dependencies>

3,YML文件

bootstrap.yml

spring:
  profiles:
    active: dev

eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka
  instance:
    instance-id: configclient3002
    prefer-ip-address: true
    lease-expiration-duration-in-seconds: 90
    lease-renewal-interval-in-seconds: 30

---
spring:
  profiles: dev
  application:
    name: config-eureka-client-service
  cloud:
    config:
      discovery:
        enabled: true
        service-id: config-eureka-server  #配置服务端的服务名
      label: main      #git 分支
      profile: dev     #环境
      #uri: http://localhost:3001
      name: config-eureka-client  #应用程序名

---
spring:
  profiles: prod
  application:
    name: config-eureka-client-service
  cloud:
    config:
      discovery:
        enabled: true
        service-id: config-eureka-server
      label: main
      profile: prod
      #uri: http://localhost:3001
      name: config-eureka-client

4,主启动类

@SpringBootApplication
@EnableEurekaClient
public class ConfigClient3002Main {
    public static void main(String[] args) {
        SpringApplication.run(ConfigClient3002Main.class,args);
    }
}

5,业务类

public class User{
    private String username;
    private String password;

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}
@Component
@ConfigurationProperties(prefix = "data")  #将配置文件中的内容注入到对象中
public class Data {
    private String env;
    private User user;

    @Override
    public String toString() {
        return "Data{" +
                "env='" + env + '\'' +
                ", user=" + user +
                '}';
    }

    public String getEnv() {
        return env;
    }

    public void setEnv(String env) {
        this.env = env;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

}

6,RestController访问

@RestController
public class ConfigController {

    @Autowired
    private Data data;

    @GetMapping("/data")
    public Data getData(){
        return data;
    }
}

但是这种情况配置出现的问题是,当github上的仓库内容更改,Config服务端会立即更改,但Config客户端不会更改。

如:

 

 

 

 客户端动态刷新

1,Config客户端POM添加actuator依赖,图形化监控

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    </dependencies>

2,Config客户端配置YML文件,暴露监控端点

spring:
  profiles:
    active: dev

eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka
  instance:
    instance-id: configclient3002
    prefer-ip-address: true
    lease-expiration-duration-in-seconds: 90
    lease-renewal-interval-in-seconds: 30

#暴露监控端点
management:
  endpoints:
    web:
      exposure:
        include: "*"
---
spring:
  profiles: dev
  application:
    name: config-eureka-client-service
  cloud:
    config:
      discovery:
        enabled: true
        service-id: config-eureka-server
      label: main
      profile: dev
      #uri: http://localhost:3001
      name: config-eureka-client

---
spring:
  profiles: prod
  application:
    name: config-eureka-client-service
  cloud:
    config:
      discovery:
        enabled: true
        service-id: config-eureka-server
      label: main
      profile: prod
      #uri: http://localhost:3001
      name: config-eureka-client

3,@RefreshScope注解添加到使用的地方,如Controller

@RestController
@RefreshScope
public class ConfigController {

    @Autowired
    private Data data;

    @GetMapping("/data")
    public Data getData(){
        return data;
    }
}

4,发送POST请求,Config客户端加/actuator/refresh,如:http://localhost:3002/actuator/refresh。

 

 

 但是这样可以实现刷新,但是当Config客户端很多时,这样的操作就不可取。

SpringCloud Bus

Spring Cloud Bus是用来将分布式系统的节点与轻量级消息系统链接起来的框架。Spring Cloud Bus提供分布式自动刷新配置功能,配合Spring Cloud Config使用可以实现配置的动态刷新。

Spring Cloud Bus 整合了Java的事件处理机制和消息中间件的功能。Bus目前支持两种消息代理:RabbitMQ和kafka。

 

 在微服务架构的系统中,通常会使用轻量级的消息代理来构建一个共用的消息主题,并让系统中所有微服务实例连接上来。由于该主题中产生的小心会被所有实例监听和消费,所以称之为消息总线。在总线上的各个实例,都可以方便地广播一些需要让其他连接在该主题上的实例都知道的消息。

基本原理:

Config Client实例都监听MQ中同一个topic(默认是SpringCloudBus)。当一个服务刷新数据的时候,它会把这个消息放入到topic中,这样其他监听同一topick的服务就能得到通知,然后去更新自身的配置。

RabbitMQ环境配置

1,安装Erlang,

2,安装RabbitMQ

3,进入安装RabbitMQ安装目录下的sbin目录,输入以下命令启动管理功能。安装可视化插件,rabbit-plugins enable rabbitmq_management

4,查看是否安装成功:http://localhost:15672/

5,默认账号和密码都是guest。

有两种方式刷新

1,利用消息总线触发一个客户端/bus/refresh,从而刷新所有客户端的配置。

 

 2,利用消息总线触发一个服务端Config Server的/bus/refresh端点,从而刷新所有客户端的配置。推荐使用这种方式。

 

 系统示例

1,Config 服务端模块

POM文件,新增bus-amqp依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>
        <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>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
    </dependencies>

YML文件,新增web监控和rabbitmq配置

server:
  port: 3001

eureka:
  instance:
    instance-id: config3001
    prefer-ip-address: true
    lease-renewal-interval-in-seconds: 30
    lease-expiration-duration-in-seconds: 90
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka
    fetch-registry: true
    register-with-eureka: true

spring:
  application:
    name: config-eureka-server
  cloud:
    config:
      server:
        git:
          uri: https://github.com/flygoldfish/cloud2020-config.git
          search-paths: config
          default-label: main
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest

management:
  endpoints:
    web:
      exposure:
        include: "bus-refresh"

2,Config客户端模块

POM文件,添加对bus-amqp依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>
        <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>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
    </dependencies>

YML文件,新增web监控和rabbitmq配置

spring:
  profiles:
    active: dev
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest

eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka
  instance:
    instance-id: configclient3002
    prefer-ip-address: true
    lease-expiration-duration-in-seconds: 90
    lease-renewal-interval-in-seconds: 30

#暴露监控端点
management:
  endpoints:
    web:
      exposure:
        include: "*"
---
spring:
  profiles: dev
  application:
    name: config-eureka-client-service
  cloud:
    config:
      discovery:
        enabled: true
        service-id: config-eureka-server
      label: main
      profile: dev
      #uri: http://localhost:3001
      name: config-eureka-client

---
spring:
  profiles: prod
  application:
    name: config-eureka-client-service
  cloud:
    config:
      discovery:
        enabled: true
        service-id: config-eureka-server
      label: main
      profile: prod
      #uri: http://localhost:3001
      name: config-eureka-client

其他保持不变,另外其他分布式Config 客户端节点与该节点配置类似。

3,发送POST请求,host+端口+/actuator/bus-refresh。如:http://localhost:3001/actuator/bus-refresh。一次发送,处处生效。

刷新定点通知

指定某一个实例生效而不是全部生效。

http://localhost:配置中心的端口号/actuator/bus-refresh/{destination}。/bus/refresh请求不再发送到具体的服务实例上,而是发给config server并通过destination参数类指定需要更新配置的服务或实例。

如:http://localhost:3001/actuator/bus-refresh/config-eureka-client-service:3003,这就是定点刷新,其中destination是微服务名+端口号。

 

 posted on 2021-01-08 22:23  会飞的金鱼  阅读(432)  评论(0)    收藏  举报