内网sandbox环境API持续一周出现应用卡死现象,所有API无响应。最初重启应用后问题缓解,但后来问题愈发频繁,引发同事不满。开始怀疑是代码问题,进行排查。发现本地IDE未显示问题,应用卡死期间数据库、Redis均正常运行,无异常日志。怀疑是测试环境问题。通过执行top命令查看服务器状态,执行top -H -p 12798定位占用资源较高的线程,使用jstack查看堆内存情况。观察线程状态,执行redis命令时发现部分线程处于lock状态。尝试dump问题进程堆内存,并在debug模式下重启测试环境应用。问题再现时,运维人员将问题应用移除,远程debug tomcat。随意选择接口,在API入口断点未触发,冷静后在接口前的AOP处设置断点,发现API等待服务响应。在执行redis命令时卡住。检查Jedis代码,发现pool.getResource()后线程开始wait,return内部池中borrowObject()的代码导致问题。发现配置MaxWaitMillis未设置,配置后仍存在问题。继续追踪,发现大量http-nio线程处于waiting状态。通过thread命令发现大量线程等待释放锁的对象53e5504e,执行jstack全局搜寻未找到该对象。确认问题原因源于Redis连接获取问题。配置获取连接超时时间,等待问题复现,通过tomcat accesslog发现大量API请求出现500错误。追踪首次出现500错误的位置,发现stringRedisTemplate.getConnectionFactory().getConnection()获取pool中的redisConnection后未进行后续操作。Redis连接被租赁但未释放或退还到连接池,导致pool中的redisConnection状态未回到idle状态。分析原因,spring的stringRedisTemplate对Redis常规操作进行封装,不支持某些特殊命令,需要通过Jedis连接进行。使用不当可能导致问题。建议合理配置Redis pool,避免出现问题无错误日志、无报错的情况。同时,避免使用keys命令,合理配置pool以提高问题定位效率。总结,通过排查发现Redis连接获取问题导致应用卡死。关键在于合理配置和使用Redis pool,避免使用不当引发的隐藏问题。