场景:在工程A中调用工程B的接口完成一些逻辑,A中每调用一个接口打印一条信息,观察到当接口连续调用一段时间后,会卡住一会,然后又继续执行。老大给出建议查看下jstack dump堆栈信息,查看阻塞和耗时长的操作。
- 在命令行终端,输入jps 查看当前java进程id;
- jstack –l PID >>log.txt, PID指进程Id,将堆栈信息输出到当前目录下的log.txt文件中。
对其中参数解释:
-l long listings,会打印出额外的锁信息,在发生死锁时可以用jstack -l pid来观察锁持有情况
-m mixed mode,不仅会输出Java堆栈信息,还会输出C/C++堆栈信息(比如Native方法) - 堆栈的详细分析,参考jstack dump日志文件详细分析
通过上述的分析,发现项目中的日志打印中存在同步程序,导致所有的接口都在等待日志打印;另一个问题是身份验证太慢。
解决:
- 日志级别调成error,减少日志打印占用的资源,p6spy关闭减少资源占用,打印日志非常耗费资源,日志中的同步更是让接口处于等待状态。
- tokenID认证使用本地的认证,或者将认证去掉,原来使用外网地址的认证,通过Apache访问认证接口,Apache默认长连接,会限制连接的数量,等待连接释放,使程序阻塞。
除此之外,能够增加接口处理速度的设置:
- 设置MySQL数据库,my.ini
max_allowed_packet = 64M
innodb_buffer_pool_size =20G --也不用设置过大,4096M也还可以
- 设置数据库的连接数,增加初始连接数,最大连接数:
#定义初始连接数
initialSize=10
#连接池处于活动状态的数据库连接的最大数目,0表示不限制,表示最大并发
maxActive=200
#连接池处于空闲状态的数据库连接的最大数目,取非正整数表示不受限制,超过此数值时多余的空闲连接将会被释放
maxIdle=20
#连接池处于空闲状态的数据库连接的最小数目,低于此数值将会创建所欠缺的连接,设0无限制
minIdle=10
#连接池中连接用完时,新的请求的等待时间(即等待别的连接空闲),超时返回异常,毫秒
maxWait=60000
- 修改Tomcat,server.xml
<Connector
executor="tomcatThreadPool"
port="8280"
protocol="org.apache.coyote.http11.Http11Nio2Protocol"
enableLookups="false"
acceptCount="1500"
disableUploadTimeout="false"
connectionTimeout="180000"
connectionUploadTimeout="300000"
maxConnections="10000"
URIEncoding="UTF-8"
redirectPort="8443"
compression="on"
compressionMinSize="1024"
useSendfile="false"
keepAliveTimeout="60000"
tcpNoDelay="true"
noCompressionUserAgents="gozilla, traviata"
maxPostSize="-1"
maxParameterCount="-1"
compressibleMimeType="text/html,text/xml,text/plain,text/css,text/javascript,application/javascript " />
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
maxThreads="150" minSpareThreads="4"/>
将tomcat的线程池最大连接数增加改成maxThreads=200;
http的长连接超时时间keepAliveTimeout设置为keepAliveTimeout="2000"ms,因为我只是调用一下,不需要保持长连接获取数据,无用连接快速释放就可以了。