成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

搞懂Spring Cloud Config配置信息自動更新原理

開發 前端
Spring Cloud Bus 是 Spring Cloud 中用于實現消息總線的專用組件,它集成了 RabbitMQ、Kafka 等主流消息中間件。

我們知道 Spring Cloud Config 是 Spring Cloud 提供的配置中心實現工具,我們可以通過它把配置信息存放在 Git 等第三方配置倉庫中。每當 Spring Cloud Config 客戶端啟動時,就會發送 HTTP 請求到服務器端獲取配置信息,這點比較好理解。但事實上,在 Git 中更改了配置信息之后,客戶端并不會主動再次請求最新配置,而是使用緩存到本地的原有配置信息。如圖 1。

圖 1 配置信息自動更新問題圖 1 配置信息自動更新問題

那么問題就來了,在這種情況下, Spring Cloud Config 是如何實時獲取到更改后的配置呢?這就是今天我們要討論的內容。通過理解 Spring Cloud Config 配置信息自動更新的執行過程,有助于我們深入把握框架的底層原理。

在對底層原理進行詳細展開之前,我們先來給出 Spring Cloud Config 應對這一問題的具體做法。事實上,Spring Cloud Config 能夠做到配置信息的自動更新,是依賴于 Spring Cloud 中的另一個組件,即 Spring Cloud Bus。

Spring Cloud Bus 是 Spring Cloud 中用于實現消息總線的專用組件,它集成了 RabbitMQ、Kafka 等主流消息中間件。當我們在 Spring Cloud Config 服務器端代碼工程的類路徑中添加 Spring Cloud Bus 的引用并啟動應用程序之后,Spring Boot Actuator 就為我們提供了/actuator/bus-refresh 端點, 通過訪問該端點就可以達到對客戶端所有服務實例的配置信息進行自動更新的效果。在這種方案中,服務端會主動通知所有客戶端進行配置信息的更新,這樣我們就無需關注各個客戶端,而只對服務端進行操作即可。

是不是聽起來有點神奇?整個實現過程我們至少要搞清楚三大問題,如圖 2 所示。

圖 2 實現配置信息自動更新的三個問題圖 2 實現配置信息自動更新的三個問題

針對這三個問題,接下來我們將結合源碼逐一展開討論。

問題一:如何自動調用服務器端所暴露的/actuator/bus-refresh 端點?

在現代軟件開發過程中,開放式平臺是一種常見的軟件服務形態。我們可以把 Spring Cloud Config Server 所提供的 HTTP 端點視為一種開放式的接口,以供 Git 等第三方工具進行訪問和集成。

基于這種思想,我們可以把服務器端/actuator/bus-refresh 端點對外進行暴露,然后第三方工具通過這個暴露的端點進行集成。例如,在 Github 中就設計了一種 Webhook 機制,并提供了用戶界面供我們配置所需要集成的端點以及對應的操作,操作方法如圖 3 所示。

圖 3 Github 的 Webhook 配置界面(來自 Github 官網)圖 3 Github 的 Webhook 配置界面(來自 Github 官網)

我們可以在上圖的 Payload URL 中設置/actuator/bus-refresh 端點地址。所謂的 Webhook,實際上就是一種回調。通過 Webhook,當我們提交代碼時,Github 就會自動調用所配置的 HTTP 端點。也就是說,我們可以根據配置項信息的更新情況自動實現對/actuator/bus-refresh 端點的訪問。基于 Github 的配置倉庫實現方案,我們可以得到如下圖所示的系統結構圖。

圖 4 Github Webhook 機制執行效果圖圖 4 Github Webhook 機制執行效果圖

現在,配置信息一旦有更新,Spring Cloud Config Server 就能從 Github 中獲取最新的配置信息了。

問題二:客戶端如何得知服務器端的配置信息已經更新?

接下來我們關注第二個問題,即客戶端如何得知服務器端的配置信息已經更新?

我們首先需要明確,調用了/actuator/bus-refresh 端點之后,系統內部會發生了什么。這里我們快速瀏覽 Spring Cloud Bus 中的代碼工程,發現存在一個 RefreshBusEndpoint 端點類,如下所示:

@Endpoint(id = "bus-refresh")
public class RefreshBusEndpoint extends AbstractBusEndpoint {
    @WriteOperation
    public void busRefreshWithDestination(@Selector String destination) {
        //發布 RefreshRemoteApplicationEvent 事件
        publish(new RefreshRemoteApplicationEvent(this, getInstanceId(), destination));
    }
    @WriteOperation
    public void busRefresh() {
        //發布 RefreshRemoteApplicationEvent 事件
        publish(new RefreshRemoteApplicationEvent(this, getInstanceId(), null));
    }
}

顯然,RefreshBusEndpoint 類對應于我們前面訪問的/bus-refresh 端點。可以看到,Spring Cloud Bus 在這里做的事情僅僅只是發布了一個新的 RefreshRemoteApplicationEvent 事件。

既然發送了事件,我們就需要尋找該事件的監聽者。我們在 Spring Cloud Bus 中找到了 RefreshRemoteApplicationEvent 事件的監聽器 RefreshListener,如下所示:

public class RefreshListener implements ApplicationListener<RefreshRemoteApplicationEvent> {
    …
    @Override
    public void onApplicationEvent(RefreshRemoteApplicationEvent event) {
        //執行配置屬性的刷新操作
        Set<String> keys = contextRefresher.refresh();
    }
}

從類的定義中不難看出該監聽器就是用來處理 RefreshRemoteApplicationEvent 事件。可以看到,在它的 onApplicationEvent 方法中同樣也是調用了 ContextRefresher 中的 refresh 方法進行配置屬性的刷新。

請注意,RefreshRemoteApplicationEvent 是一個遠程事件,將通過消息中間件進行發送,并被 Spring Cloud Config 客戶端所監聽,處理流程如下圖所示:

圖 5 基于 Spring Cloud Bus 的事件傳播機制圖 5 基于 Spring Cloud Bus 的事件傳播機制

問題三:客戶端如何實時獲取服務器端所更新的配置信息?

最后需要明確的第三個問題是,客戶端如何獲取服務器端所更新的配置信息,這就需要梳理 Spring Cloud Config Server 與注冊中心之間的關系。

我們知道配置中心作為整個微服務架構運行所需的基礎服務,需要確保其可用性。因為配置服務本身也是一個獨立的微服務,所以 Spring Cloud Config 實現高可用的方式很簡單。跟其他微服務一樣,它把自己注冊到注冊中心上,讓其他服務提供者或消費者通過注冊中心進行服務發現和獲取。

圖 6 Spring Cloud Config 與注冊中心之間的關系圖 6 Spring Cloud Config 與注冊中心之間的關系

顯然,在這種方式下,注冊中心的服務治理機制同時提供了服務器端的負載均衡和客戶端的配置功能,從而也就間接實現了高可用性。從另一個角度,我們也可以理解為,可以通過注冊中心獲取所有 Spring Cloud Config 客戶端服務的實例,從而在分布式環境下為獲取配置信息提供了一種簡便的手段。

Spring Cloud Config 提供了一個工具類 ConfigServerInstanceProvider 來完成與注冊中心之間的交互,代碼如下所示:

public class ConfigServerInstanceProvider {
   private final DiscoveryClient client;
   @Retryable(interceptor = "configServerRetryInterceptor")
   public List<ServiceInstance> getConfigServerInstances(String serviceId) {
       List<ServiceInstance> instances = this.client.getInstances(serviceId);
       if (instances.isEmpty()) {
           //拋出異常
       }
       return instances;
    }
}

在這里,我們看到了熟悉的 DiscoveryClient,DiscoveryClient 通過同樣熟悉的 getInstances 方法從注冊中心中獲取 Spring Cloud Config 服務器實例,如下所示:

List<ServiceInstance> instances = this.client.getInstances(serviceId);

ConfigServerInstanceProvider 的調用者是 DiscoveryClientConfigServiceBootstrapConfiguration。現在我們來看這個 Spring Boot 自動配置類的定義,如下所示:

public class DiscoveryClientConfigServiceBootstrapConfiguration
        implements SmartApplicationListener {
    public void startup(ContextRefreshedEvent event) {
        refresh();
    }
}

可以看到,如果系統中生成了 ContextRefreshedEvent 事件就會觸發如下所示的 refresh 方法。

private void refresh() {
    try {
        ////獲取 Spring Cloud Config 客戶端服務實例
        String serviceId = this.config.getDiscovery().getServiceId();
        List<String> listOfUrls = new ArrayList<>();
        List<ServiceInstance> serviceInstances = this.instanceProvider.getConfigServerInstances(serviceId);
        //遍歷服務實例列表
        for (int i = 0; i < serviceInstances.size(); i++) {
            ServiceInstance server = serviceInstances.get(i);
            String url = getHomePage(server);
             //獲取配置路徑
            if (server.getMetadata().containsKey("configPath")) {
                String path = server.getMetadata().get("configPath");
                if (url.endsWith("/") && path.startsWith("/")) {
                    url = url.substring(0, url.length() - 1);
                }
                url = url + path;
            }
             //填充配置路徑
            listOfUrls.add(url);
        }
        String[] uri = new String[listOfUrls.size()];
        uri = listOfUrls.toArray(uri);
        this.config.setUri(uri);
    }
}

在上述 refresh 方法中,Spring Cloud Config 首先會獲取配置文件中配置項 spring.cloud.config.discovery.serviceId 所指定的服務實例 id,然后根據 serviceId 從 ConfigServerInstanceProvider 中獲取注冊服務的實例對象集合 serviceInstances,最后循環遍歷 serviceInstances 來更新存儲在內存中的配置屬性值。

至此,我們通過解答三個問題,引出了 Spring Cloud Config 中實現配置信息自動更新的三個步驟,并基于框架內部一系列組件之間的交互過程剖析了底層實現原理。

總結

今天基于 Spring Cloud Config 框架剖析了實現配置信息自動更新的工作原理。拋出了三個與這個主題相關的核心問題,然后基于源碼對這些問題做了一一解答。

事實上,Spring Cloud Config 作為 Spring 自研的配置中心框架,其內部大量使用了 Spring 現有的功能特性,比方說這節課中提到的 Spring 容器的事件發布和監聽機制,又比方說 Spring Boot Acuator 中的端點機制以及 Spring Cloud Bus 所具備的消息通信總線機制。這點與我們學習 Netflix 旗下的 Eureka、Zuul 等框架不同。我們需要首先對 Spring 容器相關的知識體系有足夠的了解,才能更好地理解 Spring Cloud Config 的設計和實現方式。

責任編輯:武曉燕 來源: 程序員技術充電站
相關推薦

2017-10-31 14:58:11

Spring Clou配置信息問題

2023-11-22 17:00:10

ElectronWeb

2015-03-30 14:15:55

自動更新Android

2015-09-15 15:25:36

更新配置Windows 10

2010-05-24 11:27:20

SVN配置自動更新WE

2021-11-08 22:24:04

Windows 10Windows微軟

2017-10-20 12:13:11

數據庫PostgreSQL時間戳

2016-07-12 10:09:13

OpenManage大

2010-01-08 13:20:52

ibmdwWeb

2025-02-10 00:14:00

2018-07-27 15:43:24

Spring Clou管理架構

2023-09-12 13:12:23

服務器系統

2012-04-16 14:55:29

MacChrome

2025-02-27 00:10:19

2010-12-13 13:33:47

Windows 7驅動

2018-06-22 15:46:45

Spring Clou加密處理

2018-07-10 14:55:32

Git存儲配置

2021-04-20 10:15:34

Spring ClouZuul架構

2017-01-12 21:02:29

Windows 10系統更新

2021-07-26 16:23:13

Windows 10Windows微軟
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 麻豆一区 | pacopacomama在线 | 91福利网 | www一级片 | 欧美a级成人淫片免费看 | 亚洲男人天堂网 | 日韩av一区二区在线观看 | 亚洲精品一区在线观看 | 久久99精品久久久久久国产越南 | 日产久久| 欧美成人h版在线观看 | 亚洲va在线va天堂va狼色在线 | 日本欧美在线视频 | 一片毛片 | 精品久久久久久亚洲精品 | julia中文字幕久久一区二区 | 羞羞视频在线观看 | 午夜激情免费 | 精品国产色 | 国产成人精品一区二区在线 | 久久久999免费视频 999久久久久久久久6666 | 蜜桃在线视频 | 最新91在线 | 国产精品久久精品 | 一区二区三区精品视频 | 91传媒在线播放 | 久久最新精品 | 日韩中文字幕第一页 | 欧美在线视频网 | 韩国毛片一区二区三区 | 欧美一区二区小视频 | 久久一二 | 久久久久九九九女人毛片 | 亚洲 欧美 日韩 在线 | 欧美激情精品久久久久 | 国产精品视频一二三区 | 91tv在线观看| 国产成人av免费看 | 日本一区二区电影 | 欧美综合久久 | 国产99久久久国产精品 |