服务器配置:
cpu:4核4线程
cpu单核主频:2.2GHz
模拟每个请求增加200ms时延:
@RequestMapping(path = "index2")
public Mono<String> index2(ServerWebExchange exchange) {
return Flux.fromIterable(list).last().publishOn(Schedulers.parallel()).delayElement(Duration.ofMillis(200));
}
压力测试命令:
在局域网另一台ip为192.168.220.99的服务器执行
ab -c1000 -n50000 http://192.168.220.100:9999/reactive/index2
测试结果:
1千并发用户,5万个请求,TPS达到4421.90
请勿用响应式框架和阻塞io一起使用,会严重降低性能,例如spring webflux+jdbc的性能比spring mvc+jdbc要差。
spring webflux默认使用reactor-netty框架,启动时反应堆线程数量和CPU线程数量相同,随着连接增加,反应堆线程数量不会增加,若线程被阻塞,反应堆线程池可能会出现无线程可用的情况,可以在controller层publishOn切换到worker线程池,但是阻塞io也会降低worker线程的工作效率,所以更好的方式是使用基于nio的组件,例如r2dbc、WebClient等。
所以对webflux进行测试模拟时延得使用delayElement,而不是用Thread.sleep。
程序执行过程中spring data r2dbc会把当前请求切换到它的线程池,整个过程可能由多个线程来完成,数据库事务依然是有效,使用Flux.usingWhen来控制事务。