實戰:Nacos配置中心的Pull原理,附原始碼

張哥說技術發表於2023-11-20

來源:哪吒程式設計

大家好,我是哪吒。

在單體服務時代,關於配置資訊,管理一套配置檔案即可。

而拆分成微服務之後,每一個系統都會有自己的配置,並且都各不相同,有些配置還需要動態改變,以達到動態降級、切流量、擴縮容等目的。

一、本地配置

在Spring Boot開發中,可以把配置項放到config檔案中,把配置當程式碼使用。比如:

public class AppConfig {
    public static final String static_SUCCESS_CODE = "0000";
    public static final String static_ERROR_CODE = "0001";
}

也可以透過@Value載入yaml配置檔案中的配置。

@Component
public class HttpConfig {

    // 核心執行緒數
    public static String config_CORE_POOL_SIZE;

    @Value("${async.corePoolSize}")
    public void setSaveUrl(String corePoolSize) {
        HttpConfig.config_CORE_POOL_SIZE = corePoolSize;
    }
}

無論是將配置定義在程式碼中,還是將配置寫在yaml配置檔案中,都相當於把配置存在應用程式的本地。

如果想修改配置,就需要將在Linux伺服器中部署的程式停止,然後手動修改其配置,再進行重啟。

如果修改的配置項較多,這也是一項容易出錯,而且繁瑣的事情,長期運維的小夥伴應該深有體會。

當時,我就在想,作為世界上使用人數最多的語言,更新一個配置,需要這麼複雜嗎?

答案肯定不是的。

二、配置中心

配置中心(Configuration Center)通常用於集中管理應用程式的配置資訊。這些配置資訊可以包括資料庫連線資訊、外部服務地址、日誌級別、超時設定等。配置中心可以提高應用部署的靈活性和可維護性。

程式啟動時,可以自動從配置中心拉取所需要的配置項,配置中心中配置有所改變時,同樣可以自動從配置中心拉取最新的配置資訊,服務不需要重新發布。

1、以Nacos為例:

  1. 配置中心的資訊一般都是放在bootstrap.yml 中;
  2. 初始化的時候,Bootstrap Context負責從外部源載入配置屬性並解析配置;
  3. Bootstrap屬性有高優先順序,預設情況下,它們不會被本地配置覆蓋;
  4. 然後再讀取application.yml中的配置,進行配置合併,完成專案的啟動。
實戰:Nacos配置中心的Pull原理,附原始碼

專案的核心配置,需要熱更新的配置才有放到nacos管理的必要。基本不會變更的一些配置還是儲存在微服務本地比較好。

實戰:Nacos配置中心的Pull原理,附原始碼

2、Pull模式

Nacos採用的是Pull模式獲取服務端資料,客戶端採用長輪詢的方式定時的發起Pull請求,去檢查服務端配置資訊是否發生了變化。

  1. 客戶端發起長輪詢請求,監聽變更的dataId+group;
  2. 服務端收到客戶端的請求,這時會掛起客戶端的請求;
  3. 如果在服務端設計的29.5s之內都沒有發生變更,觸發自動檢查機制,此時不管是否有變化,服務端都會返回響應到客戶端
  4. 如果在29.5s之內配置項發生了變更,則會觸發一個事件機制,將變更的資料推送的客戶端。
實戰:Nacos配置中心的Pull原理,附原始碼

3、也可以透過Nacos實現註冊中心

這種是最簡單的Nacos註冊中心,有若干個服務,都註冊到Nacos註冊中心,呼叫之前,先到Nacos獲取對應介面,然後進行實際的呼叫。

服務1和服務2和Nacos之間維護一個心跳關係,每5秒跳一次,頻率不能太快或者太慢,否者會嗝屁的。

  1. 如果Nacos在5秒內沒有收到心跳,則表示服務掛了,Nacos會下線此服務。
  2. 對於超過15秒沒有收到客戶端心跳的服務例項,會將它的healthy屬性置為false,客戶端無法呼叫healthy為false的服務。
  3. 如果超過30秒沒有收到心跳,Nacos會直接將此服務剔除。

也可以透過服務端主動登出的方式,停止註冊。

服務1呼叫服務2時,服務1會透過定時任務到Nacos中獲取線上的服務,保證所呼叫的服務一直都是健康線上的狀態。

獲取到之後,用快取將其儲存起來,然後透過負載均衡器呼叫服務2,此時,將不再使用服務端的負載均衡Nginx了。

實戰:Nacos配置中心的Pull原理,附原始碼

三、配置中心提供了哪些功能

  1. 配置項管理:支援新增、釋出、修改配置項以及配置項的分組,可以實現版本管理,支援熱釋出、灰度釋出、環境隔離,提供API介面與視覺化操作頁面。
  2. 許可權控制:配置項訪問控制,讀許可權和寫許可權。
  3. 操作審計:支援記錄使用者的操作行為。
  4. 配置變更:當有新的配置項或是現有的配置項發生變動時,配置中心能夠進行實時的監控並做出相應的處理。
  5. 配置推送:透過訂閱/釋出的模式,將配置資訊推送給各個服務的消費者。
  6. 歷史版本管理:儲存所有的配置歷史版本,並提供查詢和對比的功能,可以輕鬆的回滾到任何一個版本。
  7. 灰度釋出:透過配置中心可以實現在部分環境中先發布新的配置項,觀察一段時間沒有問題後再推送給其他所有的環境。
  8. 配置變更審計:記錄每次配置的修改記錄,方便追蹤和管理。

這些功能可以幫助降低分散式系統中管理配置資訊的成本,降低因錯誤的配置資訊變更帶來可用性下降甚至發生故障的風險。

四、如何操作配置中心

1、配置註冊

配置中心的配置註冊通常包括以下步驟:

  1. 服務提供者在啟動時,將自己的配置資訊註冊到配置中心。這些資訊可能包括服務的IP地址、埠號、資料庫連線資訊等。
  2. 配置中心接收並儲存這些配置資訊。一般來說,配置中心會提供一個統一的介面或者介面,讓服務提供者能夠方便地進行註冊。
  3. 服務消費者在需要使用某個服務時,會從配置中心獲取相應的配置資訊。這樣,即使服務提供者的地址等資訊發生變化,服務消費者也能透過配置中心獲取到最新的配置資訊,而無需手動修改。

透過這種方式,配置中心實現了配置的統一管理和動態更新。服務提供者和消費者都可以透過配置中心來進行配置的註冊和獲取,大大提高了配置的靈活性和便利性。同時,也減少了因為手動配置錯誤而導致的問題,提高了系統的穩定性和可用性。

要透過Java程式碼實現配置註冊到配置中心,你可以遵循以下步驟。這裡繼續提供一個通用的示例程式碼,以展示基本的流程和步驟。請注意,實際的程式碼可能會因所使用的具體配置中心而有所不同。

import com.configcenter.sdk.ConfigCenterClient;  
import com.configcenter.sdk.exception.ConfigCenterException;  
import com.configcenter.sdk.model.Configuration;  
  
public class ConfigurationRegistration {  
  
    public static void main(String[] args) {  
        // 配置中心的伺服器URL和認證令牌  
        String serverUrl = "configcenter_server_url";  
        String authToken = "your_auth_token";  
  
        // 建立配置物件  
        Configuration configuration = new Configuration();  
        configuration.setId("your_configuration_id");  
        configuration.setKey("your_configuration_key");  
        configuration.setValue("your_configuration_value");  
        // 可選:設定其他配置項屬性,如描述、標籤等  
  
        try {  
            // 初始化配置中心的客戶端  
            ConfigCenterClient client = ConfigCenterClient.init(serverUrl, authToken);  
  
            // 呼叫配置中心的註冊API  
            boolean success = client.registerConfiguration(configuration);  
            if (success) {  
                System.out.println("配置註冊成功");  
            } else {  
                System.out.println("配置註冊失敗");  
            }  
        } catch (ConfigCenterException e) {  
            System.out.println("配置註冊出現異常: " + e.getMessage());  
            e.printStackTrace();  
        }  
    }  
}

在這個示例中:

  1. 我們首先建立了一個Configuration物件,設定了配置項的ID、鍵(key)和值(value)。你可以根據需要設定其他屬性,如描述、標籤等。
  2. 然後,我們初始化配置中心的客戶端,並呼叫client.registerConfiguration()方法來執行配置註冊操作,傳入建立好的Configuration物件。
  3. 該方法將返回一個布林值,表示註冊是否成功,我們根據返回結果列印相應的訊息。
  4. 如果發生異常,我們進行異常處理並列印異常資訊。

2、配置反註冊

配置中心的配置反註冊是指從配置中心中移除或登出某個配置項的過程。當某個服務或應用不再需要使用某個配置項時,可以進行配置反註冊操作。這個操作通常透過配置中心提供的介面來完成,它會將指定的配置項從配置中心中刪除或標記為登出狀態。

配置反註冊可以是手動觸發的,也可以是自動觸發的。

  1. 在手動觸發方式下,管理員或開發者可以透過呼叫配置中心提供的反註冊介面,指定需要反註冊的配置項。
  2. 自動觸發方式下,通常會在服務或應用停止時,自動觸發配置反註冊操作。

配置反註冊是配置中心的一個重要功能,它可以幫助管理員或開發者更好地管理配置項的生命週期,確保配置中心中的資料與實際應用需求保持一致。同時,透過反註冊不再需要的配置項,也可以減少配置中心的儲存空間和資源消耗。

要透過Java程式碼實現配置反註冊,你需要使用配置中心提供的Java SDK或API。以下是一個示例程式碼,展示瞭如何使用Java來實現配置反註冊。

import com.configcenter.sdk.ConfigCenterClient;  
import com.configcenter.sdk.exception.ConfigCenterException;  
  
public class ConfigurationDeregistration {  
  
    public static void main(String[] args) {  
        // 配置中心的伺服器URL和認證令牌  
        String serverUrl = "configcenter_server_url";  
        String authToken = "your_auth_token";  
  
        // 初始化配置中心的客戶端  
        ConfigCenterClient client = ConfigCenterClient.init(serverUrl, authToken);  
  
        // 配置項的ID  
        String configurationId = "your_configuration_id";  
  
        try {  
            // 呼叫配置中心的反註冊API  
            boolean success = client.deregisterConfiguration(configurationId);  
            if (success) {  
                System.out.println("配置反註冊成功");  
            } else {  
                System.out.println("配置反註冊失敗");  
            }  
        } catch (ConfigCenterException e) {  
            System.out.println("配置反註冊出現異常: " + e.getMessage());  
            e.printStackTrace();  
        }  
    }  
}

在這個示例中:

  1. 我們首先透過ConfigCenterClient.init()初始化配置中心的客戶端,傳入伺服器URL和認證令牌;
  2. 然後,我們呼叫client.deregisterConfiguration()方法來執行配置反註冊操作,傳入配置項的ID;
  3. 該方法將返回一個布林值,指示反註冊是否成功;
  4. 根據返回結果,我們列印相應的訊息;
  5. 如果發生異常,我們捕獲並列印異常資訊。

3、配置檢視

透過配置中心的使用者介面和API介面,你可以方便地檢視和管理配置項。

import com.configcenter.sdk.ConfigCenterClient;  
import com.configcenter.sdk.exception.ConfigCenterException;  
import com.configcenter.sdk.model.Configuration;  
  
public class ConfigurationViewer {  
  
    public static void main(String[] args) {  
        // 配置中心的伺服器URL和認證令牌  
        String serverUrl = "configcenter_server_url";  
        String authToken = "your_auth_token";  
  
        // 配置項的ID或鍵(key)  
        String configurationId = "your_configuration_id";  
        // 或者使用配置項的鍵(key)來獲取配置項,根據配置中心API的要求而定  
        // String configurationKey = "your_configuration_key";  
  
        try {  
            // 初始化配置中心的客戶端  
            ConfigCenterClient client = ConfigCenterClient.init(serverUrl, authToken);  
  
            // 呼叫配置中心的API介面獲取配置項  
            Configuration configuration = client.getConfiguration(configurationId);  
            // 或者使用配置項的鍵(key)來獲取:  
            // Configuration configuration = client.getConfigurationByKey(configurationKey);  
  
            // 輸出配置項的資訊  
            if (configuration != null) {  
                System.out.println("配置項ID: " + configuration.getId());  
                System.out.println("配置項鍵(key): " + configuration.getKey());  
                System.out.println("配置項值(value): " + configuration.getValue());  
                // 輸出其他配置項屬性,如描述、標籤等  
            } else {  
                System.out.println("未找到配置項");  
            }  
        } catch (ConfigCenterException e) {  
            System.out.println("檢視配置項出現異常: " + e.getMessage());  
            e.printStackTrace();  
        }  
    }  
}

在上面的示例程式碼中:

  1. 我們首先初始化配置中心的客戶端;
  2. 然後呼叫相應的API介面來獲取配置項;
  3. 在獲取到配置項後,我們可以輸出配置項的各種屬性,如ID、鍵(key)、值(value)等;
  4. 如果發生異常,我們進行異常處理並列印相應的異常資訊。

4、配置變更訂閱

配置中心通常支援配置變更訂閱功能,允許應用程式或其他服務訂閱配置項的變更通知。當配置項發生變化時,配置中心會向訂閱者傳送通知,以便訂閱者能夠及時獲取最新的配置項。

要透過Java程式碼實現配置變更訂閱,你可以按照以下步驟進行操作:

  1. 首先,確保你已經初始化了配置中心的客戶端,如上述示例程式碼所示。
  2. 建立一個訂閱者(listener)類,實現配置中心提供的訂閱介面。這個類將負責處理配置項的變更通知。
  3. 在訂閱者類中,實現介面中定義的方法,以處理配置項的變更事件。該方法通常會在配置項發生變化時被呼叫,並且會接收包含變更資訊的引數。
  4. 在你的應用程式或服務中,建立一個訂閱請求(subscription request)物件,指定你希望訂閱的配置項或配置項的過濾條件。
  5. 使用配置中心的客戶端物件,呼叫訂閱方法,將訂閱請求物件和訂閱者物件作為引數傳遞給該方法。這將向配置中心註冊你的訂閱請求,並指定訂閱者類來處理變更通知。
  6. 一旦註冊成功,當配置項發生變更時,配置中心將呼叫訂閱者類中的方法,將變更資訊傳遞給訂閱者。你可以在這個方法中編寫邏輯來處理配置項的變更,如更新本地快取、重新載入配置等。

下面是一個簡單的示例程式碼,展示如何實現配置變更訂閱:

import com.configcenter.sdk.ConfigCenterClient;  
import com.configcenter.sdk.exception.ConfigCenterException;  
import com.configcenter.sdk.listener.ConfigurationChangeListener;  
import com.configcenter.sdk.model.Configuration;  
  
public class ConfigurationSubscriber {  
  
    public static void main(String[] args) {  
        // 初始化配置中心的客戶端(省略程式碼)  
  
        // 建立訂閱者類  
        ConfigurationChangeListener listener = new ConfigurationChangeListener() {  
            @Override  
            public void onConfigurationChanged(Configuration configuration) {  
                // 處理配置項變更事件  
                System.out.println("配置項發生變化: " + configuration.getKey() + " = " + configuration.getValue());  
                // 在這裡可以更新本地快取、重新載入配置等  
            }  
        };  
  
        try {  
            // 建立訂閱請求物件(根據配置中心API的要求而定)  
            // 指定你希望訂閱的配置項過濾條件,如配置項的鍵(key)或其他屬性  
  
            // 呼叫配置中心的訂閱方法  
            ConfigCenterClient client = ConfigCenterClient.init(serverUrl, authToken);  
            client.subscribeToConfigurationChanges(filter, listener);  
        } catch (ConfigCenterException e) {  
            System.out.println("配置變更訂閱出現異常: " + e.getMessage());  
            e.printStackTrace();  
        }  
    }  
}

五、主流的微服務註冊中心有哪些,如何選擇?

1、在選擇微服務註冊中心時,可以考慮以下因素:

  1. 功能和特性:不同的註冊中心可能具有不同的功能和特性,需要根據自己的需求來選擇。例如,一些註冊中心可能更側重於服務發現,而另一些可能提供更全面的配置管理功能。
  2. 效能和穩定性:註冊中心作為微服務架構的核心元件,其效能和穩定性至關重要。需要對候選的註冊中心進行效能測試和穩定性評估,確保它們能夠滿足你的業務需求。
  3. 易用性和開發體驗:註冊中心的易用性和開發體驗也是選擇的重要因素。選擇一個提供良好開發文件、客戶端庫和工具的註冊中心,可以使開發過程更加順暢高效。
  4. 社群支援和生態系統:一個活躍和健康的社群可以為註冊中心提供持續的支援和改進。同時,一個豐富的生態系統可以提供更多的整合選項和解決方案。因此,需要評估候選註冊中心的社群活躍度和生態系統成熟度。
  5. 安全性和合規性:安全性和合規性對於任何系統都至關重要。需要確保所選的註冊中心能夠提供足夠的安全保障,並滿足你的合規性要求。

最終,選擇微服務註冊中心是一個權衡的過程,需要根據自己的實際需求、技術棧、團隊熟悉度等因素進行綜合考慮。

2、主流注冊中心

在Eureka、Consul、Zookeeper和Nacos這幾個微服務註冊中心中,選擇最適合的一個取決於你的具體需求和環境。

(1)Eureka

  • 是Netflix開發的服務註冊中心,與Spring Cloud整合良好。
  • 保證了高可用性和最終一致性,服務註冊相對較快。
  • 在資料不一致時,每個Eureka節點仍能正常對外提供服務,保證了可用性。

(2)Consul

  • 使用Go語言編寫,具有較好的跨平臺性。
  • 提供了豐富的功能和強大的一致性保證。
  • 支援多資料中心和分散式部署,適合大規模環境。

(3)Zookeeper

  • 最初是一個分散式協調服務,後來被用於服務註冊和發現。
  • 提供了強一致性和高可用性,但相對較複雜,需要自行實現一些服務發現功能。

(4)Nacos

  • 是阿里巴巴開源的專案,支援基於DNS和基於RPC的服務發現。
  • 除了服務註冊和發現,還支援動態配置服務。
  • 在Spring Cloud中使用較為簡單,只需簡單的配置即可完成服務的註冊和發現。

3、如何選擇?

  • 如果你使用Spring Cloud作為微服務框架,Eureka可能是一個自然的選擇,因為它與Spring Cloud整合良好。
  • 如果你需要強大的跨平臺支援和一致性保證,Consul是一個不錯的選擇。
  • 如果你已經在使用Zookeeper或其他Apache專案,並且希望在同一生態系統中解決服務註冊和發現問題,那麼Zookeeper可能適合你。
  • 如果你在尋找一個簡單且與阿里巴巴技術棧整合的解決方案,Nacos是一個值得考慮的選項。

最終的選擇應基於你的技術需求、團隊熟悉度和業務場景。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70024923/viewspace-2996072/,如需轉載,請註明出處,否則將追究法律責任。

相關文章