JVM實戰調優(空格引起的服務異常)

JVM實戰調優

問題描述

某一個項目中有一個文字轉語音的服務,使用的是科大訊飛的語音轉換服務,須要調用三方服務。因其轉換服務是一個耗時操做,官方給的demo使用的是 WebSocket 進行數據轉換操做。項目中使用線程池進行調用。同時科大訊飛的語音合成有長度限制,官方給出的在[8000字節,約2000個漢字],因此須要分段合成。java

在某一天,客戶反應語音沒法播放,通過查看服務日誌排查,是由於購買的服務到期了,客戶從新購買了其他的服務,參數發生了改變,之前的參數沒法使用。更改了參數以後,更新部署以後,服務恢復正常。又過了幾天,客戶反應語音又沒法播放了,通過查看日誌,發現大部分是成功的,部分發生了失敗。jvm

調優過程

查看日誌的時候,發現部分失敗的緣由是connection fail,經過 jps 找到對應的應用程序進程號。測試

而後經過 top -Hp PID 查看了一個CPU和內存的佔用率,都是正常的佔用。ui

因其使用了線程池,懷疑是線程池佔滿了,用 就 stack pid 查看線程池以後,發現滿了。線程

"OkHttp ConnectionPool" #48 daemon prio=5 os_prio=0 tid=0x00007f8d90002800 nid=0x2a7a in Object.wait() [0x00007f8dea5a5000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	at java.lang.Object.wait(Object.java:460)
	at okhttp3.internal.Util.waitMillis(Util.kt:536)
	at okhttp3.internal.Util.lockAndWaitNanos(Util.kt:522)
	- locked <0x000000076e9394f8> (a okhttp3.internal.connection.RealConnectionPool)
	at okhttp3.internal.connection.RealConnectionPool$cleanupRunnable$1.run(RealConnectionPool.kt:49)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

"pool-1-thread-3" #46 prio=5 os_prio=0 tid=0x00007f8dd4013000 nid=0x2a78 waiting on condition [0x00007f8deaaa8000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x000000076ea3d738> (a java.util.concurrent.CountDownLatch$Sync)
	at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:997)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1304)
	at java.util.concurrent.CountDownLatch.await(CountDownLatch.java:231)
	at com.baiying.trstts.factory.XfTts.getPcm(XfTts.java:206)
	at com.baiying.trstts.factory.XfTts.text2speechV3(XfTts.java:236)
	at com.baiying.trstts.controller.TextToSpeechControllerV3.lambda$text2Speech$0(TextToSpeechControllerV3.java:56)
	at com.baiying.trstts.controller.TextToSpeechControllerV3$$Lambda$426/909090985.run(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

經過異常信息,能夠看到是 CountDownLatch 阻塞了整個線程,致使其沒法結束,經過走查代碼發現,程序中只是在正常結束的時候會 countDown() 喚醒線程,繼續向下執行,在失敗的時候並不會喚醒線程,遂在程序中增長了在失敗的時候也會進行 countDown() 喚醒線程,程序從新部署以後,程序正常。3d

爲了防止出現問題,此次對程序的日誌進行了監控,將失敗的文章進行了從新轉換,雖然線程能夠正常結束,可是轉換仍然會出現失敗,通過對文字進行嚴格的分析和屢次轉換測試,有一小段文字被截取了出來,觀察了一會沒有發現異常,經過十六進制軟件對其進行查看,才發現兩個字符有區別,兩個字符都是空格,但前一個空格是半角輸入法下的空格十六進制是20,全角輸入法下的空格是 E38080,而後修改程序,將全角輸入法下的空格剔除,再次進行轉換,服務正常。日誌

相關文章
相關標籤/搜索