遇到tomcat莫名其妙无法响应,但是内部日志文件看是有正常打印日志的, 这就是假死情况.

假死的情况无非几种:

  • redis的连接池资源没释放掉(tcp没释放掉,tcp状态为close_wait)

  • 数据库连接池资源没释放掉(tcp没释放掉,tcp状态为close_wait)

  • 上传文件资源没关闭掉 (tcp没释放掉,tcp状态为close_wait)

  • httpclient请求没关闭掉 (tcp没释放掉,tcp状态为close_wait)

  • 线程死锁

  • 线程被阻塞了,没继续往下执行

tomcat请求超210个,无法继续服务

检查linux连接情况

ps aux | grep tomcat
ps -T -p pid |wc -l

redis连接超限

Redis cluster的最大连接数 = (单个分片的max_clients * 分片数)

查看redis最大连接数, 最大10000,当前有374个,完全没问题.

> info clients
# Clients
connected_clients:374
cluster_connections:0
maxclients:10000
client_recent_max_input_buffer:72
client_recent_max_output_buffer:0
blocked_clients:0
tracking_clients:0
clients_in_timeout_table:0

> config get maxclients
1) "maxclients"
2) "10000"

调试查看:

dispatcherServlet进入请求,这一步看来tomcat请求是没问题的.

卡在了拦截器中

内部使用redis存储token.深入进去使用了redis获取token值,

项目中使用的jedis, 进入JedisConnectionFactory 查看获取连接方法.

发现redis连接满了

进入pool.getResource()方法看怎样获取连接的.

如果blockWhenExhausted 为true,则连接最大时,将阻塞获取连接.

当前超过了最大数8个.

检查配置,发现用的不对,因为没使用jedis配置,所以创建了默认最大8,无限阻塞的连接池

为什么没有释放连接,导致超过8个,发现有个定时任务使用了redisTemplate.scan,使用后未关闭,导致连接未释放

修改代码,增加try{}catch()并在return前,关闭cursor, 并修改配置文件

  redis:
    host: 172.17.97.0
    port: 9736
    password: FA86D62022
    database: 2
    jedis:
      pool:
        enabled: true
        # 连接池最大连接数
        max-active: 200
        # 连接池最大阻塞等待时间(使用负值表示没有限制)
        max-wait: 6000
        # 连接池中的最大空闲连接
        max-idle: 200
        # 连接池中的最小空闲连接
        min-idle: 10
        # 空闲对象驱逐时间间隔
        time-between-eviction-runs: 5000

修改完毕后,观察测试环境运行半个小的JVM快照, 查看jvm堆情况,连接对象没有超2个

文章作者: 刘同学
本文链接:
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 刘同学的小站
后端 Java
喜欢就支持一下吧