监控检测到基于tomcat应用的后台管理系统网页无法访问,发来了报警短信,故障问题出现,要做的第一件事情--重启应用。没错!不是排障,而是先重启应用,线上产品出现问题第一原则,不管什么问题要在第一时间尝试恢复,而重启应用往往是最有效的手段!
重启后,后台管理系统能正常使用,这下心就算放下了,一般这种情况都是可以恢复的小问题,如果重启不行呢?恢复不了呢,运维人员这才会紧急排错,如果尝试10分钟无从下手或者预测10分钟内无法解决,那么赶紧按照容灾手册进行紧急替换恢复吧,别告诉我没有快速容灾方案....
回到主题,在业务暂时恢复正常后,千万不要不管不顾了,一定要找出问题原因,不可能出现没有原因就导致业务罢工的,那只是你没找见而已。
分享下楼主的排障步骤,仅作参考:
1. 排除是否由代码引起的故障
检查tomcat的日志,发现了错误信息,但是与tomcat的socket错误有关,从这个报错信息基本上排除是开发的代码问题,其实有很多时候开发的代码会把tomcat跑死,什么内存溢出的都是小意思,做好内存GCC和heapdump就可以了。
ClientAbortException: java.net.SocketTimeoutException atorg.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:369) atorg.apache.tomcat.util.buf.ByteChunk.append(ByteChunk.java:368) atorg.apache.catalina.connector.OutputBuffer.writeBytes(OutputBuffer.java:392) atorg.apache.catalina.connector.OutputBuffer.write(OutputBuffer.java:381) atorg.apache.catalina.connector.CoyoteOutputStream.write(CoyoteOutputStream.java:89) at org.apache.catalina.connector.CoyoteOutputStream.write(CoyoteOutputStream.java:83) atcom.qhfax.thrivefa.web.FileController.showImage(FileController.java:60) atcom.qhfax.thrivefa.common.BaseController.showImage(BaseController.java:54) at sun.reflect.GeneratedMethodAccessor40.invoke(UnknownSource) atsun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) atorg.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:175) atorg.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:446) at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:434) atorg.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938) atorg.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961) atorg.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852) atjavax.servlet.http.HttpServlet.service(HttpServlet.java:617) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837) atjavax.servlet.http.HttpServlet.service(HttpServlet.java:717) atorg.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) atorg.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88) atorg.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) atorg.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) atorg.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) atorg.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) atorg.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) atorg.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) atorg.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) atorg.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293) at org.apache.coyote.http11.Http11NioProcessor.process(Http11NioProcessor.java:889) atorg.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:744) atorg.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:2274) atjava.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) atjava.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) at java.lang.Thread.run(Thread.java:662) Caused by: java.net.SocketTimeoutException atorg.apache.tomcat.util.net.NioBlockingSelector.write(NioBlockingSelector.java:123) atorg.apache.tomcat.util.net.NioSelectorPool.write(NioSelectorPool.java:156) atorg.apache.coyote.http11.InternalNioOutputBuffer.writeToSocket(InternalNioOutputBuffer.java:460) atorg.apache.coyote.http11.InternalNioOutputBuffer.flushBuffer(InternalNioOutputBuffer.java:800) atorg.apache.coyote.http11.InternalNioOutputBuffer.addToBB(InternalNioOutputBuffer.java:644) at org.apache.coyote.http11.InternalNioOutputBuffer.access$000(InternalNioOutputBuffer.java:46) atorg.apache.coyote.http11.InternalNioOutputBuffer$SocketOutputBuffer.doWrite(InternalNioOutputBuffer.java:825) atorg.apache.coyote.http11.filters.IdentityOutputFilter.doWrite(IdentityOutputFilter.java:118) atorg.apache.coyote.http11.InternalNioOutputBuffer.doWrite(InternalNioOutputBuffer.java:610) at org.apache.coyote.Response.doWrite(Response.java:560) atorg.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:364) ... 38 more
2. 费尽心思搭监控的意义
同时赶紧检查各类报警短信和邮件,排除对网页监控的保健,还真有收获:
告警主机:**********
告警时间:********
告警等级:Warning
告警信息: Too many processes on ******
告警项目:proc.num[]
问题详情:Number of processes:106
当前状态:OK:106
事件ID:16294
那么赶紧看监控系统:
这下就抓住罪魁祸首的小尾巴了,初步找到导致业务趴下的疑犯了那么下面就要在控制台准确定位是那个捣乱的了。
3. 排障方法
找到是进程过多的原因导致的,那么解决办法就太简单了
pstree 找出哪个进程过高一看便知,额,原来是定时任务的坑...
pkill 批量结束定时任务的应用
4. 精确分析故障原因
报警看到的知识进程过多,这个和tomcat歇菜有什么关系,这就要看系统日志,这个时候日志集中管理和可视化的作用就体现出来了。
5. 知识点
Linux 内核有 个机制叫OOM killer(Out-Of-Memory killer),该机制会监控那些占用内存过大,尤其是瞬间很快消耗大量内存的进程,为了防 止内存耗尽而内核会把该进程杀掉。典型的情况是:某天一台机器突然ssh远程登录不了,但能ping通,说明不是网络的故障,原因是sshd进程被 OOM killer杀掉了(多次遇到这样的假死状况)。重启机器后查看系统日志/var/log/messages会发现Out of Memory: Kill process 1865(sshd)类似的错误信息。
需要注意的是:
1.OOM不适合于解决内存泄漏(Memory leak)的问题。
2.有时free查看还有充足的内存,但还是会触发OOM,是因为该进程可能占用了特殊的内存地址空间。
所以别指望OOM能够预防内存溢出,还有free是发现不了OOM的问题,运维伙伴们,企业级监控和日志集中管理才是你们的眼睛!