一个使用高并发高线程数 Server 使用异步数据库客户端造成的超时问题
现象
今天在做一个项目时, 将 tomcat 的 maxThreads 加大, 加到了 1024, tomcat 提供的服务主要是做一些运算, 然后插入 redis, 查询 redis, 最后将任务返回给客户端
在做压测时, 同时开了 1000 个线程, 并发发起 http 请求去访问 tomcat 的服务, 结果在第一次访问 tomcat 时出现了一系列的 redis 查询超时, 例如 1000 个并发发起 10W 次请求, 可能头 1W 次请求会有 2000 次左右的 redis 超时造成服务失败, 但是之后就再不会出现 redis 超时的情况.
解决
通过观察 vmstat, 发现在出现超时时, r (运行队列) 特别高, 达到 12~25, 持续时间为 2~3 秒, 这段时间出现了很多 redis 超时. 而以后不出现超时时, r 值都保持在 5 左右. 此时, 通过缩减 tomcat 线程数, 减到 200, 再重新测试, 则没有出现超时.
分析
这是因为我的 redis 客户端是异步客户端, 但是我在使用它的时候是用异步客户端模拟同步客户端执行(调用 future.get()), 客户端内部使用 netty 实现, netty 的工作线程只有 4 或 8 个. 当我们刚启动 tomcat 服务时, 没有预热, 系统性能较差, 此时排队任务多的话, 会让巨大的 tomcat 业务线程(1024个)占据 cpu 的任务队列, 而 netty 工作线程较少, 得不到 cpu 时间执行, 最后造成超时.
这里最大的问题在于在同步的 tomcat 业务代码中使用了异步的 redis 客户端, 因为 tomcat 业务线程数量大, 占据了大量 cpu 时间, 让 redis 客户端线程得不到执行, 最后导致了问题出现.
如果说这里将 tomcat 的业务处理改为异步处理 (使用 servlet 3.0), 那么则可以大量缩减 tomcat 的业务线程, 这样既可以减少业务线程切换, 又可以让 redis 客户端线程得到更多的执行时间.
延伸
抛开使用异步的 redis 客户端不说, 如果使用的是一个传统的同步 db 客户端, 那么 db 客户端的执行线程就是业务线程, 线程的 cpu 时间是均等的, 则不会出现这个超时的问题. 那么应该如何界定何时应该启用多少线程?
当我们的业务线程内有 io 操作, 例如 mysql 的操作时, 如果这个操作很耗时, 例如需要执行 2s, 我们则应该分配更多地线程. 假设此时并发 1000 请求, 而只有 8 个业务线程, 那么这 8 个业务线程只能执行 8 个任务, 而且因为实在等待 mysql 的 io 返回, cpu 此时处于闲置状态, 另外的 992 个请求因为没有线程执行, 只能排队等待. 所以此时如果分配更多的业务线程, 则可以更有效地利用 cpu 资源.
而如果业务处理是 cpu 密集型的, 则应该使用更少的线程. 因为此时 cpu 会处于繁忙状态, 增加更多地线程也不会让线程得到执行时间片, 反而会增加线程切换的开销.
总结
对于我的业务场景, 最好的方式应该是减少业务线程, 并将业务处理使用 servlet 3.0 改为全异步的方式. 原因是因为使用的是异步的 redis 客户端, 它不会让线程处于闲置的等待状态, 这样既能减少线程切换, 又能合理的分配 tomcat 业务线程与 redis 客户端线程的执行时间片.
一个使用高并发高线程数 Server 使用异步数据库客户端造成的超时问题的更多相关文章
- 转载:IIS 之 连接数、并发连接数、最大并发工作线程数、队列长度、最大工作进程数
一.IIS连接数 一般购买过虚拟主机的朋友都熟悉购买时,会限制IIS连接数,顾名思义即为IIS服务器可以同时容纳客户请求的最高连接数,准确的说应该叫“IIS限制连接数”. 客户请求的连接内容包括: [ ...
- IIS 之 连接数、并发连接数、最大并发工作线程数、队列长度、最大工作进程数
一.IIS连接数 一般购买过虚拟主机的朋友都熟悉购买时,会限制IIS连接数,顾名思义即为IIS服务器可以同时容纳客户请求的最高连接数,准确的说应该叫“IIS限制连接数”. 客户请求的连接内容包括: [ ...
- 高并发&高可用系统的常见应对策略 秒杀等-(阿里)
对于一个需要处理高并发的系统而言,可以从多个层面去解决这个问题. 1.数据库系统:数据库系统可以采取集群策略以保证某台数据库服务器的宕机不会影响整个系统,并且通过负载均衡策略来降低每一台数据库服务器的 ...
- PHP高并发高负载系统架构
PHP高并发高负载系统架构 1.为什么要进行高并发和高负载的研究 1.1.产品发展的需要 1.2.公司发展的需要 1.3.当前形式决定的 2.高并发和高负载的约束条件 2.1.硬件 2.2.部署 2. ...
- java处理高并发高负载类网站的优化方法
java处理高并发高负载类网站中数据库的设计方法(java教程,java处理大量数据,java高负载数据) 一:高并发高负载类网站关注点之数据库 没错,首先是数据库,这是大多数应用所面临的首个SPOF ...
- IIS:连接数、并发连接数、最大并发工作线程数、应用程序池的队列长度、应用程序池的最大工作进程数详解
Internet Information Services(IIS,互联网信息服务),是由微软公司提供的基于运行Microsoft Windows的互联网基本服务.最初是Windows NT版本的可选 ...
- [转]java处理高并发高负载类网站的优化方法
本文转自:http://www.cnblogs.com/pengyongjun/p/3406210.html java处理高并发高负载类网站中数据库的设计方法(java教程,java处理大量数据,ja ...
- IIS最大并发连接数 = 队列长度 + IIS最大并发工作线程数
深入理解IIS的多线程工作机制 首先让我们来看看IIS里面的这2个数字:最大并发连接数,队列长度.先说这2个数字在哪里看. 最大并发连接数:在IIS中选中一个网站,右键网站名称,在右键菜单中找到并 ...
- IIS连接数、IIS并发连接数、IIS最大并发工作线程数、应用程序池的队列长度、应用程序池的
IIS连接数 一般购买过虚拟主机的朋友都熟悉购买时,会限制IIS连接数,这边先从普通不懂代码用户角度理解IIS连接数 顾名思义即为IIS服务器可以同时容纳客户请求的最高连接数,准确的说应该叫" ...
随机推荐
- HTML5外包
北京动点飞扬软件 从事html5外包业务五年,是国内第一家以HTML5移动平台.手机平台项目外包业务为主的正规软件团队, 欢迎联系 QQ:372900288 电话:13911652504 我们现已发展 ...
- 《C#编程风格》还记得多少
开始实习之后,才发现自己是多么地菜.还有好多东西还要去学习. 公司很好,还可以帮你买书.有一天随口问了一下上司D,代码规范上面有什么要求.然后D在Amazon上面找到了这本书<C#编程风格(Th ...
- perl读取文件
1)文件读取的3中方法 按行读,存入标量 while (<FILE>) { print; } 按行读,存入数组 @array = <FILE>; 读入整个文件 ,存入标量 ...
- RFC3986编码 C 语言实现(支持大部分中文)
前些时间做 xauth 认证程序的编写,网上找到RFC3986编码不支持中文的编码,所以便查找了一些资料.自己写了一个,代码如下. #include <stdlib.h> #include ...
- Storm Topology及分组原理
Storm的通信机制,需要满足如下一些条件以满足Storm的语义. 1.建立数据传输的缓冲区.在通信连接没有建立之前把发送的数据缓存起来.数据发送方可以在连接建立之前发送消息,而不需要等连接建立起来, ...
- Hibernate工作原理
现在我们知道了一个概念Hibernate Session,只有处于Session管理下的POJO才具有持久化操作能力.当应用程序对于处于Session管理下的POJO实例执行操作时,Hibernate ...
- JavaScript list 去重复
function unique(arr) { var result = [], hash = {}; for (var i = 0, elem; (elem = arr[i]) != null; i+ ...
- C#_GDI+详细教程(图形图像编程基础)
第7章 C#图形图像编程基础 本章主要介绍使用C#进行图形图像编程基础,其中包括GDI+绘图基础.C#图像处理基础以及简单的图像处理技术. 7.1 GDI+绘图基础 编写图形程序时需要使用GDI( ...
- c语言 sscanf()函数
sscanf()函数用于从字符串中读取指定格式的数据,其原型如下: int sscanf (char *str, char * format [, argument, ...]); [参数]参数 ...
- delphi 10 seattle 安卓服务开发(二)
关于delphi 10 移动服务开发的几张图