springCloud config 實現高可用的分佈式配置並能夠自動刷新配置

        爲了方便服務配置文件統一管理,更易於部署、維護,因此就須要分佈式配置中心組件了,在spring cloud中,有分佈式配置中心組件spring cloud config,它支持配置文件放在在配置服務的內存中,也支持放在遠程Git倉庫裏。本項目採用的是springBoot2.0.2版本,版本不一致,配置以及訪問會有所變化java

       在github上面建立一個項目springCloud-config存放配置文件: https://github.com/ningcs/springCloud-configgit

建立了一個config-client-dev.properties用於訪問,內容: name=ningcs。github

爲了實現config的高可用,引入eureka,上篇博文已經介紹,web

咱們在這裏只需引入便可spring

eureka.client.serviceUrl.defaultZone=http://localhost:18170/eureka/

詳細eureka代碼詳見地址: https://github.com/ningcs/stocks/tree/master/eureka-serverapache

  建立config服務端:config-serverjson

配置文件bootstrap

spring.application.name=config-server
server.port=18173
spring.profiles.active=dev
#eureka配置
eureka.client.serviceUrl.defaultZone=http://localhost:18170/eureka/
# 配置git倉庫地址
spring.cloud.config.server.git.uri=https://github.com/ningcs/springCloud-config
#配置文件所在的目錄
spring.cloud.config.server.git.search-paths=/**
# 配置倉庫的分支
spring.cloud.config.label=master

# 訪問git倉庫的用戶名
spring.cloud.config.server.git.username=ningcs
# 訪問git倉庫的用戶密碼 若是Git倉庫爲公開倉庫,能夠不填寫用戶名和密碼,若是是私有倉庫須要填寫
spring.cloud.config.server.git.password=xxx

啓動類添加@EnableConfigServer 瀏覽器

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@EnableEurekaClient
@EnableConfigServer
@SpringBootApplication
public class ConfigServerApplication {

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

pom文件緩存

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>

   <groupId>com.example</groupId>
   <artifactId>demo</artifactId>
   <version>1.0.0</version>
   <packaging>jar</packaging>

   <name>config-server</name>
   <description>Demo project for Spring Boot</description>

   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>2.0.2.RELEASE</version>
      <relativePath/> <!-- lookup parent from repository -->
   </parent>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
      <spring-cloud.version>Finchley.SR1</spring-cloud.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-config-server</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
      <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
      </dependency>
   </dependencies>

   <dependencyManagement>
      <dependencies>
         <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
         </dependency>
      </dependencies>
   </dependencyManagement>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>


</project>

服務端配置完成,下面驗證一下服務端的配置有沒有什麼問題,依次啓動eureka-server、config-server,在瀏覽器裏輸入

http://localhost:18173/config-client-dev.properties

name: ningcs

說明訪問到了 

證實配置服務中心能夠從遠程程序獲取配置信息,http請求地址和資源文件映射以下:,可參考

·        /{application}/{profile}[/{label}]

·        /{application}-{profile}.yml

·        /{label}/{application}-{profile}.yml

·        /{application}-{profile}.properties

·        /{label}/{application}-{profile}.properties

    建立config客戶端:config-client

在resources目錄下新建文件bootstrap.properties,內容:

#eureka配置
eureka.client.serviceUrl.defaultZone=http://localhost:18170/eureka/
#開啓配置服務發現
spring.cloud.config.discovery.enabled=true
#配置服務實例名稱
spring.cloud.config.discovery.service-id=config-server
# 指明配置服務中心的網址
spring.cloud.config.uri=http://localhost:18173
#配置文件所在分支
spring.cloud.config.label=master
#配置所使用文件類別 dev-開發,test測試,pro生產
spring.cloud.config.profile=dev
#spring.cloud.config.fail-fast:true
##自動刷新配置 默認 health,info
management.endpoints.web.exposure.include=refresh,health,info
##是否須要權限拉去,默認是true,若是不false就不容許你去拉取配置中心Server更新的內容
management.security.enabled=false

pom:

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>

   <groupId>com.example</groupId>
   <artifactId>demo</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>

   <name>config-client</name>
   <description>Demo project for Spring Boot</description>

   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>2.0.2.RELEASE</version>
      <relativePath/> <!-- lookup parent from repository -->
   </parent>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
      <spring-cloud.version>Finchley.SR1</spring-cloud.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-config</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>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>

        <!--引入springcloud上下文依賴,使bootstrap配置文件生效-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-context</artifactId>
        </dependency>
      <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
      </dependency>
   </dependencies>

   <dependencyManagement>
      <dependencies>
         <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
         </dependency>
      </dependencies>
   </dependencyManagement>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>


</project>

 

引入springcloud上下文依賴,使bootstrap配置文件生效

<!--引入springcloud上下文依賴,使bootstrap配置文件生效-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-context</artifactId>
</dependency>

這裏說明一下爲何 要放在bootstrap裏面,由於項目啓動的時候是先加載bootstrap.properties

在client的bootstrap.properties中能夠添加本身的屬性配置,但若是有和server端相同的屬性配置會以server端的會準。

application.properties配置以下

#spring.profiles.active=dev

spring.application.name=config-client
server.port=18174


#開啓健康檢查
#eureka.client.healthcheck.enabled=true

info.app.name=@project.name@
info.app.description=@project.description@
info.app.version=@project.version@

啓動方法:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@EnableEurekaClient
@SpringBootApplication
public class ConfigClientApplication {

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

測試方法:

@RefreshScope
@RestController
public class MyController {

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


    @RequestMapping(value = "/name",method = RequestMethod.GET)
    public String hi(){
        return foo;
    }

    @RequestMapping(value = "/hi",method = RequestMethod.GET)
    public String his(){
        return "ok";
    }



}

    啓動後在日誌裏面能夠看到/actuator/health、/actuator/info、/actuator/refresh,如沒有·說明沒有配置成功。

2018-09-03 14:21:38.303  INFO 6000 --- [           main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/health],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
2018-09-03 14:21:38.304  INFO 6000 --- [           main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/info],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
2018-09-03 14:21:38.304  INFO 6000 --- [           main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/refresh],methods=[POST],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)


 看到如下日誌說明訪問到了config-server

2018-09-03 11:50:54.272  INFO 7492 --- [io-18174-exec-4] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at : http://172.21.122.120:18173/

 

注: @RefreshScope 開啓 SpringCloudConfig 客戶端的 refresh 刷新範圍,來獲取服務端的最新配置,@RefreshScope要加在聲明@Controller聲明的類上,不然refresh以後Conroller拿不到最新的值,會默認調用緩存。

操做步驟:

①首先在 https://github.com/ningcs/springCloud-config 修改配置文件config-client-dev.properties

我把ningcs修改成 name=ningcs123

②而後訪問 http://localhost:18174/actuator/refresh 會出現你修改的字段名 以及版本號

[
    "config.client.version",
    "name"
]

③而後調用 http://localhost:18174/name 若是不調用  http://localhost:18174/actuator/refresh則會顯示ningcs

 每次修改配置文件更新都須要手動刷新配置,這樣豈不是很麻煩,固然springcloud也解決了這個問題,

接下來我將引入springcloud-bus實現自動刷新。

新建config-bus-client項目(複製config-client便可)

在bootstarp.properites引入mq配置文件

#配置mq
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=ningcs
spring.rabbitmq.password=ningcs123456

pom添加mq jar包:

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

總bootstarp.properites配置文件以下:

#eureka配置
eureka.client.serviceUrl.defaultZone=http://localhost:18170/eureka/
#開啓配置服務發現
spring.cloud.config.discovery.enabled=true
#配置服務實例名稱
spring.cloud.config.discovery.service-id=config-server
# 指明配置服務中心的網址
spring.cloud.config.uri=http://localhost:18175
#配置文件所在分支
spring.cloud.config.label=master
#配置所使用文件類別 dev-開發,test測試,pro生產
spring.cloud.config.profile=dev
#spring.cloud.config.fail-fast:true
##自動刷新配置 默認 health,info
management.endpoints.web.exposure.include=refresh,health,info
##是否須要權限拉去,默認是true,若是不false就不容許你去拉取配置中心Server更新的內容
management.security.enabled=false

#配置mq
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=ningcs
spring.rabbitmq.password=ningcs123456

application.properties配置以下:

#spring.profiles.active=dev

spring.application.name=config-bus-client
server.port=18176


#開啓健康檢查
#eureka.client.healthcheck.enabled=true

info.app.name=@project.name@
info.app.description=@project.description@
info.app.version=@project.version@

①依次啓動eureka-server,config-server,config-bus-client ,在 https://github.com/ningcs/springCloud-config 修改配置文件config-bus-client-dev.properties

②手動刷新配置http://172.21.122.120:18175/actuator/refresh

③訪問 http://localhost:18176/name  若是顯示成功說明已配置完成。

④在 https://github.com/ningcs/springCloud-config 配置webhooks

進入項目 /setting-->webhooks -->add webhook

而後配置url,這樣你必須須要一個公網能夠訪問的地址便可,我這裏只是示例。

而後修改config-bus-client-dev.properties 自動刷新配置 。

webhooks理解:

Webhook是一個API概念,而且變得愈來愈流行。咱們能用事件描述的事物越多,webhook的做用範圍也就越大。Webhook做爲一個輕量的事件處理應用,正變得愈來愈有用。

準確的說webhoo是一種web回調或者http的push API,是向APP或者其餘應用提供實時信息的一種方式。Webhook在數據產生時當即發送數據,也就是你能實時收到數據。這一種不一樣於典型的API,須要用了實時性須要足夠快的輪詢。這不管是對生產仍是對消費者都是高效的,惟一的缺點是初始創建困難。

Webhook有時也被稱爲反向API,由於他提供了API規則,你須要設計要使用的API。Webhook將向你的應用發起http請求,典型的是post請求,應用程序由請求驅動。

 

注:寫此博客的時候查閱文獻,不少博主springboot2.0版本config-client都配置的

management.endpoints.web.exposure.include=bus-refresh

或者 config-server再加配置 management.endpoints.web.exposure.include=‘*’

我測試屢次,均訪問報404錯誤。

後來參考文檔: https://blog.csdn.net/alinyua/article/details/80009435 

就將配置改成 

management.endpoints.web.exposure.include=refresh,health,info

即訪問成功,若是有springboot2.0版本使用bus-refresh訪問成功的能夠留下評論探討一下。

項目源碼地址:

https://github.com/ningcs/stocks

相關文章
相關標籤/搜索