2021-03-12

JVM实战调优(空格引发的服务异常)

JVM实战调优

问题描述

某一个项目中有一个文字转语音的服务,使用的是科大讯飞的语音转换服务,需要调用三方服务。因其转换服务是一个耗时操作,官方给的demo使用的是 WebSocket 进行数据转换操作。项目中使用线程池进行调用。同时科大讯飞的语音合成有长度限制,官方给出的在[8000字节,约2000个汉字],所以需要分段合成。

在某一天,客户反应语音无法播放,经过查看服务日志排查,是因为购买的服务到期了,客户重新购买了其余的服务,参数发生了改变,以前的参数无法使用。更改了参数之后,更新部署之后,服务恢复正常。又过了几天,客户反应语音又无法播放了,经过查看日志,发现大部分是成功的,部分发生了失败。

调优过程

查看日志的时候,发现部分失败的原因是connection fail,通过 jps 找到对应的应用程序进程号。

然后通过 top -Hp PID 查看了一个CPU和内存的占用率,都是正常的占用。

因其使用了线程池,怀疑是线程池占满了,用 就 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() 唤醒线程,程序重新部署之后,程序正常。

为了防止出现问题,这次对程序的日志进行了监控,将失败的文章进行了重新转换,虽然线程可以正常结束,但是转换仍然会出现失败,经过对文字进行严格的分析和多次转换测试,有一小段文字被截取了出来,观察了一会没有发现异常,通过十六进制软件对其进行查看,才发现两个字符有区别,两个字符都是空格,但前一个空格是半角输入法下的空格十六进制是20,全角输入法下的空格是 E38080,然后修改程序,将全角输入法下的空格剔除,再次进行转换,服务正常。









原文转载:http://www.shaoqun.com/a/621661.html

跨境电商:https://www.ikjzd.com/

打折网:https://www.ikjzd.com/w/74

ensogo:https://www.ikjzd.com/w/1485


JVM实战调优问题描述某一个项目中有一个文字转语音的服务,使用的是科大讯飞的语音转换服务,需要调用三方服务。因其转换服务是一个耗时操作,官方给的demo使用的是WebSocket进行数据转换操作。项目中使用线程池进行调用。同时科大讯飞的语音合成有长度限制,官方给出的在[8000字节,约2000个汉字],所以需要分段合成。在某一天,客户反应语音无法播放,经过查看服务日志排查,是因为购买的服务到期了,
focalprice:https://www.ikjzd.com/w/1094.html
reddit:https://www.ikjzd.com/w/180
深诺互动:https://www.ikjzd.com/w/2746
还能问亚马逊拿钱?卖家笑了……:https://www.ikjzd.com/home/9706
亚马逊抓测评的逻辑是什么?什么样的测评方式才安全?:https://www.ikjzd.com/home/107016
亚马逊文案写作的秘密:如何在一夜之间提升listing转化率?:https://www.ikjzd.com/home/114772

No comments:

Post a Comment