一次服務大量超時的java排查過程經驗

一次應用提供的服務化接口收到報警大量超時,報404.趕忙着手處理:

1)查看監控報表的cpu  load ,jvm gc情況,jvm內存,io都正常,如果沒有做監控可以手工到服務器上命令查看

2)檢查網絡包括http響應及tcp網絡響應請求情況均正常

3)登陸服務器,jps -v把java進程打出來,或者top發現j該java進程的cpu使用率及內存佔用率正常

4)top -H -p PID 命令查看該進程裏對應的當前線程數量正常,各線程佔用的cpu和內存正常.和上次cpu load過高時不一樣,當時的線程是有幾個佔用了較高的cpu.

5)jstack pid  打出來一臺服務超時和一臺重啓後正常提供服務的stack信息,發現差不多,都有類似信息:

"DubboClientHandler-172.22.35.17:9090-thread-5" daemon prio=10 tid=0x00002aaab85fa800 nid=0x50d9 waiting on condition [0x0000000041c6a000]
   java.lang.Thread.State: TIMED_WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x0000000793f97040> (a java.util.concurrent.SynchronousQueue$TransferStack)
        at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:198)
        at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:424)
        at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:323)
        at java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:874)
        at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:945)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
        at java.lang.Thread.run(Thread.java:662)

"DubboClientHandler-172.22.11.33:9090-thread-5" daemon prio=10 tid=0x00002aaab9e2f800 nid=0x50d3 waiting on condition [0x00000000492bc000]
   java.lang.Thread.State: TIMED_WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x0000000793c2b708> (a java.util.concurrent.SynchronousQueue$TransferStack)
        at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:198)
        at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:424)
        at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:323)
        at java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:874)
        at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:945)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
        at java.lang.Thread.run(Thread.java:662)

6)執行 jstack [進程pid]|grep -A 100 [線程pid]

發現有問題的這臺機器單個線程出現上面的信息較多,正常服務的服務器打出來的線程上面的併發銷等待信息較少


對上面信息分析後,結合自己的應用情況得到下面的信息:

應用報404是做了超時控制,請求大於500ms就報404請求,監控到後臺服務平均響應基本是1000ms左右.從日誌報錯情況來看,有一個搜索的接口不停打超時日誌,但諮詢接口方說該接口正常.這個接口是http請求,curl這個請求返回正常.

異步加載框架設置的超時剛好1秒鐘.所以基本斷定這個接口不可用,直接給異步框架做超時控制1秒鐘返回,因爲大於500ms直接報404.


重啓後的機器這個接口沒有報錯,說明connection出現了問題.

至於爲什麼突然出現這個問題,這個錯誤的信息很重要,初步看是nio報的,問題遠沒想象的簡單.後繼再找接口方排查



最後確認是dubbo的一個bug,導致配置的業務線程池無效,線程會無限增長,所以會導致線程無限堆積和大量空等待線程,導致內存,gc的cpu開銷過大,間而導至load過高。後面升級dubbo版本修復。









發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章