一次應用提供的服務化接口收到報警大量超時,報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版本修復。