# 性能测试

参考博客：[https://blog.csdn.net/get\_set/article/details/79492439](https://lxdd.gitbook.io/spring-webflux/webflux/xing-neng-ce-shi)

上边我们分别针对[Http服务端](http://blog.csdn.net/get_set/article/details/79492439)、[Http客户端](http://blog.csdn.net/get_set/article/details/79506373)以及数据库进行了同步和异步的测试对比，综上来看，**基于异步非阻塞的响应式应用或驱动能够以少量且固定的线程应对高并发的请求或调用，对于存在阻塞的场景，能够比多线程的并发方案提供更高的性能。**

响应式和非阻塞并不是总能让应用跑的更快，况且将代码构建为非阻塞的执行方式本身还会带来少量的成本。但是在类似于WEB应用这样的高并发、少计算且I/O密集的应用中，响应式和非阻塞往往能够发挥出价值。尤其是微服务应用中，网络I/O比较多的情况下，效果会更加惊人

增加Servlet容器处理请求的线程数量可以缓解这一问题，就像上边把最大线程数量从默认的200增加的400。

最高200的线程数是Tomcat的默认设置，我们将其设置为400再次测试。

由于工作线程数扩大一倍，因此请求排队的情况缓解一半，具体可以对比一下数据：

1. “最大线程数200用户5000”的“95%响应时长”恰好与“最大线程数400用户10000”完全一致，我对天发誓，这绝对绝对是真实数据，更加巧合的是，吞吐量也恰好是1:2的关系！有此巧合也是因为测试场景太简单粗暴，哈哈；
2. “95%响应时长”的曲线斜率也是两倍的关系。

这也再次印证了我们上边的分析。增加线程数确实可以一定程度下提高吞吐量，降低因阻塞造成的响应延时，但此时我们需要权衡一些因素：

* 增加线程是有成本的，JVM中默认情况下在创建新线程时会分配大小为1M的线程栈，所以更多的线程异味着更多的内存；
* 更多的线程会带来更多的线程上下文切换成本。

我们再来看一下对于`WebFlux-with-latency`的测试数据：

![](https://leanote.com/api/file/getImage?fileId=5a977ae5ab644112c2000ae7)

* 这里没有统计线程数量，因为对于运行在异步IO的Netty之上的WebFlux应用来说，其工作线程数量始终维持在一个固定的数量上，通常这个固定的数量等于CPU核数（通过jconsole可以看到有名为`reactor-http-nio-X`和

  `parallel-X`的线程，我这是四核八线程的i7，所以`X`从1-8），因为异步非阻塞条件下，程序逻辑是由事件驱动的，并不需要多线程并发；
* 随着用户数的增多，吞吐量基本呈线性增多的趋势；
* 95%的响应都在100ms+的可控范围内返回了，并未出现延时的情况。

可见，非阻塞的处理方式规避了线程排队等待的情况，从而可以用少量而固定的线程处理应对大量请求的处理。

> 除此之外，我又一步到位直接测试了一下20000用户的情况：\
> 1\. 对`mvc-with-latency`的测试由于出现了许多的请求fail而以失败告终；\
> 2\. 而`WebFlux-with-latency`应对20000用户已然面不改色心不慌，吞吐量达到7228 req/sec（我擦，正好是10000用户下的两倍，太巧了今天怎么了，绝对是真实数据！），95%响应时长仅117ms。

最后，再给出两个吞吐量和响应时长的图，更加直观地感受异步非阻塞的WebFlux是如何一骑绝尘的吧：

![](https://leanote.com/api/file/getImage?fileId=5a977e7dab644114e4000b42)![](https://leanote.com/api/file/getImage?fileId=5aa1da6eab644172e50002f1)

此时，我们更加理解了Nodejs的骄傲，不过我们大Java语言也有了**Vert.x**和现在的**Spring WebFlux**。
