如何在租户上下文中正确使用 spring webclient

how to use spring webclient properly in the tenant context

我正在使用 Spring WebClient (org.springframework.web.reactive.function.client.WebClient) 以实现一些非阻塞行为。

        Mono<ClientResponse> clientResponse = 
            webClient
            .get(...).exchange();

        clientResponse.subscribe((response) -> {
             //--- unfortunately my tenant context is lost here !!! Someone knows the right solution?
        });

然而,一旦响应到达,我的租户上下文就会丢失(当然,我们在一个新线程中)。

这里是关于如何在租户上下文中实现常见异步任务的文档:https://sap.github.io/cloud-sdk/docs/java/features/multi-tenancy/multi-tenancy-thread-context/

但是,我找不到如何使用 Spring webflux(使用 WebClient)保留租户上下文的推荐方法。

SAP Cloud SDK API 支持 Spring Boot,目前不支持开箱即用的 Spring Webflux。如果在响应式 Spring 开发中使用 SDK API,您可能会看到各种错误。另一方面,正如 Matthias 所展示的那样,某些用例可能有变通办法。

我们考虑在将来添加 Spring WebFlux 支持。今年(2021年)应该不会了。

编辑:SAP Cloud SDK 在操作结束时销毁 ThreadContext。这样做是为了防止它泄漏,例如当线程被重新使用时。

如果:

  • 上下文传递给异步操作
  • 但“父”操作在异步操作开始之前完成

ThreadContext在异步操作中将不可用。这就是使用 WebClient.

时发生的情况

自定义属性不是这样,SDK 不会清除它们。但这也意味着您必须自己清除它们以确保它们在重新使用线程时不会泄漏。

在这种情况下,我建议不要使用 SDK 的多租户功能。尽管如此,我还是会留下下面的答案以供参考。


当且仅当您拥有控制权时,您才可以将 SAP Cloud SDK 的 ThreadContext 转移到任何新线程:

  • 创建新线程之前
  • 需要上下文
  • 的异步操作运行
  • 编辑:父线程(上下文)仍然存在

我对 WebFlux 不太熟悉,但我假设:

  • clientResponse.subscribe 运行 父线程
  • 并且lambda在异步线程中执行

鉴于此,以下内容应将 ThreadContext 转移到 lambda 中:

ThreadContextExecutor executor = new ThreadContextExecutor();

clientResponse.subscribe((response) -> 
    executor.execute(() ->
       {
          // your code goes here, the ThreadContext should be available
       }
    )
);

您必须在新线程中 运行 正在执行操作的每个点执行此操作。正如 Artem 指出的那样,目前 SDK 中没有可自动实现相同功能的功能。


我认为还可以定义一个自定义 ExecutorService,Spring 将使用它来创建和 运行 新线程。在自定义执行程序中,您可以为所有操作封装一次此包装逻辑。