调用触发死循环的请求
[root@jvm001 ~]# curl http://localhost:8088/loop
使用top检查进程状态
- 发现PID=265的进程的CPU占用率为99%,从而确定出问题的进程为265;
[root@jvm001 ~]# top
top - 01:09:43 up 1:22, 3 users, load average: 0.36, 0.15, 0.06
Tasks: 10 total, 1 running, 9 sleeping, 0 stopped, 0 zombie
Cpu(s):100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 997088k total, 933772k used, 63316k free, 8524k buffers
Swap: 524284k total, 4688k used, 519596k free, 449012k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
265 root 20 0 2180m 128m 16m S 99.9 13.2 0:30.60 java
1 root 20 0 66296 5312 4828 S 0.0 0.5 0:00.03 sshd
5 root 20 0 98.2m 6968 5952 S 0.0 0.7 0:00.52 sshd
7 root 20 0 13028 3184 2796 S 0.0 0.3 0:00.03 bash
212 root 20 0 98.3m 6920 5916 S 0.0 0.7 0:00.58 sshd
214 root 20 0 13028 3040 2676 S 0.0 0.3 0:00.01 bash
294 root 20 0 14948 1992 1764 R 0.0 0.2 0:00.04 top
295 root 20 0 98.2m 6904 5896 S 0.0 0.7 0:00.03 sshd
297 root 20 0 13028 2992 2708 S 0.0 0.3 0:00.00 bash
312 root 20 0 75164 5940 5176 S 0.0 0.6 0:00.00 curl
使用jstack输出265号进程的信息
- 用jstack将265号进程的信息重定向到文件265.txt;
- 用sz将265.txt下载到本机;
[root@jvm001 ~]# jstack 265 > 265.txt
[root@jvm001 ~]# sz 265.txt
rz
使用top检查265号进程中的线程信息
- 发现PID为282的线程CPU占用率异常;
- 注意这个282是十进制的,而jstack输出的线程号是十六进制的,需做转换;
[root@jvm001 ~]# top -p 265 -H
top - 01:11:42 up 1:24, 3 users, load average: 0.99, 0.45, 0.18
Tasks: 27 total, 1 running, 26 sleeping, 0 stopped, 0 zombie
Cpu(s):100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 997088k total, 914796k used, 82292k free, 8572k buffers
Swap: 524284k total, 5540k used, 518744k free, 431036k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
282 root 20 0 2181m 128m 16m R 99.7 13.2 2:21.75 java
265 root 20 0 2181m 128m 16m S 0.0 13.2 0:00.00 java
266 root 20 0 2181m 128m 16m S 0.0 13.2 0:02.24 java
267 root 20 0 2181m 128m 16m S 0.0 13.2 0:00.35 java
268 root 20 0 2181m 128m 16m S 0.0 13.2 0:00.00 java
269 root 20 0 2181m 128m 16m S 0.0 13.2 0:00.00 java
270 root 20 0 2181m 128m 16m S 0.0 13.2 0:00.00 java
271 root 20 0 2181m 128m 16m S 0.0 13.2 0:02.40 java
272 root 20 0 2181m 128m 16m S 0.0 13.2 0:01.05 java
273 root 20 0 2181m 128m 16m S 0.0 13.2 0:00.00 java
274 root 20 0 2181m 128m 16m S 0.0 13.2 0:00.23 java
277 root 20 0 2181m 128m 16m S 0.0 13.2 0:00.03 java
278 root 20 0 2181m 128m 16m S 0.0 13.2 0:00.01 java
279 root 20 0 2181m 128m 16m S 0.0 13.2 0:00.00 java
280 root 20 0 2181m 128m 16m S 0.0 13.2 0:00.01 java
281 root 20 0 2181m 128m 16m S 0.0 13.2 0:00.09 java
283 root 20 0 2181m 128m 16m S 0.0 13.2 0:00.00 java
284 root 20 0 2181m 128m 16m S 0.0 13.2 0:00.00 java
285 root 20 0 2181m 128m 16m S 0.0 13.2 0:00.00 java
286 root 20 0 2181m 128m 16m S 0.0 13.2 0:00.00 java
287 root 20 0 2181m 128m 16m S 0.0 13.2 0:00.00 java
288 root 20 0 2181m 128m 16m S 0.0 13.2 0:00.00 java
289 root 20 0 2181m 128m 16m S 0.0 13.2 0:00.00 java
290 root 20 0 2181m 128m 16m S 0.0 13.2 0:00.00 java
291 root 20 0 2181m 128m 16m S 0.0 13.2 0:00.02 java
292 root 20 0 2181m 128m 16m S 0.0 13.2 0:00.00 java
323 root 20 0 2181m 128m 16m S 0.0 13.2 0:00.00 java
将十进制的282转换成十六进制
[root@jvm001 ~]# printf "%x" 282
11a
拿着十六进制的11a在265.txt中排查
- 定位到了这个方法:com.example.demo.CpuController.loop(CpuController.java:19),从而找到了导致CPU占用过高的代码;
"http-nio-8088-exec-2" #16 daemon prio=5 os_prio=0 tid=0x00007f8828822000 nid=0x11a runnable [0x00007f87f8ffa000]
java.lang.Thread.State: RUNNABLE
at java.lang.String.indexOf(String.java:1769)
at java.lang.String.indexOf(String.java:1718)
at com.example.demo.CpuController.getPartneridsFromJson(CpuController.java:74)
at com.example.demo.CpuController.loop(CpuController.java:19)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:189)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:800)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:200)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:834)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
- locked <0x00000000f0d74c98> (a org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
查看造成问题的代码
@RestController
public class CpuController {
/**
* 死循环
* 由不合法的json串导致
* */
@RequestMapping("/loop")
public List<Long> loop(){
String data = "{\"data\":[{\"partnerid\":]";
return getPartneridsFromJson(data);
}
public static List<Long> getPartneridsFromJson(String data){
//{\"data\":[{\"partnerid\":982,\"count\":\"10000\",\"cityid\":\"11\"},{\"partnerid\":983,\"count\":\"10000\",\"cityid\":\"11\"},{\"partnerid\":984,\"count\":\"10000\",\"cityid\":\"11\"}]}
//上面是正常的数据
List<Long> list = new ArrayList<Long>(2);
if(data == null || data.length() <= 0){
return list;
}
int datapos = data.indexOf("data");
if(datapos < 0){
return list;
}
int leftBracket = data.indexOf("[",datapos);
int rightBracket= data.indexOf("]",datapos);
if(leftBracket < 0 || rightBracket < 0){
return list;
}
String partners = data.substring(leftBracket+1,rightBracket);
if(partners == null || partners.length() <= 0){
return list;
}
while(partners!=null && partners.length() > 0){
int idpos = partners.indexOf("partnerid");
if(idpos < 0){
break;
}
int colonpos = partners.indexOf(":",idpos);
int commapos = partners.indexOf(",",idpos);
if(colonpos < 0 || commapos < 0){
//partners = partners.substring(idpos+"partnerid".length());//1
continue;
}
String pid = partners.substring(colonpos+1,commapos);
if(pid == null || pid.length() <= 0){
//partners = partners.substring(idpos+"partnerid".length());//2
continue;
}
try{
list.add(Long.parseLong(pid));
}catch(Exception e){
//do nothing
}
partners = partners.substring(commapos);
}
return list;
}
}