记一个腾讯信鸽引发的线程卡死问题

本文介绍了一款游戏因第三方SDK导致大量玩家无法进行自动战斗等问题的排查过程。通过分析发现,SDK调用HTTP请求时未能正确处理读超时,最终通过调整系统变量并在合适时机设置读超时来解决问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一天公司的游戏有大量玩家报自动战斗、种植等操作无法进行,第一时间想到可能是因为玩家的定时任务线程卡死了。用jstack查看线程堆栈日志,发现都卡在了一个http read的地方。

公司使用腾讯信鸽做手游的系统推送,卡住的地方就是调用信鸽的服务端sdk向信鸽服务器发送http请求,并等待回应的时候。

因为是调用第三方jar包,所以无法直接设置读超时。在网上搜索到一种方法是通过系统变量设置超时时间:

 System.setProperty("sun.net.client.defaultReadTimeout", 3000);

测试过有效之后上线。

本以为万事大吉了。结果过了一段时间又报出大量玩家无法自动战斗,后面一看还是这个问题。

说明设置的系统变量并未生效。

于是在线下详细测试,发现一个奇怪的问题:在两个不同的工程中设置这个系统变量,一个是有效的,一个是无效的。

不过能够复现问题就是件好事。查看堆栈对应的jdk源码,发现是sun包下的,不开源。再找到openjdk源码,研究后发现是NetworkClient的static代码块的执行时机的问题。

原来java在第一次生成http请求时,会从系统变量sun.net.client.defaultReadTimeout读取默认读超时时间并放在缓存里,以后即使修改了这个系统变量,也不会影响默认读超时时间了。

知道了问题的原因,那就知道解决办法了:将默认读超时设在程序的起始位置,或者启动脚本中

后面向腾讯信鸽写邮件反映这个问题。在最新版的SDK中看到已经得以修正。

总结:

  1. 使用http请求一定要设置连接超时和读超时,否则网络一出问题就会卡死。
  2. 在涉及第三方类库时使用单独的线程池,与业务线程池分离。因为你永远不知道里面会有什么未知的问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值