响应式基础设施
本节介绍使用 Spring Vault 进行响应式编程支持的基本信息。
什么是响应式编程?
简单来说,响应式编程是关于非阻塞应用程序的,这些应用程序是异步的、事件驱动的,并且需要少量线程来进行垂直扩展(即在 JVM 内)而不是水平扩展(即通过集群)。
响应式应用程序的一个关键方面是背压的概念,这是一种机制,可以确保生产者不会压倒消费者。例如,在一个从数据库到 HTTP 响应的响应式组件管道中,当 HTTP 连接过慢时,数据存储库也可以减慢或完全停止,直到网络容量释放。
响应式 Vault 客户端
Spring Vault 的响应式客户端支持建立在 可组合身份验证步骤 和 Spring 的函数式 WebClient
(通过 Reactor Netty 或 Jetty)之上,它们都具有完全非阻塞、事件驱动的 HTTP 客户端。
它公开 VaultTokenSupplier
作为 VaultToken
的提供者来验证 HTTP 请求,并公开 ReactiveVaultOperations
作为主要入口点。VaultEndpoint
、ClientOptions
和 SSL 的核心配置在各种客户端实现中重复使用。
类 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 上下文。但是,在托管上下文中注册的 ReactiveVaultTemplate
和 VaultTokenSupplier
实例将参与 Spring IoC 容器提供的 生命周期事件。这对于在应用程序关闭时释放活动 Vault 会话非常有用。您还可以从在整个应用程序中重用相同的 ReactiveVaultTemplate
实例中获益。
Spring Vault 带有一个支持配置类,该类提供用于在 Spring 上下文中使用的 Bean 定义。应用程序配置类通常扩展自 AbstractVaultConfiguration
,并且需要提供特定于环境的额外详细信息。
从 AbstractVaultConfiguration
扩展需要实现 VaultEndpoint vaultEndpoint()
和 ClientAuthentication clientAuthentication()
方法。
@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);
});