简单不先于复杂
而是在复杂之后

记录一次由于线程使用不当引发的血案

背景

最近给第三方做了一个接口,接口的作用是接收数据对数据进行验证之后通过kafka推送到模型进行数据处理,最终通过kafka接收模型的数据,开始只做了一个异步的接口,由于对方业务原因需要一个同步的接口传输数据,但是每当运行一段时间之后程序就会进入假死状态,接口无法正常调用;

同步接口

同步接口的实现是使用阻塞Map,当对方发送请求时,对数据进行验证,然后推送到模型,等待结果返回之后将处理好的数据推送到对方接口,此时这次请求给调用方返回相应信息;

思路

开始认为是由于用户量过大导致内存不足引发的程序假死,使用JMeter进行压力测试异步接口模拟10000个请求同时调用接口,程序如丝滑般运行,没有丝毫问题,所有请求都正常返回(这里由于在家里通过VPN连接的公司开发服务器,网络不稳定,所以就拿少量测试用例为例);

然后开始怀疑是不是同步接口出了问题,刚开始模拟少量请求,因为当时是在开发环境进行测试,模型并没有放上去,所以没有返回信息,一直在等待模型的返回结果,也是没有问题的,这时候调用异步接口也没有任何问题;

思考:所有资源都是阻塞状态,因为没有处理结果,一直没有释放进程,当数据过大时会不会造成服务器资源耗尽,导致程序假死?

当再次加大同步接口的调用次数的时候,再去尝试请求异步接口,发现异步接口也没有了返回信息,这时遍确认了问题所在;

线程全部在阻塞状态,当太多资源没有释放掉时,服务器资源耗尽,导致程序无法正常运行;

解决

找到问题之后就是要解决问题,去掉同步接口是不可能的,所以要给阻塞的线程设置一个超时时间,当长时间没有等到模型的处理数据时,主动放弃监听,释放掉占用的资源,从而保证服务器资源充足;

思考

虽然问题解决了,但是模型的数据产出最长达10秒钟,当并发量过大时还是会出现这种问题,在不动模型的情况下如何解决这种问题?如何一直保证服务器资源充足?

参考资料

阻塞Map的实现:https://songsong.iteye.com/blog/802881

压力测试简介和JMeter的简单实用:https://www.cnblogs.com/TankXiao/p/4059378.html

posted @ 2019-08-20 22:48  Jacian  阅读(180)  评论(0编辑  收藏  举报