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,然后修改程序,将全角输入法下的空格剔除,再次进行转换,服务正常。

JVM实战调优(空格引发的服务异常)的更多相关文章

  1. JVM 性能调优实战之:一次系统性能瓶颈的寻找过程

    玩过性能优化的朋友都清楚,性能优化的关键并不在于怎么进行优化,而在于怎么找到当前系统的性能瓶颈.性能优化分为好几个层次,比如系统层次.算法层次.代码层次…JVM 的性能优化被认为是底层优化,门槛较高, ...

  2. JVM 性能调优实战之:使用阿里开源工具 TProfiler 在海量业务代码中精确定位性能代码

    本文是<JVM 性能调优实战之:一次系统性能瓶颈的寻找过程> 的后续篇,该篇介绍了如何使用 JDK 自身提供的工具进行 JVM 调优将 TPS 由 2.5 提升到 20 (提升了 7 倍) ...

  3. jvm gc 调优 实战

    非常不错的文章们 转自: 中文:http://blog.csdn.net/dragonassassin/article/details/51010947 http://josh-persistence ...

  4. JVM性能调优与实战基础理论篇-上

    Java虚拟机 概述 Java官方文档 https://docs.oracle.com/en/java/index.html JVM是一种规范,通过Oracle Java 官方文档找到JVM的规范查阅 ...

  5. JVM性能调优

    摘自:http://uule.iteye.com/blog/2114697 JVM垃圾回收与性能调优总结 JVM调优的几种策略 一.JVM内存模型及垃圾收集算法  1.根据Java虚拟机规范,JVM将 ...

  6. JVM性能调优(4) —— 性能调优工具

    前序文章: JVM性能调优(1) -- JVM内存模型和类加载运行机制 JVM性能调优(2) -- 垃圾回收器和回收策略 JVM性能调优(3) -- 内存分配和垃圾回收调优 一.JDK工具 先来看看有 ...

  7. jvm 性能调优

    [转载]:http://blog.csdn.net/chen77716/article/details/5695893 最近因项目存在内存泄漏,故进行大规模的JVM性能调优 , 现把经验做一记录. 一 ...

  8. (转)JVM性能调优之生成堆的dump文件

    转自:http://blog.csdn.net/lifuxiangcaohui/article/details/37992725 最近因项目存在内存泄漏,故进行大规模的JVM性能调优 , 现把经验做一 ...

  9. eclipse JVM 性能调优

    最近因项目存在内存泄漏,故进行大规模的JVM性能调优 , 现把经验做一记录. 一.JVM内存模型及垃圾收集算法 1.根据Java虚拟机规范,JVM将内存划分为: New(年轻代) Tenured(年老 ...

随机推荐

  1. C++实现二叉树的基本操作:建立、遍历、计算深度、节点数、叶子数等

    题意: 代码实现: #include<iostream> #include<queue> #include<stack> using namespace std; ...

  2. 痞子衡嵌入式:我的博文总量终于追平了jicheng0622

    自打2016年10月选定清爽又复古的博客园平台作为痞子衡的个人博客主战场之后,痞子衡就一直坚持在博客园首发原创技术文章,然后再同步到其他平台(CSDN,知乎,微信公众号...),在坚持更文近四年半(2 ...

  3. js optional chaining operator

    js optional chaining operator js 可选链 可选链操作符( ?. )允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效. ?. 操作符的功能类似于 ...

  4. npm version ^ meaning

    npm version ^ meaning ^ 更新版 https://docs.npmjs.com/cli/v6/commands/npm-version https://github.com/ge ...

  5. base 64 bug & encodeURIComponent

    base64 bug & encodeURIComponent window.btoa("jëh²H¶�%28"); // "autoskiptoclMjiu&q ...

  6. NGK公链:通用型存储网络

    NGK公链,是一条发展中的通用型存储网络. NGK的运用归结与存储场景.NGK通证的运用归结于支付场景.个人数据被中心化服务商买卖.被大数据服务商使用.被无数的商务及销售人员窃取.那么NGK的运用场景 ...

  7. 【Python核心编程笔记】一、Python中一切皆对象

    Python中一切皆对象 本章节首先对比静态语言以及动态语言,然后介绍 python 中最底层也是面向对象最重要的几个概念-object.type和class之间的关系,以此来引出在python如何做 ...

  8. django学习-9.windows系统安装mysql8教程

    1.前言 mysql是最流行的关系型数据库管理系统之一,我们可以在本地windows环境下搭建一个mysql的环境,便于学习. 当前我采取的搭配是: windows7(window8和window10 ...

  9. 不使用的大对象为什么要手动设置null,真的有效吗?

    本文转载自不使用的大对象为什么要手动设置null,真的有效吗? 导语 在我们开发过程中,对于大的对象使用过后,为了help gc ,我们会手动将大对象置为null,背后的原理是什么,是不是最佳的实践. ...

  10. hadoop的lzo支持

    目录 1.下载相关文件: 2.Configure LZO to build a shared library (required) and use a package-specific prefix ...