响应式基础设施
本节涵盖使用 Spring Vault 实现响应式编程支持的基本信息。
什么是响应式编程?
简单来说,响应式编程是指非阻塞应用程序,它们是异步的、事件驱动的,并且需要少量线程才能垂直(即在 JVM 内)而不是水平(即通过集群)扩展。
响应式应用程序的一个关键方面是背压的概念,这是一种确保生产者不会压倒消费者的机制。例如,在一个从数据库到 HTTP 响应的响应式组件管道中,当 HTTP 连接太慢时,数据存储库也可以减慢或完全停止,直到网络容量释放。
响应式 Vault 客户端
Spring Vault 的响应式客户端支持构建在可组合身份验证步骤和 Spring 的函数式 WebClient(通过 Reactor Netty 或 Jetty)之上,它们都具有完全非阻塞、事件驱动的 HTTP 客户端。
它公开了 VaultTokenSupplier 作为 VaultToken 的提供者以进行 HTTP 请求身份验证,以及 ReactiveVaultOperations 作为主要入口点。VaultEndpoint、ClientOptions 和 SSL 的核心配置在各种客户端实现中重用。
位于 org.springframework.vault.core 包中的 ReactiveVaultTemplate 类是 Spring 响应式 Vault 支持的核心类,提供丰富的功能集以与 Vault 交互。该模板提供便捷的操作来在 Vault 中读取、写入和删除数据,并提供您的领域对象与 Vault 数据之间的映射。
配置完成后,ReactiveVaultTemplate 是线程安全的,可以在多个实例之间重用。 |
Vault 文档和领域类之间的映射通过委托给 WebClient 及其编解码器来完成。
ReactiveVaultTemplate 类实现了 ReactiveVaultOperations 接口。尽可能地,ReactiveVaultOperations 上的方法名称与 Vault API 上可用的方法名称一致,以便熟悉 API 和 CLI 的现有 Vault 开发人员熟悉该 API。例如,您会找到“write”、“delete”和“read”等方法。设计目标是尽可能简化 Vault API 和 ReactiveVaultOperations 之间的转换。这两个 API 之间的主要区别在于 ReactiveVaultOperations 可以传递领域对象而不是 JSON 键值对。
ReactiveVaultTemplate(以及可从其访问的接口)中使用的路径被认为是相对于 VaultEndpoint 的。完全限定的 URI 路径可用于在已认证的上下文中访问 Vault 集群成员。为防止不必要的完整 URI 访问,请确保在将路径传递给 ReactiveVaultTemplate 之前对其进行清理。
引用 ReactiveVaultTemplate 实例操作的首选方式是通过其接口 ReactiveVaultOperations。 |
ReactiveVaultTemplate 未明确暴露的功能,您可以使用几种 execute 回调方法之一来访问底层 API。execute 回调将为您提供一个 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://: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> TdoWithVault(Function<WebClient, ? extends T> clientCallback)使用给定的WebClient组合响应式序列,允许在没有会话上下文的情况下与 Vault 交互。 -
<T> TdoWithSession(Function<WebClient, ? extends T> clientCallback)使用给定的WebClient组合响应式序列,允许在已认证的会话中与 Vault 交互。
这是一个使用回调初始化 Vault 的示例
reactiveVaultOperations.doWithVault(webClient -> {
return webClient.put()
.uri("/sys/init")
.syncBody(request)
.retrieve()
.toEntity(VaultInitializationResponse.class);
});