pca*_*tre 24 reactive spring-webflux
我试图了解什么时候我们会使用像 webflux 这样的反应式堆栈框架。我读过的文章似乎表明,当我们有许多阻塞调用时,我们将从反应式方法中受益。例如,如果我们有一个 Webhook 服务,需要调用客户端服务器来更新信息。
但我也在这里阅读https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html
评估应用程序的一个简单方法是检查其依赖性。如果您要使用阻塞持久性 API(JPA、JDBC)或网络 API,那么 Spring MVC 至少是通用架构的最佳选择。使用 Reactor 和 RxJava 在单独的线程上执行阻塞调用在技术上是可行的,但您不会充分利用非阻塞 Web 堆栈。
这似乎表明恰恰相反。我读到,如果你可以流式传输信息,反应式会更有用。例如,如果您有一个前端要求一个列表和一个反应源,它可以在信息可用时为您提供信息,而不是在信息完成后仅提供全部信息。
那么问题是我们什么时候应该在后端使用响应式?当我们有很多阻塞调用时我们应该使用它吗?例如,对客户端的 HTTP 调用我们需要等待响应。或者这到底是错误的用例?
我知道还有其他考虑因素,例如代码的复杂性。我知道反应式方法更难实现,但我在这里只是询问性能和可扩展性。
Tho*_*olf 60
由于我们不知道您的确切架构,因此很难在这里给您任何具体答案。
但是,如果您了解反应式试图解决的问题以及它是如何解决的,那么您可能会更好地了解如何做出更好的决策。
大多数 Java Web 服务器使用的传统 servlet 方法为每个请求分配一个线程。因此,当收到请求时,就会为其分配一个线程,然后该线程处理该请求。如果您的服务器随后阻塞对其他服务器的调用,则分配的线程需要等待响应返回。
这往往会导致 Web 服务器有数百个线程,这些线程花费大量时间等待。当我说等待时,我的意思是等待很多。线程 90% 的时间都花在等待阻塞调用上。例如,Web 服务器中的处理可能需要 3 毫秒,然后它会执行阻塞数据库调用,并且线程需要等待 200 毫秒(不要引用我的数字)。
大量的资源都花在了等待上。
这么老的方法:
反应式通过使用事件循环和一个在事件循环上安排工作的小型线程池来解决这个问题。
在实践中,你可以这样看,一个事件循环,然后可能有 10 个线程,所有线程都调度工作,事件循环一直在工作,调度程序只是为事件循环安排一长串工作来推动。所以所有线程始终处于 100% 繁忙状态。
在 webflux 应用程序中,事件循环的数量通常取决于硬件中内核的数量。
但这意味着我们需要100%非阻塞。想象一下,在这种情况下我们有一个阻塞调用,然后整个事件循环将停止,所有计划的作业将停止,整个机器将冻结,直到我们“解除阻塞”。
如此反应:
所以我们基本上是用内存换取 CPU 能力。
那么什么是阻塞调用呢?大多数呼叫都会阻塞,因为您呼叫另一个服务并且需要等待。但这就是响应式的闪光点,因为它还有另一个功能。
由于每个请求没有一个特定的线程,因此任何线程都可以发出请求,但事情是这样的,任何线程都可以处理响应,它不必是同一个线程。
我们是所谓的线程不可知论者。
我们的非阻塞服务可以对其他服务进行大量阻塞调用,并且仍然保持完全非阻塞。因为当说非阻塞时,我的意思是我们在自己的应用程序内部是非阻塞的。
那么什么是错误的阻塞调用呢?好吧,当您调用与线程相关的东西时。这意味着您正在调用的东西依赖于发出调用来处理响应的同一线程,那么我们需要阻塞该线程并等待响应。
如果我们需要进行调用,然后阻塞等待响应,然后处理响应,因为我们需要相同的线程,那么我们就不能使用响应式,因为这样我们可能会阻塞事件循环,这将停止整个应用程序。
例如,ThreadLocal在响应式世界中,所有使用的东西都是不好的,这就是主要问题之一。 JDBC(数据库驱动程序规范)本质上是阻塞编写的。因为它依赖于本地线程来跟踪事务以便能够回滚。这意味着所有使用 JDBC 的数据库调用在非/阻塞反应式应用程序中都不可用,这意味着您必须使用使用 R2DBC 规范的数据库驱动程序。
但是 REST 调用不会阻塞,因为它不依赖于线程,除非您使用依赖于线程的功能,而ThreadLocalSpring Webclient 则不然。
那么你的引用在说什么?Spring Reactor 有一种机制,使您可以将“旧方式”(每个请求一个线程)与新方式(线程无关)混合在一起。这意味着,如果您有一个硬阻塞调用(使用 JDBC 驱动程序调用旧数据库),您可以明确告诉框架“对此数据库的所有调用都应该放在它自己的线程池上”,这样您就可以告诉框架使用旧方法(通过为该请求分配一个独占线程)进行该特定调用的框架。但请记住,这样做您将失去响应式的所有好处。
因此,如果您的服务仅调用大量硬阻塞服务(例如旧数据库),您将不得不不断选择退出反应式框架,因此您基本上只需使用反应式框架构建一个旧的传统 servlet Web 服务,即有点反模式。所以我不建议这样做。
我在这里写的只是一般计算机知识,线程如何工作,REST 调用如何工作,数据库驱动程序如何工作。我无法在单个堆栈溢出帖子中解释计算机如何工作。
Reactor 参考文献中阐述了这一点以及更多内容,我建议您进行更多研究。
如果你的道路有很多转弯而没有直道,那么如果你经常需要减速并经常转弯,那么购买一辆 F1 赛车还有什么意义呢?
我把这个决定留给你。
| 归档时间: |
|
| 查看次数: |
9738 次 |
| 最近记录: |