最近发布了Spring-boot 2.0,新功能和改进让大家都很兴奋。我喜欢Spring-boot提供的轻松和简单,让你可以在最小的麻烦下创建服务。其中最有趣、关键和值得注意的特性之一是增加和支持反应式编程模型。Spring 5引入了WebFlux框架,这是一个完全异步和非阻塞的反应式Web堆栈,可以处理大量并发连接。这使我们能够垂直扩展服务,以在相同的硬件上处理更多的负载。
这个实验的目的是通过捕捉它们在负载下的性能来比较传统的servlet堆栈和反应式堆栈。
为了实现这一点,我创建了3个服务,如下所示:基于_spring-boot web 1.5.10.RELEASE_的PersonService基于_spring-boot web 2.0.0.RELEASE_的第二个PersonService*基于_spring-boot reactive-web-2.0.0.RELEASE_的第三个PersonService为了尽可能地保持代码相似,我使用基于注释的方法创建了类似的“控制器”和“服务”。(对于好奇的人,还有另一种功能方式来创建路由和处理程序)。
反应式堆栈的真正威力在于与阻塞I/O的交互。为了模拟这个过程,我添加了一个registrationService,引入了200毫秒的延迟。每个PersonService将调用registrationService,并在成功时返回状态201-Created。
为了衡量性能,我使用Gatling编写了我的测试方案。测试包括用户4次调用PersonService,每次使用Person有效载荷(POST)。我们将改变同时用户的数量,以查看servlet和反应式堆栈的行为。
该项目在这里可用https://github.com/raj-saxena/spring-boot-1-vs-2-performance
以下是我的发现:(我发现spring-boot web 1.5.10.RELEASE和spring-boot web 2.0.0.RELEASE的性能大多相似,因此只分享了spring-boot web 2.0.0.RELEASE vs spring-boot reactive-web-2.0.0.RELEASE的结果。我也在git repo中添加了我的运行报告)。
测试2500个同时用户
我们可以看到,在这个负载下,响应时间相似,但是反应式堆栈处理的请求数量是servlet堆栈的1.5倍以上。
SpringBoot 2 Servlet vs Reactive performance — 2500 users (4 requests/user)
SpringBoot servlet性能的报告此处,SpringBoot反应性能的报告此处。
测试5000个同时用户
SpringBoot 2 Servlet vs Reactive performance — 5000 users (4 requests/user)
现在开始变得清晰了,反应式堆栈在响应时间和它可以处理的请求数/秒方面都有更好的性能。
SpringBoot servlet性能的报告此处,SpringBoot反应性能的报告此处。
测试10000个同时用户
SpringBoot 2 Servlet vs Reactive performance — 10000 users (4 requests/user)
现在,我们可以看到,反应式堆栈是明显的赢家。
虽然反应式堆栈的性能略有下降,但是servlet堆栈的性能降低非常明显。在50th和75th百分位数的请求中,servlet堆栈的性能几乎下降了8-10倍。在多次运行中,servlet堆栈中的一些请求完全失败。
SpringBoot servlet性能的报告此处,SpringBoot反应性能的报告此处。
结论:
我们可以清楚地看到,反应式堆栈可以承受的负载而不会降低性能是一个显著的改进。它使我们能够更好地利用硬件,特别是对于那些执行大量I/O操作(如与其他服务进行网络调用或与数据库交互)的服务。它在低负载下具有类似的吞吐量,并快速处理高负载。这是一个巨大的胜利!然而,使用反应式流需要一定的学习曲线,还要确保没有开发者会调用block()
方法。另一个问题可能是缺乏反应式数据库驱动程序。JDBC本质上是阻塞的,目前仅有少数其他数据库(如MongoDB、Cassandra)官方支持反应式驱动程序。
请分享你的想法。
使用的硬件:处理器:2.3 GHz Intel Core i5内存:16 GB 2133 MHz LPDDR3显卡:Intel Iris Plus Graphics 640 1536 MB
我鼓励你自己尝试使用不同数量的用户进行实验,并分享结果。
注:捕获性能是一个非常详细和复杂的领域。它涉及许多可能影响结果的参数。在捕获之前,我多次运行了测试,以确保像JVM预热、字节码优化等不会影响结果。我尽量减少变量、简化实现,并尽可能保持测试条件的一致性。即使我指定了大量同时用户,实际每秒请求数也受限于我的硬件能力。但是,这确实可以让我们感受到这两个栈在压力下的表现。
评论(0)