Early in the morning, the server reported an alarm. The system's CPU load reached 15, leading to access failure!
Jstack PID prints the stack, and a large number of JSON parsing threads are in runnable.
Suddenly, I gave up the ready-made class libraries and manually performed JSON parsing for the efficiency of JSON parsing. The result was that the efficiency was improved by more than 50 times. At that time, I was complacent for a while!
Unexpectedly, a piece of data in an invalid format suddenly led to an endless loop!
For the moment, let's not talk about how dirty data enters the system. Let's take a look at how to parse JSONCode:
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 \"}]} // The above is a normal data list <long> List = new arraylist <long> (2); If (Data = NULL | data. length () <= 0) {return list;} int datapos = data. indexof ("data"); If (Data Pos <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 ;}
Note that if the format is invalid, perform the next loop. This is where the problem occurs, if partners. substring (colonpos + 1, commapos) is null. The original string is not changed when it enters the next loop. It will be executed again next time, leading to an endless loop!
A very low-level mistake! Fuck!
Lessons learned:
(1) do not optimize the code easily.
(2) be sure to perform unit tests and consider normal branches and abnormal branches, normal data and abnormal data.
(3) The CPU load is too high, and an endless loop may occur!
PS: how to print a stack:
Method for writing a printing Stack: @ path (value = "/API/stackinfo") @ getpublic actionresult stackinfo () {string STR = " memory: "; STR + = "
"; STR + = "
- freememory =" + runtime. getruntime (). freememory ()/(1024*1024) + "m
"; STR + = "
- totalmemory =" + runtime. getruntime (). totalmemory ()/(1024*1024) + "m
"; STR + = "
- maxmemory =" + runtime. getruntime (). maxmemory ()/(1024*1024) + "m
"; STR + = "
"; STR + = "
"; STR + = " thread: "; STR + = "
"; for (thread t: list_threads ()) {STR + = "
- " + T. getname () + "," + T. getstate () + ":" + T. getclass (). getname () + "
"; stacktraceelement [] elems = T. getstacktrace (); STR + = "
"; for (stacktraceelement ELEM: elems) {STR + = "
- " + ELEM. tostring () + "
";} STR + = "
";} STR + = "
"; beat. getresponse (). setcontenttype ("text/html; charset = UTF-8"); return New contentresult (STR) ;}