很多時候線上服務的配置需要進行修改,但是我們不想或者沒辦法重啓服務來讓配置生效,那麼這時候應該怎麼辦呢?
在Spring Cloud中,spring cloud config所提供的分佈式配置中心能完美的解決以上問題,spring cloud config將配置文件存放在配置服務內存中或者託管在遠程git倉庫中。然後通過一個配置中心來獲取配置信息,這樣,如果需要維護配置信息,則只需要在本地修改配置文件,然後保存到遠程git倉庫上即可,十分方便。同時爲了保證配置中心的穩定,也可以集羣部署。
主要在上一篇的內容上進行擴展.
PS.一下Spring Boot項目都爲2.X版本
- 新建配置文件
(1)配置文件的命名規則爲
{spring.application.name}-{type}.properties
。
比如我上一篇中的SpringCloudServiceI服務的註冊名(spring.application.name)爲myServiceI,則其的配置文件名爲myServiceI-{type}.properties
。
新建配置文件myServiceI-dev.properties
和myServiceI-prod.properties
myServiceI-dev.properties中內容爲name=devConfig
myServiceI-prod.properties中內容爲name=prodConfig
然後通過git客戶端上傳到git倉庫,我這裏是上傳到了碼雲(github因爲某長城的關係訪問速度…你懂的)
https://gitee.com/SecondMagic/config
- 配置中心
新建Spring Boot 項目 SpringCloudConfig
(1)pom.xml
添加如下依賴
<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>
(2)application.properties配置
#服務端口
server.port=8091
#服務名稱
spring.application.name=myConfigServer
#服務註冊中心
eureka.client.service-url.defautZone=http://serviceCenter:8761/eureka/
#服務的git倉庫地址
spring.cloud.config.server.git.uri=https://gitee.com/SecondMagic/config.git
#配置文件所在的目錄
spring.cloud.config.server.git.search-paths=/**
#配置文件所在的分支
spring.cloud.config.label=master
#git倉庫的用戶名
spring.cloud.config.username=password
#git倉庫的密碼
spring.cloud.config.password=13363784679SUL
#spring 2.X actuator
#http://ip:port/actuator/refresh
management.endpoints.web.exposure.include=refresh,health,info
這裏有一個大坑,現在大部分的教程都是基於Spring Boot 1.X版本的,但是對於spring cloud config的配置,1.X和2.X版本是有一些不同的。在1.X中是不用配置management.endpoints.web.exposure.include
,然後在手動更新配置時用的路徑爲http://服務項目ip:服務項目port/refresh
。但是在2.X中,是不存在/refresh該路徑的,需要我們自行配置management.endpoints.web.exposure.include=refresh,health,info
,然後訪問路徑爲http://服務項目ip:服務項目port/actuator/refresh
。這個坑了我好久= =。
(3)啓動文件添加@EnableConfigServer
package com.my.config;
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 SpringCloundConfigApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCloundConfigApplication.class, args);
}
}
整體結構如下
現在啓動上一篇中的服務註冊中心和這裏的配置中心
可以從註冊界面看到配置中心服務已經註冊。
然後可以通過http://localhost:8091/myServiceI/dev
或http://localhost:8091/myServiceI-dev.properties
或http://localhost:8091/master/myServiceI-dev.properties
來查看配置信息
{“name”:“myServiceI”,“profiles”:[“dev”],“label”:null,“version”:“91bd9f2f8989eb798c789988242b1a6fbbbb0fde”,“state”:null,“propertySources”:[{“name”:“https://gitee.com/SecondMagic/config.git/myServiceI-dev.properties",“source”:{“name”:"devConfig”}}]}
- 配置客戶端(使用配置中心配置的服務)
在上一篇的SpringCloudServiceI服務基礎上進行擴展
(1)首先在原pom.xml基礎上添加config和actuator的依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
#更新
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
(2)application.properties配置
在原有基礎上添加如下配置
#spring 2.X actuator
#http://ip:port/actuator/refresh
management.endpoints.web.exposure.include=refresh,health,info
(3)新建bootstrap.properties配置文件(和application.properties在同一文件夾下)
我這裏使用的是prod配置文件
#config
#開啓配置服務發現
spring.cloud.config.discovery.enabled=true
#配置服務實例名稱
spring.cloud.config.discovery.service-id=myConfigServer
#配置文件所在分支
spring.cloud.config.label=master
spring.cloud.config.profile=prod
#配置服務中心
spring.cloud.config.uri=http://localhost:8091/
至於這裏爲什麼需要新建一個配置文件而不是在application.properties中直接添加config配置,是因爲在項目啓動時bootstrap.properties配置文件會先於application.properties加載,詳細原因可以百度。
(4)修改服務接口,將上一篇中的/getInfo
接口修改下
@RefreshScope代表刷新配置,是actuator提供的
package com.my.serviceI.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RefreshScope
@RequestMapping(value="/Api")
public class ServiceApiController {
//獲取配置信息
@Value("${name}")
private String name;
@ResponseBody
@RequestMapping(value="/getInfo")
public String getInfo() {
return "123+"+name;
}
}
整體結構
啓動服務項目,可以在註冊界面中查看到服務項目信息。
然後訪問接口http://localhost:8762/myServiceI/Api/getInfo
看下配置文件,恩,確實是這個
然後修改下配置,改成
name=prodConfigII
修改完後上傳到碼雲上
再次訪問服務接口http://localhost:8762/myServiceI/Api/getInfo
嗯?好像沒有更新成功?
想要刷新配置還需要一步操作,用POST方式訪問 http://localhost:8762/myServiceI/actuator/refresh
,這樣就會將myServiceI服務的標有@RefreshScope的部分中的配置信息進行刷新了。
或者通過git工具執行
curl -X POST http://localhost:8762/myServiceI/actuator/refresh
然後再次訪問接口http://localhost:8762/myServiceI/Api/getInfo
OK,成功刷新了。
但是該方法如果有很多個服務的話,需要手動一個一個的刷新,當服務數量到一定量級時就不靠譜了,所以需要使用MQ+spring-could-bus 消息總線模式來批量更新配置信息。
還有一個附加的,就是在服務端在從配置中心獲取配置信息時,如果出現了網絡波動,導致項目啓動時無法獲取信息的話,可以使用如下配置來規避。
還是在SpringCloudServiceI項目上進行擴展
pom.xml在原有基礎上添加依賴
<!--添加 重試機制 的依賴
因網絡的抖動等原因導致在啓動時候訪問config-server沒有訪問成功從而報錯,
希望config-client能重試幾次,故重試機制
-->
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
application.properties在原有基礎上添加配置
#retry
#和重試機制相關的配置有如下四個:
# 配置重試次數,默認爲6
spring.cloud.config.retry.max-attempts=6
# 間隔乘數,默認1.1
spring.cloud.config.retry.multiplier=1.1
# 初始重試間隔時間,默認1000ms
spring.cloud.config.retry.initial-interval=1000
# 最大間隔時間,默認2000ms
spring.cloud.config.retry.max-interval=2000
bootstrap.properties在原有基礎上添加配置
#啓動失敗時能夠快速響應
#spring.cloud.config.fail-fast=true