利用Git服務的webhook通知功能,在每次更新配置以後,Git服務器會用POST方式調用配置中心的/actuator/bus-refresh接口,配置中心的總線服務會將此事件廣播給加入總線的全部客戶端,客戶端收到事件後會重新讀取配置中心的內容。java
配置中心的服務端(spring-cloud-config-server)和客戶端(spring-cloud-config-client)都加入Spring Cloud Bus引用包:git
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bus-amqp</artifactId> </dependency>
docker pull rabbitmq:3-management docker run -d --hostname my-rabbit --name rabbit -p 5672:5672 -p 15672:15672 rabbitmq:3-management
能夠訪問127.0.0.1:15672/登陸rabbitmq管理監控後臺,用戶名密碼都是guest/guest。github
配置中心的服務端(spring-cloud-config-server)和客戶端(spring-cloud-config-client)都須要修改配置文件的內容:
spring-cloud-config-server項目的application.properties增長:web
# 開啓消息跟蹤 spring.cloud.bus.trace.enabled=true spring.rabbitmq.host=127.0.0.1 spring.rabbitmq.port=5672 spring.rabbitmq.username=guest spring.rabbitmq.password=guest #顯示的暴露接入點 management.endpoints.web.exposure.include=*
spring-cloud-config-client項目的application.properties增長:spring
# 開啓消息跟蹤 spring.cloud.bus.trace.enabled=true spring.rabbitmq.host=127.0.0.1 spring.rabbitmq.port=5672 spring.rabbitmq.username=guest spring.rabbitmq.password=guest #顯示的暴露接入點 management.endpoints.web.exposure.include=*
spring-cloud-config-client項目的bootstrap.properties增長(不然會報錯:A component required a bean named 'configServerRetryInterceptor' that could):docker
spring.cloud.config.fail-fast=true
192.168.0.21:9004/actuator/bus-refresh是我一個配置中心的地址,若是有多個配置中心能夠寫多個webhook,在頁面上測試中若是返回204就說明成功了。shell
Git在進行webhood post請求的同時默認會在body加上這麼一串載荷(payload),Spring Boot 沒法並行化,因此在配置中心服務端(spring-cloud-config-server)新建下面兩個類:
此代碼參考了:spring_cloud config 配置中心及利用Github實現自動化熱加載配置bootstrap
import javax.servlet.ReadListener; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import java.io.ByteArrayInputStream; import java.io.IOException; //清空請求中的Body public class EmptyRequestWrapper extends HttpServletRequestWrapper{ public EmptyRequestWrapper(HttpServletRequest request) { super(request); } @Override public ServletInputStream getInputStream() throws IOException { byte[] bytes = new byte[0]; ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes); return new ServletInputStream() { @Override public boolean isFinished() { return byteArrayInputStream.read() == -1 ? true:false; } @Override public boolean isReady() { return false; } @Override public void setReadListener(ReadListener readListener) { } @Override public int read() throws IOException { return byteArrayInputStream.read(); } }; } }
import org.springframework.core.annotation.Order; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import java.io.IOException; @WebFilter(filterName = "bodyFilter", urlPatterns = "/*") @Order(1) //Git在進行webhood post請求的同時默認會在body加上這麼一串載荷(payload),Spring Boot 沒法並行化。 public class BusRefreshFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest httpServletRequest = (HttpServletRequest)servletRequest; String url = new String(httpServletRequest.getRequestURI()); //只過濾/actuator/bus-refresh請求 if (!url.endsWith("/bus-refresh")) { filterChain.doFilter(servletRequest, servletResponse); return; } //使用HttpServletRequest包裝原始請求達到修改post請求中body內容的目的 EmptyRequestWrapper requestWrapper = new EmptyRequestWrapper(httpServletRequest); filterChain.doFilter(requestWrapper, servletResponse); } @Override public void destroy() { } }
最後在啓動類上添加@ServletComponentScan註解服務器
@SpringBootApplication //啓動配置中心 @EnableConfigServer //啓動服務發現 @EnableDiscoveryClient @ServletComponentScan public class SpringCloudConfigServerApplication { public static void main(String[] args) { SpringApplication.run(SpringCloudConfigServerApplication.class, args); } }
訪問客戶端程序127.0.0.1:9006/ConfigTest,獲得當前結果Test-8,訪問配置中心也是Test-8:
咱們更新Git參考將配置內容改成Test-9:
查看配置中心127.0.0.1:9004/ConfigDepot/Test,內容已經改成Test-9,再刷新客戶端程序127.0.0.1:9006/ConfigTest,這時配置內容已經成功改爲了Test-9,總線事件通知客戶端刷新配置成功。
從配置中心服務端和客戶端的日誌也可看出刷新配置信息的過程:
app
Github倉庫:https://github.com/sunweisheng/spring-cloud-example