线程夯死的排查及解决

最近做的业务一直是和第三方交互的业务,为了加快速度,基本上都是采用多线程,然而时不时总是发生一些推送任务莫名的卡死,知道前几天的一次发现,让我开始了线程的排查之路,希望对大家的有一定的启发和借鉴

一:分布式锁导致的线程夯死

问题的发生是小伙伴突然和我说线上的数据推送任务不推送了,于是我基于对自己的代码信任,觉得不可能,(其实以前也发生过这样的问题,大多是代码中涉及的redis队列超时导致,不过我已经优化了一个版本,觉得不可能还有这样的问题,这时候小伙伴说重启吧,但是我想了想之前也遇到过这种灵异现象,这一次上头了,感觉事情没那么简单,于是我开始了排查之路

1.发现线程夯死

日志系统显示下午的15:30,google的推送线程(gg_push_47)捞取了数据打了日志就卡住了,初步怀疑线程夯死
在这里插入图片描述

2.确认线程夯死

于是根据ip找到了具体的pod,以及里面的自主排障里的Arthas控制台,查询到了线程处于TIMED_WAITING,注意我配图的Arthas线程已经不是当时的线程了(gg_push_47),因为当时忘记截图了,所以随手找了一个,用来代表线程当时的状态

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

3.排查夯死原因

问题已经定位到了,于是找到了运维打了jstack日志(因为我没服务器权限。。。)可以看到gg_push_47夯死在了jedis的一个lock操作上面,而最后一次业务当法则是getToken
在这里插入图片描述
getToken中恰好也存在利用公司架构封装的redis使用的分布式锁,于是我们看看.getToken操作redis
到底做了啥

在这里插入图片描述

到这里其实原因就很清晰了,lock这个方法设置的锁,锁持有超时和锁等待时间都是-1,也就是永久
那么假设A线程调用 getToken但是由于释放锁的时候出现了redis超时的问题,也就是finally这段代码异常了,那么A线程由于锁永远持有,所以B线程(gg_push_47)由于设置的锁等待时间是-1,那么B线程虽然获取不到锁,但是也会永远等待,导致了线程的夯死

4.结论

分布式锁一定要设置锁超时和锁等待时间,如果不确定时间的值,那么可采用看门狗机制,我这里是维护之前的代码,没办法。。都是坑啊

二:网络请求不设置超时时间导致的线程夯死

问题的发生是小伙伴又和我说线上的数据推送任务不推送了,不过这次从google换成了facebook,tm的分布式锁搞定了啊,而且facebook没用分布式锁,设置任何JUC到LOCK都没,怎么可能会被夯死呢,这时候小伙伴又说重启吧,但是我又一次上头了,于是再次踏上排查之路。。。

1.确认线程夯死

有了上次的经验我直接拿到了停止推送的线程,发现不同于上次的等待这次一直处于runnable状态
在这里插入图片描述

在这里插入图片描述

2.排查夯死原因

于是又找到了运维打了jstack日志(运维累了。。。)可以看到fb_push_44夯死在fb的网络请求中在这里插入图片描述
绿色的是我的最后一次交互业务代码,红色的为facebook-sdk封装的网络请求的api,可以发现问题出现在读取respose,初步怀疑是没有设置超时时间,于是我看了一下源码发现真的没有设置超时时间

1.发现连接对象是HttpsURLConnection,set方法并为设置任何超时时间参数,去看看具体的的属性有无默认值
在这里插入图片描述
2.发现JDK提供的HttpsURLConnection初始化时间都是0,即永不超时,而SDK中也为设置,所以也就导致了线程夯死
在这里插入图片描述

3.结论

任务网络请求,一定要设置超时时间,否则就是坑啊。。。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值