记一个腾讯信鸽引发的线程卡死问题
2017-07-22 19:12
615 查看
一天公司的游戏有大量玩家报自动战斗、种植等操作无法进行,第一时间想到可能是因为玩家的定时任务线程卡死了。用jstack查看线程堆栈日志,发现都卡在了一个http read的地方。
公司使用腾讯信鸽做手游的系统推送,卡住的地方就是调用信鸽的服务端sdk向信鸽服务器发送http请求,并等待回应的时候。
因为是调用第三方jar包,所以无法直接设置读超时。在网上搜索到一种方法是通过系统变量设置超时时间:
测试过有效之后上线。
本以为万事大吉了。结果过了一段时间又报出大量玩家无法自动战斗,后面一看还是这个问题。
说明设置的系统变量并未生效。
于是在线下详细测试,发现一个奇怪的问题:在两个不同的工程中设置这个系统变量,一个是有效的,一个是无效的。
不过能够复现问题就是件好事。查看堆栈对应的jdk源码,发现是sun包下的,不开源。再找到openjdk源码,研究后发现是NetworkClient的static代码块的执行时机的问题。
原来java在第一次生成http请求时,会从系统变量
知道了问题的原因,那就知道解决办法了:将默认读超时设在程序的起始位置,或者启动脚本中。
后面向腾讯信鸽写邮件反映这个问题。在最新版的SDK中看到已经得以修正。
总结:
使用http请求一定要设置连接超时和读超时,否则网络一出问题就会卡死。
在涉及第三方类库时使用单独的线程池,与业务线程池分离。因为你永远不知道里面会有什么未知的问题。
公司使用腾讯信鸽做手游的系统推送,卡住的地方就是调用信鸽的服务端sdk向信鸽服务器发送http请求,并等待回应的时候。
因为是调用第三方jar包,所以无法直接设置读超时。在网上搜索到一种方法是通过系统变量设置超时时间:
System.setProperty("sun.net.client.defaultReadTimeout", 3000);
测试过有效之后上线。
本以为万事大吉了。结果过了一段时间又报出大量玩家无法自动战斗,后面一看还是这个问题。
说明设置的系统变量并未生效。
于是在线下详细测试,发现一个奇怪的问题:在两个不同的工程中设置这个系统变量,一个是有效的,一个是无效的。
不过能够复现问题就是件好事。查看堆栈对应的jdk源码,发现是sun包下的,不开源。再找到openjdk源码,研究后发现是NetworkClient的static代码块的执行时机的问题。
原来java在第一次生成http请求时,会从系统变量
sun.net.client.defaultReadTimeout读取默认读超时时间并放在缓存里,以后即使修改了这个系统变量,也不会影响默认读超时时间了。
知道了问题的原因,那就知道解决办法了:将默认读超时设在程序的起始位置,或者启动脚本中。
后面向腾讯信鸽写邮件反映这个问题。在最新版的SDK中看到已经得以修正。
总结:
使用http请求一定要设置连接超时和读超时,否则网络一出问题就会卡死。
在涉及第三方类库时使用单独的线程池,与业务线程池分离。因为你永远不知道里面会有什么未知的问题。
相关文章推荐
- Debug 模式 和 Release 模式下,一个线程在"编译"上引发的问题
- 关于linux线程实时信号的一个问题
- 再谈HashMap-由一个实际问题引发的对HashMap设计吐嘈
- 由一个问题引发的思考——关于数据库的外键约束
- 一个distinct问题引发的思考
- 一个JDK版本问题引发的思考--Java环境配置 && Eclipse的JDK配置
- 一个Java NIO问题引发的思考
- 一个小问题引发的"Listview里有多个Edittext,点击一个全部都高亮"
- 一个JavaScript问题引发的思考
- 遇到一个因socket未关闭引发的文件句柄用完问题
- 由安卓开发中的一个坑引发的问题解决之道浅析
- 安装2K可能引发一个严重问题
- 细节:一个很SB的问题引发的思考
- 一个office未激活引发的问题
- 一个content-type引发的问题
- eclipse-调试的一个问题:到了断点那里,不过step over 无效,即F6、F5z无效,原因是没有在debug视图中选中当前线程
- 关于一个登录引发的session域配置的问题
- 同一目录两程序引用同一个类库dll,所引发的问题
- 一个粗心的问题引发的思考
- InputStreamReader引发的一个编码问题