Oracle的最大并发数由PROCESSES和SESSIONS决定,归根结底由操作系统和硬件配置决定。
根据对Tomcat、Druid、Oracle三者的与并发相关的参数进行了解,结合经验和网上的部分说法后,得出如下数据:
- Tomcat的单机并发最大线程数为500到700。
- Druid数据库连接池的推荐配置最大并发数(maxActive)为20.
- Oralce的最大进程数(PROCESSES)为300,最大SESSIONS为300 * 1.5 + 22 = 477 (这个公式对应Oracle 11g版本)
- 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了。基于已有的测试结果,基本可以验证上面的推测。