记一次对象池引起的Tomcat卡死的事故

博客讲述了在项目中遇到浏览器加载慢且后台接口无法访问的问题。通过`jstack`命令发现大量线程处于WAITING状态,原因是Apache对象池大小不足且无等待超时设置。解决方案是调整对象池大小为50,并设置最大等待时间为5000毫秒。文章详细解释了对象池配置参数,包括最大空闲、最小空闲、最大活动对象数等,以避免线程池溢出。
摘要由CSDN通过智能技术生成

1. 先说情况:

浏览器访问项目一直转圈,出不来页面,后台接口也访问不了

2. 定位过程:

使用ps aux | grep java查询进程

Tomcat进程存在,查看日志没有报错,但是日志不再打印

根据进程pid查看服务的线程:jstack 19746

发现有大量WAITING的线程,定位到代码是从apache对象池获取对象的方法

进入到源码就发现有个获取最大等待时间的方法,进去一看默认值是-1

再检查了一下池子设置的大小,只有5

那就很明显了,对象池大小不够,导致超过5人请求时就会等待,而且没有等待超时时间,等待的线程多了就把Tomcat的线程池给撑爆了,因为是小型项目,看了一下WAITING的正好是200个,和Tomcat默认的线程池大小一致。

3. 解决方案:

因为项目同时使用的人数在20+人左右,设置对象池的大小为50,超时时间为5000毫秒

GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
// 50
poolConfig.setMaxIdle(threadPoolSize);
poolConfig.setMaxTotal(threadPoolSize);
poolConfig.setMinIdle(threadPoolSize);
// 5000
poolConfig.setMaxWaitMillis(maxWaitMillis);

顺便列一下对象池配置各个参数的含义:

public static class Config {  
	// 允许最大空闲对象数  
	public int maxIdle = GenericObjectPool.DEFAULT_MAX_IDLE;  
	// 允许最小空闲对象数  
	public int minIdle = GenericObjectPool.DEFAULT_MIN_IDLE;  
	// 允许最大活动对象数  
	public int maxActive = GenericObjectPool.DEFAULT_MAX_ACTIVE;  
	// 允许最大等待时间毫秒数  
	public long maxWait = GenericObjectPool.DEFAULT_MAX_WAIT;  
	// 当池中对象用完时,请求新的对象所要执行的动作  
	public byte whenExhaustedAction = GenericObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION;  
	// 是否在从池中取出对象前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个  
	public boolean testOnBorrow = GenericObjectPool.DEFAULT_TEST_ON_BORROW;  
	// 是否在向池中归还对象前进行检验,如果检验失败  
	public boolean testOnReturn = GenericObjectPool.DEFAULT_TEST_ON_RETURN;  
	// 连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除  
	public boolean testWhileIdle = GenericObjectPool.DEFAULT_TEST_WHILE_IDLE;  
	// 在空闲连接回收器线程运行期间休眠的时间毫秒数. 如果设置为非正数,则不运行空闲连接回收器线程  
	public long timeBetweenEvictionRunsMillis = GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;  
	// 设定在进行后台对象清理时,每次检查对象数  
	public int numTestsPerEvictionRun =  GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN;  
	// 被空闲对象回收器回收前在池中保持空闲状态的最小时间毫秒数  
	public long minEvictableIdleTimeMillis = GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;  
	// 被空闲对象回收器回收前在池中保持空闲状态的最小时间毫秒数  
	public long softMinEvictableIdleTimeMillis = GenericObjectPool.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS;  
	// 是否采用后进先出策略  
	public boolean lifo = GenericObjectPool.DEFAULT_LIFO;  
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值