现象:
之前工作中遇到一个场景:对一个通过端口监听的方式接收设备日志入库的功能进行长时间日志接收测试(200条/s)的时候,总是会在不停接收日志一天左右的时间后,突然暴毙,必须要通过重启服务器的方式才能够恢复。
定位过程:
一开始的反应是内存OOM了,但是日志上没有任何有效的错误的信息记录。并且之后通过jconsole监控的方式发现内存占用等一直是保持在一个正常的区间(过程中没有内存泄漏的情况)。
最后通过对tomcat的日志分析中发现了端倪。在查看tomcat的catalina日志以及localhost日志的时候,发现其记录了一个比较明显的错误信息——Too many open files
赶紧面向百度编程了一下后发现,这个问题是因为Linux系统句柄数耗尽引起的
查询资料后发现,正常程序的运行中,http请求建立连接的过程中会占用系统的句柄数,
但是会随着连接的关闭而释放。
然后排查后发现有一个远古流传下来的HttpUtil类中的一个post请求方法在请求结束后并没有关闭client连接,
而该日志接收功能在存库后会有一个http请求回调,恰好调用了这个post方法!然后又因为这个功能会持续的大量的请求,导致最后没有关闭的连接越来越多最终占满了Linux系统句柄,导致了服务器崩溃。
总结:
1.httpclient用完就关闭连接这个是常识就不多说了。
2.当出现服务器挂了的问题时,如果工程记录的日志中没有明显的错误信息,也可以去tomcat的日志中去寻找问题。因为有些可能是系统出现的问题往往不会被我们自己的程序捕捉到并打印到日志中,而tomcat的日志一般都会记录到崩溃前的所有问题。
3.Linux系统句柄数不一定只有在操作文件的时候才会占用,http连接这种操作也会占用句柄数。其本质是一个特殊的指针,当应用程序要引用其他系统(比如操作系统和数据库等)所管理的内存块或对象时,就要使用句柄。
以上,希望也能对你有帮助。