响应式基础设施
本节介绍使用 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 上可用的方法命名,以便熟悉 Vault 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。但是,在托管上下文内注册的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 模板类的一个常见设计特征是,所有功能都路由到模板的 execute 回调方法之一。这有助于确保一致地执行异常和任何可能需要的资源管理。虽然在 JDBC 和 JMS 中比在 Vault 中更需要这样做,但它仍然提供了一个用于访问和记录的单一位置。因此,使用 execute 回调是访问 Vault API 以执行我们尚未在ReactiveVaultTemplate
上公开为方法的不常见操作的首选方法。
以下是 execute 回调方法的列表。
-
<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);
});