SpringCloud系列教程 | 第七篇:Spring Cloud Config 配置中心高可用和refresh Springboot: 2.1.6.RELEASE SpringCloud: Greenwich.SR1 如無特殊說明,本系列教程全採用以上版本 1. 引言 上一篇我們聊了Spring ...
SpringCloud系列教程 | 第七篇:Spring Cloud Config 配置中心高可用和refresh
Springboot: 2.1.6.RELEASE
SpringCloud: Greenwich.SR1
如無特殊說明,本系列教程全採用以上版本
1. 引言
上一篇我們聊了Spring Cloud Config 配置中心,並且和Github做了集成,我們的Server端是單機版的,任何單機版的服務都只能使用與測試環境或者自己做Demo測試,生產環境嚴禁使用單機服務,配置中心在整個微服務體系中都是及其重要的一個節點,尤其是在DevOps中自動擴容,如果配置中心宕機,那麼所有的自動擴容都會失敗。
所以這一篇我們聊聊配置中心的高可用,說到高可用,在springcloud體系中,是有註冊中心的,那麼,我們的配置中心也是一個服務,可不可以使用Eureka做服務的註冊與發現呢?
答案是肯定的。
2. Serve端
我們將上一篇的Serve端Copy到新的目錄中,增加Eureka-client的依賴,使得Config-Serve可以註冊到Eureka上。
2.1 pom.xml
<?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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.springcloud</groupId>
<artifactId>config-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>config-server</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<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>
</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>
2.2 配置文件application.yml
server:
port: 8080
spring:
application:
name: spring-cloud-config-server
cloud:
config:
server:
git:
uri: https://github.com/meteor1993/SpringCloudLearning
search-paths: chapter6/springcloud-config
username: username
password: password
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
增加eureka的地址配置
2.3 啟動類
啟動類增加@EnableEurekaClient激活對註冊中心的支持
package com.springcloud.configserver;
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;
@SpringBootApplication
@EnableConfigServer
@EnableEurekaClient
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
這樣Server註冊端我們就修改完成了。先啟動Eureka,再啟動Serve,在瀏覽器中訪問http://localhost:8761/,就可以看到我們的Serve端已經註冊到註冊中心了,接下來我們開始改造Client端。
3. Client端
首先還是將上一篇的Client端Copy過來,和Server端一樣,增加Eureka-client的依賴,使得Config-Client可以從註冊中心上發現服務。
3.1 pom.xml
<?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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.springcloud</groupId>
<artifactId>config-client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>config-client</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<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-test</artifactId>
<scope>test</scope>
</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>
3.2 bootstrap.properties
這裡我們需要先清空application.yml,所有的配置全都轉移到bootstrap.properties中。
spring.application.name=spring-cloud-config-client
server.port=8081
spring.cloud.config.name=springcloud-config
spring.cloud.config.profile=dev
spring.cloud.config.label=master
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.serviceId=spring-cloud-config-server
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
主要是去掉了spring.cloud.config.uri直接指向server端地址的配置,增加了最後的三個配置:
- spring.cloud.config.discovery.enabled :開啟Config服務發現支持
- spring.cloud.config.discovery.serviceId :指定server端的name,也就是server端spring.application.name的值
- eureka.client.serviceUrl.defaultZone :指向註冊中心的地址
3.3 啟動類
啟動類增加@EnableEurekaClient激活對註冊中心的支持
package com.springcloud.configclient;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class ConfigClientApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigClientApplication.class, args);
}
}
4. 高可用
現在我們來模擬生產環境。
首先,順次啟動Eureka,Server,Client。
在idea啟動兩個config-serve,我們修改idea配置啟動配置,換到8000埠啟動config-serve。
先訪問http://localhost:8761/,可以看到兩個config-serve都正常註冊到註冊中心。
如上圖就可發現會有兩個server端同時提供配置中心的服務,防止某一臺down掉之後影響整個系統的使用。
我們訪問client端的鏈接:http://localhost:8081/hello, 可以看到頁面正常顯示:hello dev update1,刷新幾次,顯示都沒問題,現在我們隨機停掉一個埠的config-serve服務,再去刷新頁面,可以發現,頁面依然可以正常顯示:hello dev update1。
至此,我們高可用的目的已經達到,但是,不知道各位有沒有映像,我們上一篇留了一個坑,服務啟動後,我們修改遠端github上的配置時,這個配置並不會實時被客戶端端所獲取到,下麵我們來聊一聊有關Spring Cloud Config 刷新的問題。
5. refresh
我們的客戶端並不能主動去感知Git或者Svn的配置變化,從而主動獲取最新的配置。那麼,客戶端如何去主動獲取新的配置信息呢?springcloud已經給我們提供瞭解決方案,每個客戶端通過POST方法觸發各自的/refresh。
修改config-client項目已到達可以refresh的功能。
5.1 添加依賴pom.xml
在我們原有的config-client項目的pom.xml的基礎增加新的依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
增加了spring-boot-starter-actuator包,spring-boot-starter-actuator是一套監控的功能,可以監控程式在運行時狀態,其中就包括/refresh的功能。
5.2 開啟更新機制
需要給載入變數的類上面載入@RefreshScope,在客戶端執行/refresh的時候就會更新此類下麵的變數值。
package com.springcloud.configclient.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author: shiyao.wei
* @Date: 2019/7/4 16:19
* @Version: 1.0
* @Desc:
*/
@RestController
@RefreshScope // 使用該註解的類,會在接到SpringCloud配置中心配置刷新的時候,自動將新的配置更新到該類對應的欄位中。
public class HelloController {
@Value("${springcloud.hello}")
private String hello;
@RequestMapping("/hello")
public String from() {
return this.hello;
}
}
5.3 配置文件bootstrap.properties
spring.application.name=spring-cloud-config-client
server.port=8081
spring.cloud.config.name=springcloud-config
spring.cloud.config.profile=dev
spring.cloud.config.label=master
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.serviceId=spring-cloud-config-server
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
management.security.enabled=false
management.endpoints.web.exposure.include=*
- management.security.enabled: springboot 1.5.X 以上預設開通了安全認證,所以需要添加這個配置
- management.endpoints.web.exposure.include: springboot 2.x 預設只開啟了info、health的訪問,*代表開啟所有訪問
5.4 測試
我們先訪問客戶端的測試連接:http://localhost:8081/hello, 這時,頁面的顯示是:hello dev update1,我們修改github上的信息,修改為:hello dev update,現在訪問http://localhost:8081/hello,得到的信息還是:hello dev update1,現在我們刷新一下客戶端,通過cmd命令行執行:curl -X POST http://localhost:8081/actuator/refresh,可以看到命令行上有顯示:["springcloud.hello","config.client.version"],意味著springcloud.hello這個配置已經刷新,這時,我們再去刷新一下頁面,可以看到,頁面上得到的信息已經變為了:hello dev update,這時我們refresh成功。
每次手動刷新客戶端還是很麻煩,有沒有什麼辦法只要提交代碼就自動調用客戶端來更新呢,github的webhook是一個好的辦法。
6. webhook
WebHook是當某個事件發生時,通過發送http post請求的方式來通知信息接收方。Webhook來監測你在Github.com上的各種事件,最常見的莫過於push事件。如果你設置了一個監測push事件的Webhook,那麼每當你的這個項目有了任何提交,這個Webhook都會被觸發,這時Github就會發送一個HTTP POST請求到你配置好的地址。
如此一來,你就可以通過這種方式去自動完成一些重覆性工作,比如,你可以用Webhook來自動觸發一些持續集成(CI)工具的運作,比如Travis CI;又或者是通過 Webhook 去部署你的線上伺服器。下圖就是github上面的webhook配置。
- Payload URL: 觸發後回調的URL
- Content type: 數據格式,兩種一般使用json
- Secret: 用作給POST的body加密的字元串。採用HMAC演算法
- events: 觸發的事件列表
events事件類型 | 描述 |
---|---|
push | 倉庫有push時觸發。預設事件 |
create | 當有分支或標簽被創建時觸發 |
delete | 當有分支或標簽被刪除時觸發 |
這樣我們就可以利用hook的機制去觸發客戶端的更新,但是當客戶端越來越多的時候hook支持的已經不夠優雅,另外每次增加客戶端都需要改動hook也是不現實的。其實Spring Cloud給了我們更好解決方案,我們在下一篇接著聊。