响应式编程是否比非响应式编程消耗更多的资源?



我们目前正面临Spring webFlux的性能问题。 为了确定响应式编程的好处,我们实现了一个Spring Boot服务,该服务从MongoDB获取数据,并通过REST API将其返回给消费者。

该服务有两种变体:

  1. 一个带有Spring Boot,MongoRepository的非反应式实现。此服务将数据作为列表返回
  2. 使用 Spring Boot、ReactiveMongoRepository、spring-boot-starter-webflux 实现的响应式实现。此服务将数据作为 Flux 返回。

在这两种实现中,REST 控制器直接从存储库中获取数据,并将其作为 List 或 Flux 返回。不执行进一步的应用程序逻辑。

我们对 100 个用户调用该服务进行了一次小型负载/性能测试,我们发现非反应式实现的性能远远优于反应式实现。

事实上,非反应式实现不仅具有更好的 HTTP 吞吐量,而且也许更有趣的是,它比反应式实现消耗更少的 CPU 和更少的线程! 这与预期尤其相反,因为我们预计反应式版本可以使用少量线程进行扩展,如 https://spring.io/blog/2016/07/28/reactive-programming-with-spring-5-0-m1 中所述

我们需要在设置中调整什么吗?

有人遇到过类似的问题吗?

我们使用 Spring-Data-Reactive-Cassandra 和Spring-Webflux 对 Spring-Data-Cassandra 和 Spring-MVC 进行了类似的测试。

我们对两台服务器进行了 10000 个请求的基准测试,并发性为 100 req/sec。结果并不令人惊讶:-

Non Reactive Stack:-
Concurrency Level:      100
Time taken for tests:   22.945 seconds
Complete requests:      10000
Failed requests:        0
Percentage of the requests served within a certain time (ms)
50%    190
66%    253
75%    288
80%    314
90%    384
95%    465
98%    627
99%    824
100%   1208 (longest request)
Reactive Stack:-
Concurrency Level:      100
Time taken for tests:   30.061 seconds
Complete requests:      10000
Failed requests:        0
Percentage of the requests served within a certain time (ms)
50%    304
66%    379
75%    421
80%    443
90%    507
95%    589
98%    694
99%    736
100%    858 (longest request)

在执行这些测试时,非反应式堆栈生成了 147 个线程,而反应式堆栈生成了 48 个线程。

如果比较结果,非反应式堆栈比反应式堆栈略快。它在大约 23 秒内将 10,000 个对象持久化到数据库中,而反应式堆栈大约需要 30 秒。但是,如果您比较两个堆栈中最慢的 2% 请求,则反应式堆栈几乎快 28%。

线程数量较少的反应式堆栈具有更均匀的响应时间分布。没有一个请求被搁置。而对于非反应式堆栈,1% 的请求相对较慢。

在持续一段时间内增加调用次数时,与非反应式堆栈相比,反应式堆栈将能够更好地扩展。由于与可以在服务器上打开的套接字数量相比,您可以在服务器上生成的线程数要少得多。此外,在这些测试中,两种情况下的CPU利用率都低于33%,从而证明CPU利用率并没有限制可扩展性。

如果非反应式堆栈没有受到线程上下文切换和线程创建的限制,它可以扩展更多。

让我尝试解释这种行为的可能原因。反应式应用程序的运行速度并不比反应式应用程序快。如果请求队列不为空,则反应式应用程序不允许系统处于空闲状态。由于您在低负载下进行了测试,因此您还没有看到反应式应用程序的优缺点,但您已经看到了性能的降级。性能低于非活动应用程序的性能,因为反应式执行的开销很小。

相关内容

  • 没有找到相关文章

最新更新