【问题标题】:Spring MVC to Spring Webflux migration - block vs subscribeSpring MVC 到 Spring Webflux 迁移 - 阻止与订阅
【发布时间】:2019-10-22 22:26:27
【问题描述】:

让我们想象一个场景,其中有一个使用 Servlet 堆栈编写的旧应用程序,您决定将其迁移到 Spring Webflux。假设首先要迁移的是RestTemplateWebClient

处理WebClient 返回的MonoFlux 的首选方式是什么?调用 block 似乎是好的解决方案,因为应用程序使用 RestTemplate 无论如何都会阻塞。 subscribe 应该更好一些,因为它有回调,但也许你必须等待才能继续。另外,对于subscribe,我们是否需要处理Disposable,如果需要,如何处理,因为我不确定在哪里最好调用dispose

还有一个关于 JDBC 的问题。使用Schedulers.boundedElastic() 有多危险?据我了解,拥有一个单独的线程池应该会有所帮助,尤其是在使用 Netty 的情况下。这并不理想,但在 R2DBC 驱动程序达到 1.0.0 之前,它是否可以作为临时解决方案?如果应用程序使用 Tomcat 怎么办? Tomcat默认有更多线程,情况会更好吗?

【问题讨论】:

    标签: spring spring-mvc spring-webflux project-reactor


    【解决方案1】:

    处理 WebClient 返回的 Mono 或 Flux 的首选方式是什么?

    鉴于您的目标是使用 Webflux,最终的首选方式是在您的反应链上以整个方式处理这些发布者。这意味着您最终不会直接调用 subscribe 任何东西,因为您的控制器本身将返回一个 Mono (并且所有内容,包括 WebClient 调用,都将通过一系列反应性操作合并到 Mono在链中。)

    但是,正如您所指出的,您实际上无法一次迁移所有内容。

    如果它只有您现在要迁移的WebClient,那么只需调用block() 以与您的RestController 一样对待它。调用 subscribe() 然后等待订阅完成没有任何优势 - 这只是一种不太明显且更冗长的阻塞方式。

    一旦您将越来越多的堆栈迁移到响应式,您就可以以响应式的方式做越来越多的事情,然后开始“移动”您的 block() 调用,从而进一步向上链(直到块在控制器级别,然后您可以切换到返回Mono。)

    另外,通过订阅,我们是否需要处理 Disposable

    仅当您可能需要取消订阅者(并且它支持它)时。根据我的经验,这种情况非常罕见。

    还有一个关于 JDBC 的问题。使用Schedulers.boundedElastic()有多危险?

    boundedElastic() 被设计为阻塞 IO 的包装器,因此在反应器端使用它本身并没有错。唯一的“危险”在于 JDBC / 应用程序是否符合您的要求:

    • CPU 内核数量上限为 10 倍
    • “排队”任务的数量上限为 100K

    如果您有足够长的运行时间的数据库查询而这还不够,那么您可以考虑改用newBoundedElastic() 并手动指定threadCapqueuedTaskCap

    如果应用程序使用 Tomcat 会怎样? Tomcat默认有更多线程,情况会更好吗?

    我不建议依赖它。 Tomcat 仍然在每个请求中使用一个线程(即使使用 Webflux),因此存在您最终阻塞一个您不应该阻塞的线程的危险,并且最终没有意识到然后依赖该行为(当你切换到 Netty。)

    【讨论】:

    • 这是一个写得很好的回复 :) 另外,你基本上证实了我的每一个理论,但无法找到正确的答案/确认。我有 2 年的 RxJava 经验,所以响应式对我来说并不新鲜,但我发现有太多地方说 JDBC + 响应式会导致很多问题,这对我来说很奇怪,因为我知道 boundedElastic()。但是,我想有权衡。也许你会在调用阻塞 API 时遇到一些问题,最好还是坚持使用 Tomcat(因为它仍然适用于响应式类型),但我想这取决于用例。
    • 这是关于反应式 Java 的“名人堂”答案之一。我是 WebFlux 的完整初学者,一点一点地学习它,这个答案确实有助于确认我对 WebFlux 和反应式 Java 的概念。非常感谢! :-)
    • @MichaelBerry 在标准 webmvc 中我可以使用 subscribe 进行异步调用吗,它正在工作。只有当线程完成和订阅方法进行调用和完成调用时才被处理?
    • @Bilgehan 你可以,你不需要担心处理/清理,但最大的缺点是当它完成“链”到任何其他时,没有办法得到回调手术。所以从这个意义上说,它真的是“一劳永逸”。如果这确实是您需要的,那么订阅就没有问题,但通常您会在完成后需要某种反馈,在这种情况下,它是不合适的。
    • 谢谢迈克尔,那么它是完全安全的,如果我在简单的 mvc 中使用 webclient 并订阅异步调用,或者你是否建议任何其他方法?当我阅读 spring 网站时,他们建议使用 webclient 来休息和 asyctemplate
    猜你喜欢
    • 1970-01-01
    • 2020-04-06
    • 2018-03-18
    • 2020-05-18
    • 1970-01-01
    • 2021-08-17
    • 2015-12-20
    • 1970-01-01
    相关资源
    最近更新 更多