Oracle的最大并发数由PROCESSES和SESSIONS决定,归根结底由操作系统和硬件配置决定。

根据对Tomcat、Druid、Oracle三者的与并发相关的参数进行了解,结合经验和网上的部分说法后,得出如下数据:

  1. Tomcat的单机并发最大线程数为500到700。
  2. Druid数据库连接池的推荐配置最大并发数(maxActive)为20.
  3. Oralce的最大进程数(PROCESSES)为300,最大SESSIONS为300 * 1.5 + 22 = 477 (这个公式对应Oracle 11g版本)
  4. Nginx在windows上的最大并发数为1024,在linux为8192.(受限于文件系统的最大文件打开数)。

基于以上数据,进行推测:

数据库最大并发 = 300
数据库可以支持的连接池个数 = 477 / 20 = 23
23个连接池对应23个Tomcat,可以支撑的线程数:
23 * 500 = 11500个线程

也就是,数据库按照PROCESSES=300的配置来的话,可以压榨的极限是11500并发。这里补充一点,对于Spring框架的Web应用来说,Spring会用一个线程来处理一次用户请求(注意是一次请求,不是一次会话),处理完一次请求后,线程即回到等待状态,等待下一次请求调用。

所以11500个并发并不代变11500个用户,具体要看实际场景中一个用户的单位时间访问量。


下面来验证以上推测。

环境准备:
  • 服务器:
  • 4核8G5M带宽阿里云服务器 * 3
  • 4核4G5M带宽阿里云服务器 * 2
  • 测试客户端:
  • 4核8G笔记本
  • Tomcat线程池配置
  • maxThreads=500
  • accept=400
  • maxConnection=800

5个服务器上分散部署了共13个Tomcat和1个Nginx

首先,按照7500线程在70秒内全部发起请求,得到的结果是:前面十秒左右一切正常,10秒过后nginx开始大量请求无法响应(failed to response),原因是nginx所在的windows服务器限制了最大文件打开数量为1024,也就是限制了nginx的并发数为1024.

马上把nginx转移到linux上,其他不变。

此时,按照7500线程70秒内发起的结果如下:

线程数

时间

发出请求

平均响应

95%响应

错误率

吞吐量

数据库平均cpu%

数据库峰值cpu%

3750*2

54s

7499

12721ms

60147ms

15.12%

40.8/s

60%

100%

3750*2

54s

7498

13753ms

60358ms

13.27%

61.8/s

66%

100%

5750*2

83s

11490

15669ms

60384ms

15.97%

56.4/s

76%

100%

5750*2

83s

11489

19229ms

60376ms

31.3%

78.4/s

50%

100%

5750*2

83s

11489

19037ms

60313ms

36.3%

67.56/s

60%

100%

说明:线程数乘2的原因是测试脚本包含两个请求,分别是登录请求和加载阅卷页面的请求。

根据压测过程中的监控,错误率里面85%来自登录请求的连接超时错误。正常情况下,这个系统的登录请求耗时1到1.5秒左右,并发场景下更严重。

由于这次部署的Tomcat实例数是13个,每个Tomcat的最大线程数是500,最大同时active的线程数就是7500,离预估的数据库最大承受值11500还差一点。凑齐20多个Tomcat的工作量太大,就不继续压榨Oracle了。基于已有的测试结果,基本可以验证上面的推测。