当前位置: 首页 > 科技观察

是时候考虑Spring的非阻塞编程模式了

时间:2023-03-21 14:09:36 科技观察

介绍:在Spring框架中,有WebFlux、R2DBC等响应式模块,也有WebMVC、JDBC等阻塞式框架。在什么情况下应该使用不同的技术栈,很多技术人可能会感到困扰。本文作者对两种技术栈进行了详细的对比和压力测试,为技术选型提供支持。在2017年9月发布的SpringFramework5中,引入了SpringWebFlux。WebFlux是一个完全响应式的技术堆栈。2019年12月,发布了SpringDataR2DBC,这是一个响应式数据库驱动程序。在这篇文章中,我将证明WebFlux和R2DBC在高并发下表现更好。该组合具有更好的响应时间和吞吐量。在处理每个请求时使用更少的内存和CPU,你的FatJAR就会更小。高并发时最好使用WebFlux和R2DBC(如果不需要JPA)。测试方法在这篇文章中,我们尝试了以下四种组合:SpringWebMVC+JDBC数据库驱动SpringWebMVC+R2DBC数据库驱动SpringWebFlux+JDBC数据库驱动SpringWebFlux+R2DBC数据库驱动我设置了并行请求数,单位是50从4增加到500,为负载生成器和服务各分配4个内核(我的笔记本电脑有12个内核)。我配置的所有连接池都是100,为什么要固定核心数和连接池大小呢?由于在以前的JDBC和R2DBC测试中改变这些因素不会提供更多数据,因此我决定在此测试中保持变量固定,以减少需要运行时的测试数量。我在服务上模拟GET请求。该服务从数据库中提取10条记录并将它们作为JSON返回。首先,我为服务做了2秒的热身。接下来,我开始了1分钟的基准测试。我对每个场景运行了5次(按顺序,而不是5次之后是其他测试)并对结果进行平均。我只计算那些没有错误的测试。当我将并发数增加到1000以上时,所有实现都无一例外地失败了。我使用Postgres(12.2)作为数据库。并使用wrk进行基准测试。我使用以下方法来解析wrk的输出。关键测量:响应时间-来自Wrk测试报告吞吐量(请求数)-来自Wrk测试报告进程CPU使用-用户和内核时间(基于/proc/PID/Stat)内存使用-私有和共享进程内存(基于/proc/PID/maps)你可以看到这里使用的测试脚本[1]。您可以在此处查看使用的代码[2]。测试结果你可以在这里看到我在图表中使用的原始数据[3]。响应时间显然在高并发下,SpringWebMVC+JDBC未必是你最好的选择。显然,在更高的并发下,R2DBC可以提供更好的响应时间。SpringWebMVC和SpringWebFlux有相似的趋势。吞吐量和响应时间差不多,使用JDBC+SpringWebMVC在高并发下表现更差。同样,R2DBC显然表现更好。如果您的后端仍然使用JDBC,那么从SpringWebMVC迁移到SpringWebFlux也不是一个好主意。SpringWebMVC+JDBC在低并发时表现最好。CPUCPU是指整个运行过程中的CPU时间,即进程用户时间和内核时间之和。采用JDBC+WebMVC的方案,高并发CPU消耗最高。JDBC+WebFlux方案使用的CPU时间最少,但吞吐量也最低。当您查看每个请求使用的平均CPU时,您可以通过多种方式衡量CPU使用效率。与JDBC相比,R2DBC每个请求平均使用更少的CPU。使用JDBC+WebFlux似乎不是一个好主意。JDBC+WebMVC在高并发的时候比较差,而其他至少有一个非阻塞组件的实现比较稳定。但是在低并发的情况下,WebMVC+JDBC可以最有效地利用CPU。内存我们将进程私有内存测量为运行结束时的内存消耗。内存使用取决于垃圾收集。我们使用JDK11.0.6和G1GC。Xms设置为0.5Gb(默认为可用RAM的32Gb的1/64)。Xmx设置为8Gb(默认为32Gb可用RAM的1/4)。相比WebMVC,WebFlux的内存占用似乎更加稳定,后者在高并发时内存占用更大。使用WebFlux+R2DBC时,高并发下内存占用最小。在低并发时,WebMVC+JDBC内存使用率较低,但在高并发时,WebFlux+R2DB平均每个请求处理使用最少的内存。FatJarsizeJPA占据了下图中的大部分。如果你在使用R2DBC时不使用它,那么FatJAR大小将下降到15Mb左右!综上所述,R2DBC+WebFlux是高并发的好思路!在高并发时,使用R2DBC代替JDBC,使用WebFlux代替WebMVC,好处是显而易见的。处理单个请求所需的CPU更少。处理单个请求所需的内存更少。高并发时响应时间较低。高并发时更好的吞吐量更小的FatJAR(不使用JPA)。当只使用阻塞组件时,高并发下内存和CPU使用效率会降低。JDBC+WebFlux似乎不是一个好主意。R2DBC+WebMVC在高并发下比JDBC+WebMVC效果更好。您不需要完全非阻塞的堆栈来获得使用R2DBC的好处。但是,如果您正在使用Spring,最好将其与WebFlux结合使用。当并发量较低时(小于200个并发请求),使用WebMVC和JDBC可能会有更好的效果。测试以确定平衡。使用R2DBCJPA时的一些挑战无法处理SpringDataR2DBC提供的响应式功能。这意味着您在使用R2DBC时必须手动完成更多工作。还有其他反应式驱动程序,例如QuarkusReactivePostgres客户端(使用Vert.x)。它们不使用R2DBC并且具有不同的性能特征。可用性有限并非所有关系数据库都有反应驱动程序。例如,Oracle还没有R2DBC实现。应用服务器仍然依赖于JDBC。在这个Kubernetes时代,人们还在使用那些古老的功能吗?当JavaFibers出来时(ProjectLoom,可能是Java15),数据库驱动的格局可能会再次发生变化,R2DBC可能不会成为JDBC的继任者。原文地址:https://technology.amis.nl/2020/04/10/spring-blocking-vs-non-blocking-r2dbc-vs-jdbc-and-webflux-vs-web-mvc/文中链接:[1]https://github.com/MaartenSmeets/db_perftest/blob/r2dbc/test_scripts/run_test.py[2]https://github.com/MaartenSmeets/db_perftest/tree/r2dbc/test_apps[3]https://github.com/MaartenSmeets/db_perftest/blob/r2dbc/test_scripts/restotal.txt本文转载自微信公众号“高可用架构”,可通过以下二维码关注。转载本文请联系高可用架构公众号。