版本
- spring-boot 2.0.6.RELEASE
- spring-cloud Finchley.SR2
目錄結構
eurka-server 服務注冊中心
pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.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.SR2</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-netflix-eureka-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>
application.yml
server:
port: 18080
spring:
application:
name: eurka-server
eureka:
instance:
hostname: localhost # 主機地址
client:
register-with-eureka: false # 注冊中心告訴自己不能向自己注冊自己警绩,默認為true
fetch-registry: false # 獲取注冊信息
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
server:
enable-self-preservation: false # 關閉自我保護
eviction-interval-timer-in-ms: 60000 # 清理時間間隔 服務器清理服務列表的定時器 單位 毫秒
注冊中心 啟動類 EurekaServerApplication
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer //表示是一個 eureka 服務
@SpringBootApplication
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
在自己的git上上傳一個配置文件(在統(tǒng)一配置中心config-server 配置git倉庫地址時需要使用這個作為遠程配置文件倉庫)
config-server 統(tǒng)一配置中心
pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.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.SR2</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-config-server</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>
<!--配置中心監(jiān)控-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-monitor</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</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>
application.yml
server:
port: 18082
spring:
application:
name: config-server
cloud:
config:
server:
git:
search-paths: /** #遠程倉庫的目錄跟匆,本例子配置文件在根目錄中
uri: https://github.com/wangqiang/MySpringCloudConfig.git # 配置自己的git倉庫地址
#username: '' # 訪問git倉庫的用戶名 如果Git倉庫為公開倉庫,可以不填寫用戶名和密碼,如果是私有倉庫需要填寫贡避,
#password: '' # 訪問git倉庫的用戶密碼
default-label: master # 配置倉庫的分支
#消息總線配置
bus:
enabled: true
trace:
enabled: true
refresh:
enabled: true #開啟總線消息更新功能
# rabbitmq 配置
rabbitmq:
host: 127.0.0.1
port: 5672
username: rabbit
password: 123456
virtual-host: /
eureka:
client:
service-url:
defaultZone: http://localhost:18080/eureka/ #注冊中心地址
registry-fetch-interval-seconds: 20 # 多久拉取服務注冊信息 表示從“發(fā)現(xiàn)”服務器獲取注冊表信息的頻率(以秒為單位)赡译。
instance:
# 60s未收到心跳湃密,剔除instance 要比心跳時間大 服務器端等待的時間蒋失,因為它收到了最后的心跳,然后才可以從它的視圖中刪除這個實例夫嗓,并且不允許流量進入這個實例迟螺。將這個值設置得太長可能意味著,即使實例不存在舍咖,流量也可以被路由到實例矩父。將這個值設置得太小可能意味著,由于臨時網(wǎng)絡故障排霉,該實例可能會被排除在流量之外浙垫。這個值的設置至少要高于leaseRenewalIntervalInSeconds中指定的值。默認90s
lease-expiration-duration-in-seconds: 60
# 心跳時間 即每15秒發(fā)送一次心跳 表明客戶端需要將心跳發(fā)送到服務器端郑诺,以表明它還活著夹姥。如果心跳停止的時間超過了服務器設置的等待時間,那么服務器端將會從它的服務列表中刪除該實例辙诞,從而將流量排除在該實例之外辙售。默認30s
lease-renewal-interval-in-seconds: 15
prefer-ip-address: true
ip-address: 127.0.0.1
hostname: localhost
instance-id: ${spring.cloud.client.ip-address}:${server.port} #eureka client向eureka server注冊使用真實ip設置 默認為本機機器名
# 屏蔽安全驗證
management:
endpoints:
web:
exposure:
include: '*' # 可以選擇【"health","mappings","bus-refresh"】三種選項暴露那些端點
統(tǒng)一配置中心 啟動類 ConfigServerApplication
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;
@EnableConfigServer //標記為 Config Server
@EnableEurekaClient //標記為eureka client
@SpringBootApplication
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
auth-server 業(yè)務的微服務
pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.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.SR2</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<exclusions>
<!-- 排除默認日志插件 -->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</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-config</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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<!-- 排除默認日志插件 -->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.12</version>
</dependency>
<!-- druid 連接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.11</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.49</version>
</dependency>
<!-- 使用log4j2 日志 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<!-- Log4j2 異步支持 -->
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<version>3.4.2</version>
</dependency>
<!-- sql 日志待參數(shù)輸出 -->
<dependency>
<groupId>com.googlecode.log4jdbc</groupId>
<artifactId>log4jdbc</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<!-- 排除默認日志插件 -->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</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>
<dependencies>
<!-- spring熱部署 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
<version>1.2.8.RELEASE</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
bootstrap.yml
配置中心的客戶端要使用bootstrap.yml
bootstrap.yml優(yōu)先于 application.yml 加載 即 bootstrap.yml加載完后才加載 application.yml
server:
tomcat:
uri-encoding: UTF-8
port: 18088
spring:
application:
name: auth-server # 對應配置中心配置文件中的{application}部分 名稱需要與子服務名稱以及讀取的配置文件庫中文件名稱一致
cloud:
config:
discovery:
enabled: true # 配置中心的servieId,即服務名
service-id: config-server # 配置中心的服務名
label: master # 指明遠程倉庫的分支
profile: dev # 對應配置中心配置文件中的{profile}部分 本例子中讀取的配置文件為 auth-server-dev.yml dev開發(fā)環(huán)境配置文件 test測試環(huán)境 pro正式環(huán)境
name: auth-server # 對應配置中心配置文件中的{application}部分 多個用,隔開
fail-fast: true
#消息總線配置
bus:
enabled: true
trace:
enabled: true
refresh:
enabled: true #開啟總線消息更新功能
eureka:
client:
service-url:
defaultZone: http://localhost:18080/eureka/ #注冊中心地址
registry-fetch-interval-seconds: 20 # 多久拉取服務注冊信息 表示從“發(fā)現(xiàn)”服務器獲取注冊表信息的頻率(以秒為單位)飞涂。
instance:
# 60s未收到心跳旦部,剔除instance 要比心跳時間大 服務器端等待的時間祈搜,因為它收到了最后的心跳,然后才可以從它的視圖中刪除這個實例士八,并且不允許流量進入這個實例容燕。將這個值設置得太長可能意味著,即使實例不存在婚度,流量也可以被路由到實例蘸秘。將這個值設置得太小可能意味著,由于臨時網(wǎng)絡故障蝗茁,該實例可能會被排除在流量之外醋虏。這個值的設置至少要高于leaseRenewalIntervalInSeconds中指定的值。默認90s
lease-expiration-duration-in-seconds: 60
# 心跳時間 即每15秒發(fā)送一次心跳 表明客戶端需要將心跳發(fā)送到服務器端哮翘,以表明它還活著颈嚼。如果心跳停止的時間超過了服務器設置的等待時間,那么服務器端將會從它的服務列表中刪除該實例饭寺,從而將流量排除在該實例之外阻课。默認30s
lease-renewal-interval-in-seconds: 15
prefer-ip-address: true
ip-address: 127.0.0.1
hostname: localhost
instance-id: ${spring.cloud.client.ip-address}:${server.port} #eureka client向eureka server注冊使用真實ip設置 默認為本機機器名
# 屏蔽安全驗證
management:
endpoints:
web:
exposure:
include: '*' # 可以選擇【"health","mappings","bus-refresh"】三種選項暴露那些端點
業(yè)務微服務端 啟動類 AuthServerApplication
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@EnableEurekaClient
@SpringBootApplication
public class AuthServerApplication {
public static void main(String[] args) {
SpringApplication.run(AuthServerApplication.class, args);
}
}
業(yè)務微服務端 測試類
在需要更新的配置類上加@RefreshScope注解,@RefreshScope必須加艰匙,否則客戶端會收到服務端的更新消息柑肴,但是更新不了,因為不知道更新哪里的旬薯。
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RefreshScope // 需要更新的配置類上加@RefreshScope注解,@RefreshScope必須加适秩,否則客戶端會收到服務端的更新消息绊序,但是更新不了,因為不知道更新哪里的
public class Test {
@Value("${name}")
private String name;
@GetMapping("test")
public String test() {
return name;
}
}
依次啟動 eurka-server -> config-server -> auth-server
訪問遠程git上的配置文件 http://127.0.0.1:18082/auth-server/dev
18082: 是統(tǒng)一配置中心的端口
/auth-server/dev 對應遠程配置文件的auth-server-dev.yml
/{name}-{profiles}.yml
/{label}/{name}-{profiles}.yml
name : 文件名秽荞,一般以服務名來命名
profiles : 一般作為環(huán)境標識
lable : 分支(branch)骤公,指定訪問某分支下的配置文件
{
"name": "auth-server",
"profiles": [
"dev"
],
"label": null,
"version": "69b2e80b7f8dbd6f84f24152a389bf091d5333dc",
"state": null,
"propertySources": [
{
"name": "https://github.com/wangqiang/MySpringCloudConfig.git/auth-server-dev.yml",
"source": {
"name": "之歌劉",
"spring.rabbitmq.host": "127.0.0.1",
"spring.rabbitmq.port": 5672,
"spring.rabbitmq.username": "rabbit",
"spring.rabbitmq.password": 123456,
"spring.rabbitmq.virtual-host": "/"
}
}
]
}
業(yè)務微服務端 獲取遠程配置文件中的屬性值
業(yè)務微服端的測試接口:http://127.0.0.1:18088/test
遠程配置文件更新后,客戶端自動更新
修改配置文件并提交到git上
name: 啊哈哈哈哈
- 首先發(fā)布一個post請求 http://localhost:18088/actuator/bus-refresh 手動刷新配置
或者請求 http://localhost::18082/actuator/refresh
18088 是配置客戶端應用 config-client
18082 是配置服務中心 config-server
image.png
image.png
- 再次訪問測試接口 http://127.0.0.1:18088/test
image.png
我們發(fā)現(xiàn)再不重啟服務的情況下就能獲取到修改的屬性值
只要開啟 Spring Cloud Bus 后扬跋,不管是對 config-server 還是 config-client 執(zhí)行/actuator/bus-refresh都是可以更新配置的阶捆,
如果有多個客戶端,多個客戶端都會接收到刷新配置的消息钦听,并刷新配置洒试。
局部刷新配置(只刷新某些客戶端)
某些場景下(例如灰度發(fā)布),我們可能只想刷新部分微服務的配置朴上,此時可通過/actuator/bus-refresh/{destination}端點的 destination 參數(shù)來定位要刷新的應用程序垒棋。例如:/actuator/bus-refresh/customers:8000,這樣消息總線上的微服務實例就會根據(jù) destination 參數(shù)的值來判斷是否需要要刷新痪宰。其中叼架,customers:8000指的是各個微服務的 ApplicationContext ID畔裕。destination 參數(shù)也可以用來定位特定的微服務。例如:/actuator/bus-refresh/customers:**乖订,這樣就可以觸發(fā) customers 微服務所有實例的配置刷新扮饶。
集成WebHooks實現(xiàn)動態(tài)更新
遠程配置文件修改后,不需要手動調(diào)用http://localhost:18088/actuator/bus-refresh 即可刷新配置
-
在遠程配置文件的MySpringCloudConfig.git倉庫中添加密鑰
image.png
image.png -
在遠程配置文件git倉庫中找到Webhooks
image.png -
點擊Add webhook乍构,添加一個webhook
image.png
Payload URL: push 代碼后自動運行的腳本 http://localhost:18082/actuator/bus-refresh(配置能夠被git訪問到的請求地址甜无,根據(jù)git內(nèi)外網(wǎng)情況自行配置)
Content type :我們選擇application/json
Secret: 通訊密鑰 用來認證身份
選擇Just the push event.,因為我們只需要push的時候進行回調(diào)蜡吧,然后添加即可
每當我們更新遠程配置文件后毫蚓,push到git后,就會觸發(fā)Payload URL(配置的是訪問刷新配置的地址)