调优系列:高并发环境下,解决xml解析过慢的方法
场景
多线程环境下,启动了线程池,包含30个线程进行数据清洗。其中涉及xml文件的解析。即使机器配置十分不错,但是启动多个线程进行清洗,速度依旧跟不上。本篇博客主要是讲述该情况的原因及解决方法。
环境
| 软件 | 版本 |
|---|---|
| JDK | 1,8 |
| centos | 7 |
正文
一、环境准备
博主这里是使用阿里巴巴开源的arthas工具进行问题的跟踪。如果有兴趣了解的小伙伴请自行百度搜索。
二、启动项目和arthas工具
启动项目,等开始运行之后,使用命令ps -ef|grep clean获取进程编号,然后使用arthas工具绑定对应的进程号。具体操作可以点击 https://arthas.aliyun.com/doc/quick-start.html 进行查看。
三、查看进程情况
一般像这种启动了多个线程,但是速度跟不上的情况,很大程度是因为锁的问题。我们这里使用arthas提供的thread命令,查看进程情况。结果如下:

从上图可以了解到,有30个线程的情况下,有21个线程被阻塞等待其他操作的完成。我们可以看到里面是关于dom4j的操作导致阻塞的。这个时候,就得去研究一下源码,看看是什么原因导致线程阻塞的。
四、源码剖析
给大家截图一下,我们这里使用的业务代码,如下:

我们这里主要使用了DocumentHelper.parseText进行文本解析。单步进去查看源码,我们可以根据第三步的截图来锁定具体的位置,如下图:

这个时候,要进去查看一下,如下图:

这里要记录一下,这里主要是为了搜索SAXParserFactory的实现类,其中第二个参数为搜索不到之后的默认参数。这里先mark一下,是后面的重点。下图是该方法的注释:

我们再进去find方法,这里就是主要的问题难点了。有兴趣的同学可以自己查看源码,源码路径为:javax.xml.parsers.FactoryFinder#find。我这里大概总结一下这个方法的步骤:
-
查找环境变量中是否配置了
javax.xml.parsers.SAXParserFactory,如果有配置,则取配置值并返回;

-
尝试从
$java.home/lib/jaxp.properties查找配置,如果可以找到,则取配置中的javax.xml.parsers.SAXParserFactory并返回;

-
尝试通过读取jar包来获取服务。

我们从第三步的截图可以了解到,这里是走入第三种情况,所以去搜索jar包里面是否存在对应的服务。是不是有一种恍然大悟的感觉?!!

博主在本地单步调试过,最后是jar包搜索不到,直接返回默认值了。所以,这个时候,我们可以直接在启动脚本设置环境变量javax.xml.parsers.SAXParserFactory,减少反复搜索的时间消耗。设置如下:
-Djavax.xml.parsers.SAXParserFactory="com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl"
五、结果
添加参数之后,重新启动,速度果然有了比较大的提升。未添加参数之后,清洗效率为:

添加参数之后,清洗效率为:

耗时为原本耗时的十分之一!!!

总结
工作中会遇到很多问题,多总结,多思考,多输出,日积月累,总会变成一个大神!!!
随缘求赞
如果我的文章对大家产生了帮忙,可以在文章底部点个赞或者收藏;
如果有好的讨论,可以留言;
如果想继续查看我以后的文章,可以点击关注
可以扫描以下二维码,关注我的公众号:枫夜之求索阁,查看我最新的分享!


浙公网安备 33010602011771号