帶你入門SpringCloud 之 經過SpringCloud Bus 自動更新配置

前言

《帶你入門SpringCloud統一配置 | SpringCloud Config》中經過 SpringCloud Config 完成了統一配置基礎環境搭建,可是並無實現配置修改自動更新的操做(GitHub 或Gitee 修改配置後,須要重啓配置服務才能更新配置)。html

本文是《帶你入門SpringCloud統一配置 | SpringCloud Config》的續篇,經過 SpringCloud Bus 完成配置修改自動更新的操做介紹。java

閱讀本文前須要你先移步《帶你入門SpringCloud統一配置 | SpringCloud Config》由於本文是在其基礎上進行講解的。git

另外須要你熟悉 SpringBoot 項目的基本使用便可,還有一點須要注意的是在操做過程當中儘可能和我本地環境一致,由於環境不一致可能會帶來一些問題。我本地環境以下:github

  • SpringBoot Version: 2.1.0.RELEASE
  • SpringCloud Version: Greenwich.RELEASE
  • Apache Maven Version: 3.6.0
  • Java Version: 1.8.0_144
  • IDEA:Spring Tools Suite (STS)

接下來就開始 SpringCloud Bus 環境搭建操做介紹!web

SpringCloud Bus 環境搭建

第一步:安裝並啓用 RabbitMQ,這裏就不作詳細介紹了。能夠查看以前的總結:Windows 環境安裝 RabbitMQspring

若是你的 RabbitMQ和 Config Server 端不在一臺機器上,或者端口、用戶名、密碼不是使用的默認配置,那麼你須要進行以下配置在 Config Server 端 application.properties 中

spring.rabbitmq.host=rabbitmq 服務IP地址
spring.rabbitmq.port=rabbitmq 服務端口號
spring.rabbitmq.username=rabbitmq 服務用戶名
spring.rabbitmq.password=rabbitmq 服務密碼app

第二步:在 Config Server 端端和客戶端都引入 spring-cloud-starter-bus-amqp 依賴。具體代碼以下:dom

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

第三步:在Config Server 端的 application.properties 中須要添加以下配置,目的是把刷新配置接口暴露出來,具體配置以下:ide

management.endpoints.web.exposure.include=  *

第四步:Config Client 端引入openfeign starter 依賴,具體代碼以下:post

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

第五步:驗證 Config Server 端和 Config Client 端是否在 RabbitMQ 註冊隊列和是否註冊到 Eureka Server 端上。以下圖所示:

須要先啓動 Eureka Server 服務端,而後在依次啓動 Config Server端和Config Client端。

在這裏插入圖片描述
在這裏插入圖片描述
第六步:Config Client 端上訪問配置的 Controller 聲明刷新配置做用域@RefreshScope。具體代碼以下:

@RestController
@RefreshScope
public class EvnController {
    @Value("${env}")
    private String env;
    
    @RequestMapping("/env")
    public String evn() {
        return this.env;
    }
}
不添加 @RefreshScope註解,配置更新後不會生效。
若是是自定義前綴配置須要在@ConfigurationProperties下添加 @RefreshScope便可,

最七步在 Gitee 上配置 WebHooks,具體操做方式以下圖所示:

進入Gitee 點擊管理,而後點擊 WebHooks。
在這裏插入圖片描述
在這裏插入圖片描述
點擊添加按鈕添加新的 WebHooks 設置。
在這裏插入圖片描述
輸入本地映射外網訪問域名+/actuator/bus-refresh,本身測試可使用 NATAPP 進行內網穿穿透配置。具體配置請查看 https://natapp.cn/
在這裏插入圖片描述

測試

手動訪問更新連接進行測試

修改配置在碼雲遠程倉庫上,而後使用 PostMan 訪問:http://localhost:8080/actuator/bus-refresh ,以下圖所示:

這裏演示直接是在碼雲上操做,至關於執行 git push 操做。

在這裏插入圖片描述
在這裏插入圖片描述
而後在查看商品服務(Config Client端)配置是否生效。以下圖所示自動更新成功!
在這裏插入圖片描述
WebHooks 測試

進入 WebHooks 設置,而後點擊測試。會報以下圖所示錯誤:
在這裏插入圖片描述

解決方案:

參考來CSDN 做者 tinysakurac 解決方案。
文章:《解決使用spring cloud config bus使用webhook自動刷新出現的400問題》 (https://blog.csdn.net/m0_3755...

問題產生緣由:GitHub在進行 POST 請求的同時默認會在 Body 加上這麼一串載荷(payload),而 /actuator/bus-refresh 接口沒有進行接受這些信息處理,因此就報錯了。

解決問題思路:經過攔截器攔截 bus-refresh請求,而後在 HttpServletRequestMapper 包裝類將 Request中 Body 內容置空。具體代碼以下:

攔截 bus-refresh請求Filter 類。

public class BusRefreshFilter implements Filter{

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest)request;
        String url = new String(httpServletRequest.getRequestURI());
        //只過濾/actuator/bus-refresh請求
        if (!url.endsWith("/bus-refresh")) {
            chain.doFilter(request, response);
            return;
        }
        //使用HttpServletRequest包裝原始請求達到修改post請求中body內容的目的
        CustometRequestWrapper requestWrapper = new CustometRequestWrapper(httpServletRequest);
        chain.doFilter(requestWrapper, response);
    }
}

自定義 HttpServletRequestWrapper 類

public class CustometRequestWrapper extends HttpServletRequestWrapper{

    public CustometRequestWrapper(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();
            }

        
        };
    }
}

將攔截 bus-refresh請求Filter 添加到 Spring 上下文中配置類。

@Configuration
public class FilterConfig {
     @Bean
        public FilterRegistrationBean<BusRefreshFilter> filterRegistration() {
            FilterRegistrationBean<BusRefreshFilter> registration = new FilterRegistrationBean<BusRefreshFilter>();
            registration.setFilter(new BusRefreshFilter());
            List<String> urlList = new ArrayList<String>();
            urlList.add("/*");
            registration.setUrlPatterns(urlList);
            registration.setName("BusRefreshFilter");
            registration.setOrder(1);
            return registration;
        }
}

在這裏插入圖片描述

而後修改Gitee 上的配置信息後就能夠自動更新了,這裏就不在進行演示操做來。

還有一種方式是經過訪問 Config Server端域名/monitor 來取代 Config Server端域名//actuator/bus-refresh。本方式我的嘗試沒有成功!具體配置官網介紹以下:

Many source code repository providers (such as Github, Gitlab, Gitea, Gitee, Gogs, or Bitbucket) notify you of changes in a repository through a webhook. You can configure the webhook through the provider’s user interface as a URL and a set of events in which you are interested. For instance, Github uses a POST to the webhook with a JSON body containing a list of commits and a header (X-Github-Event) set to push. If you add a dependency on the spring-cloud-config-monitor library and activate the Spring Cloud Bus in your Config Server, then a /monitor endpoint is enabled.

在Config Server 添加 spring-cloud-config-monitor 依賴

<dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-config-monitor</artifactId>
</dependency>

而後在Config Client 添加以下配置:
參考:https://github.com/spring-cloud/spring-cloud-bus/issues/124

spring.cloud.bus.id=${vcap.application.name:${spring.application.name:application}}:${vcap.application.instance_index:${spring.profiles.active:${local.server.port:${server.port:0}}}}:${vcap.application.instance_id:${random.value}}

小結

當將遠程倉庫配置文件修改後,經過GitHub 或者 Gitee 的 WebHooks 配置自動訪問接口bus-refresh 來通知Config Server 端。

Config Server 端收到請求後將配置 clone 下來,而後經過消息隊列(默認是RabbitMQ)將修改後的配置發送給 Config Client 端。Config Client 端收到消息後從新從Config Server 端獲取最新的配置信息。

而WebHooks 配置請求接口 bus-refresh 和消息隊列發送配置給 Config Client 端都是 SpringCloud Bus 幫助咱們完成的。

代碼示例

若是你按照上述方式搭建並未成功,能夠參考我在GitHub 項目 spring-cloud-get-started 倉庫中模塊名爲:

spring-cloud-config-eureka-service
spring-cloud-config-server
spring-cloud-config-product-service
進行對比查看是否配置有誤。

spring-cloud-get-started 項目地址:https://github.com/zhuoqianmingyue/spring-cloud-get-started

參考文獻

http://www.javashuo.com/article/p-cztletnu-eb.html By tinysakurac

https://cloud.spring.io/spring-cloud-config/reference/html/

相關文章
相關標籤/搜索