反應式基礎架構

本節涵蓋使用 Spring Vault 的反應式程式設計支援的基本資訊。

什麼是反應式程式設計?

簡單來說,反應式程式設計是有關非阻塞應用程式,它們是非同步和事件驅動的,並且需要少量的執行緒來垂直擴展(即在 JVM 內部),而不是水平擴展(即透過叢集)。

反應式應用程式的一個關鍵方面是背壓的概念,這是一種確保生產者不會壓倒消費者的機制。例如,在從資料庫延伸到 HTTP 回應的反應用程式元件管線中,當 HTTP 連線太慢時,資料儲存庫也可以減速或完全停止,直到網路容量釋放出來。

反應式 Vault 客戶端

Spring Vault 的反應式客戶端支援建立在可組合的驗證步驟和 Spring 的功能性 WebClient 之上,透過 Reactor Netty 或 Jetty,它們都具有完全非阻塞、事件驅動的 HTTP 客戶端。

它公開了 VaultTokenSupplier 作為 VaultToken 的供應者,用於驗證 HTTP 請求,以及 ReactiveVaultOperations 作為主要入口點。VaultEndpointClientOptionsSSL 的核心配置在各種客戶端實作中重複使用。

ReactiveVaultTemplate 類別位於 org.springframework.vault.core 套件中,是 Spring 反應式 Vault 支援的核心類別,提供豐富的功能集以與 Vault 互動。該模板提供方便的操作來讀取、寫入和刪除 Vault 中的資料,並提供您的網域物件和 Vault 資料之間的映射。

一旦配置完成,ReactiveVaultTemplate 就是執行緒安全的,並且可以在多個實例中重複使用。

Vault 文件和網域類別之間的映射是透過委派給 WebClient 及其編解碼器來完成的。

ReactiveVaultTemplate 類別實作了 ReactiveVaultOperations 介面。在盡可能多的情況下,ReactiveVaultOperations 上的方法以 Vault API 上可用的方法命名,以使 API 對於已經習慣使用 API 和 CLI 的現有 Vault 開發人員來說是熟悉的。例如,您會找到諸如 "write"、"delete" 和 "read" 等方法。設計目標是盡可能容易地在 Vault API 和 ReactiveVaultOperations 的使用之間進行轉換。兩個 API 之間的主要區別在於 ReactiveVaultOperations 可以傳遞網域物件而不是 JSON 鍵值對。

參考 ReactiveVaultTemplate 實例上的操作的首選方式是透過其介面 ReactiveVaultOperations

對於 ReactiveVaultTemplate 未明確公開的功能,您可以使用多個執行回呼方法之一來存取底層 API。執行回呼將為您提供對 WebClient 物件的參考。請參閱「執行回呼」章節以取得更多資訊。

現在讓我們看看如何在 Spring 容器的上下文中與 Vault 協同工作的範例。

註冊和配置 Spring Vault Bean

使用 Spring Vault 不需要 Spring Context。但是,在受管上下文中註冊的 ReactiveVaultTemplateVaultTokenSupplier 實例將參與 Spring IoC 容器提供的 生命週期事件。這對於在應用程式關閉時處置活動的 Vault 會話很有用。您還可以受益於在整個應用程式中重複使用相同的 ReactiveVaultTemplate 實例。

Spring Vault 隨附一個支援配置類別,該類別提供在 Spring 上下文內使用的 Bean 定義。應用程式配置類別通常從 AbstractVaultConfiguration 擴展,並且需要提供特定於環境的其他詳細資訊。

AbstractVaultConfiguration 擴展需要實作 VaultEndpoint vaultEndpoint()ClientAuthentication clientAuthentication() 方法。

範例 1. 使用基於 Java 的 Bean 元資料註冊 Spring Vault 物件
@Configuration
public class AppConfig extends AbstractReactiveVaultConfiguration {

    /**
     * Specify an endpoint for connecting to Vault.
     */
    @Override
    public VaultEndpoint vaultEndpoint() {
        return new VaultEndpoint();                            (1)
    }

    /**
     * Configure a client authentication.
     * Please consider a more secure authentication method
     * for production use.
     */
    @Override
    public ClientAuthentication clientAuthentication() {
        return new TokenAuthentication("…");                   (2)
    }
}
1 建立一個新的 VaultEndpoint,預設指向 https://127.0.0.1:8200
2 此範例使用 TokenAuthentication 快速開始。有關支援的驗證方法的詳細資訊,請參閱 [vault.core.authentication]

會話管理

Spring Vault 需要一個令牌來驗證 Vault 請求。有關驗證的詳細資訊,請參閱 [vault.core.authentication]。反應式客戶端需要一個非阻塞令牌供應器,其合約在 VaultTokenSupplier 中定義。令牌可以是靜態的,也可以透過宣告的驗證流程獲得。Vault 登入不應在每次驗證的 Vault 互動時發生,但會話令牌應在整個會話中保留。此方面由實作 ReactiveSessionManager 的會話管理器處理,例如 ReactiveLifecycleAwareSessionManager

執行回呼

所有 Spring 模板類別的一個常見設計特點是,所有功能都路由到模板的執行回呼方法之一。這有助於確保異常和可能需要的任何資源管理都以一致的方式執行。雖然在 JDBC 和 JMS 的情況下比 Vault 更需要這樣做,但它仍然為存取和記錄提供了一個單一位置。因此,使用執行回呼是存取 Vault API 以執行我們未在 ReactiveVaultTemplate 上公開為方法的不常見操作的首選方式。

這是執行回呼方法的列表。

  • <T> T doWithVault (Function<WebClient, ? extends T> clientCallback) 組成給定 WebClient 的反應式序列,允許在沒有會話上下文的情況下與 Vault 互動。

  • <T> T doWithSession (Function<WebClient, ? extends T> clientCallback) 組成給定 WebClient 的反應式序列,允許在已驗證的會話中與 Vault 互動。

這是一個使用回呼來初始化 Vault 的範例

reactiveVaultOperations.doWithVault(webClient -> {

    return webClient.put()
                    .uri("/sys/init")
                    .syncBody(request)
                    .retrieve()
                    .toEntity(VaultInitializationResponse.class);
});