`
bnmnba
  • 浏览: 287895 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

Linux Centos 7.2 JDK 1.7.0 Tomcat8.5 部署的web应用(连接池druid),长时间不用后,再次访问很慢卡住

 
阅读更多

JDK 1.7.0 + Tomcat 8.5 部署的web应用,启动后第一次打开很快。长时间不用后,再次浏览器访问时很慢卡住,或是socket连接超时。后台代码卡住的位置不是很确定,后来发现都是卡到了Service层。连接池是druid 1.0.8。

解决问题的思路:

1.首先确定卡在那里。

(方法用jps和jstack和远程调试)

问题重现后立即进行如下操作:

a.找到进程ID,查看进程命令:ps -ef      或者  jps -v

b.查看java进程中的线程命令:jstack 进程ID

   可以看到java进程里的每个线程的调用栈。

   类似如下图(linux在内网,用外网的windows截图代替)

 可以看到每个线程目前运行到哪里。

如果是和我一样卡在Service层的方法,而且里面又有类似getConnection这样获取数据库连接的情况下:



 
Service层方法有事务,事务需要数据库连接,连接池里连接长时间不用会断开。

这就是我的问题原因。可以用netstat -ant | grep 11521可查看这些被卡住的socket连接。

 

 

2.我的问题解决方法:a+b双管齐下

a.避免因为安全随机数慢导致获取连接卡住,centos7.2里用jdbc连接Oracle时,会因为这个问题超时[socket reset]或程序卡住,在tomcatbin/目录下新建setenv.sh文件内容如下(注意英文双引号和"/./"是必须的):

export JAVA_OPTS="$JAVA_OPTS -Djava.security.egd=file:/dev/./urandom"
#export CATALINA_OPTS="-server -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=18000"
#export CATALINA_OPTS="-agentlib:jdwp=transport=dt_socket,address=18000,server=y,suspend=n,timeout=60000"
export  JAVA_OPTS="-server -Xms2048m -Xmx2048m -XX:PermSize=128m -XX:MaxPermSize=512m $JAVA_OPTS"

设置后,tomcat的启动速度加快很多。

 

b.尝试修改我的druid数据源配置后:这个配置应该可以解决大部分问题。

 

initialSize=5 初始化5个连接
minIdle=5 最小空闲5个连接
maxActive=20 最多20个连接
maxWait=10000  获取连接最多等待10000毫秒
useUnfairLock=true 处理等待时使用非公平锁
testWhileIdle=true 检查空闲连接可用性
timeBetweenEvictionRunsMillis=60000 一分钟检查一次空闲连接,同时关闭多余的空闲连接 毫秒
testOnBorrow=true 获取连接前检查可用性
minEvictableIdleTimeMillis=300000 一个连接在池中最小生存的时间毫秒
validationQuery=select 1 from dual
validationQueryTimeout=4 检查连接可用性的超时时间4秒

但是我这台电脑上发现每次打开都很卡,使用netstat -ant | grep 11521可以看到数据库连接要么没有,要么已经wait_close。然后我停用了Druid,换Spring自带数据源:

    <!-- 数据源配置, 不使用连接池 -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${jdbc.driver}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

 

使用netstat -ant | grep 11521 可以看到总是有数据库连接是建立的。 观察几个星期,问题都不在出现了。问题解决!

 

但是druid哪里设置错了吗?有知道的可以回复一下,告诉我。

 

2019年12月10日

spring boot 开发的微服务项目存在同样问题,jdbc('org.springframework.boot', name: 'spring-boot-starter-jdbc', version: '1.4.1.RELEASE'),spring boot默认使用连接池:org.apache.tomcat.jdbc.pool.ConnectionPool

jstack信息:

Full  thread  dump  Java  HotSpot(TM)  64-Bit  Server  VM  (25.172-b11  mixed  mode):

"XNIO-2  task-6"  #61  prio=5  os_prio=0  tid=0x00007fddb4004800  nid=0x16a1  runnable  [0x00007fde84bcb000]
      java.lang.Thread.State:  RUNNABLE
at  sun.nio.ch.FileDispatcherImpl.read0(Native  Method)
at  sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:39)
at  sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)
at  sun.nio.ch.IOUtil.read(IOUtil.java:197)
at  sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:380)
-  locked  <0x00000000d1c78c28>  (a  java.lang.Object)
at  oracle.net.nt.TimeoutSocketChannel.read(TimeoutSocketChannel.java:144)
at  oracle.net.ns.NIOHeader.readHeaderBuffer(NIOHeader.java:82)
at  oracle.net.ns.NIOPacket.readFromSocketChannel(NIOPacket.java:139)
at  oracle.net.ns.NIOPacket.readFromSocketChannel(NIOPacket.java:101)
at  oracle.net.ns.NIONSDataChannel.readDataFromSocketChannel(NIONSDataChannel.java:80)
at  oracle.jdbc.driver.T4CMAREngineNIO.prepareForReading(T4CMAREngineNIO.java:98)
at  oracle.jdbc.driver.T4CMAREngineNIO.unmarshalUB1(T4CMAREngineNIO.java:534)
at  oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:485)
at  oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:252)
at  oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:612)
at  oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:213)
at  oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:37)
at  oracle.jdbc.driver.T4CStatement.executeForDescribe(T4CStatement.java:733)
at  oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:904)
at  oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1082)
at  oracle.jdbc.driver.OracleStatement.executeInternal(OracleStatement.java:1737)
at  oracle.jdbc.driver.OracleStatement.execute(OracleStatement.java:1692)
-  locked  <0x00000000d1c6e380>  (a  oracle.jdbc.driver.T4CConnection)
at  oracle.jdbc.driver.OracleStatementWrapper.execute(OracleStatementWrapper.java:300)
at  org.apache.tomcat.jdbc.pool.PooledConnection.validate(PooledConnection.java:509)
at  org.apache.tomcat.jdbc.pool.PooledConnection.validate(PooledConnection.java:443)
at  org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:784)
at  org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:635)
at  org.apache.tomcat.jdbc.pool.ConnectionPool.getConnection(ConnectionPool.java:187)
at  org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:132)
at  org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111)
at  org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77)
at  org.mybatis.spring.transaction.SpringManagedTransaction.openConnection(SpringManagedTransaction.java:82)
at  org.mybatis.spring.transaction.SpringManagedTransaction.getConnection(SpringManagedTransaction.java:68)
at  org.apache.ibatis.executor.BaseExecutor.getConnection(BaseExecutor.java:338)
at  org.apache.ibatis.executor.SimpleExecutor.prepareStatement(SimpleExecutor.java:84)
at org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:62)
at org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:326)
at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:156)
at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:109)
at com.github.pagehelper.PageInterceptor.intercept(PageInterceptor.java:108)
at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:61)
at com.sun.proxy.$Proxy165.query(Unknown Source)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:148)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:141)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:77)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:433)
at com.sun.proxy.$Proxy124.selectOne(Unknown Source)
at org.mybatis.spring.SqlSessionTemplate.selectOne(SqlSessionTemplate.java:166)
at com.xxxxxx.core.dao.impl.BaseDaoImpl.select(BaseDaoImpl.java:23)
at com.xxxxxx.core.dao.impl.BaseDaoImpl$$FastClassBySpringCGLIB$$fa9bc947.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:720)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:655)
at com.xxxxxx.core.dao.impl.BaseDaoImpl$$EnhancerBySpringCGLIB$$789fcc35.select(<generated>)
at com.xxxxxx.core.service.PublicService.queryUserDeptCount(PublicService.java:58)
at com.xxxxxx.core.configurate.LoginInterceptor.preHandle(LoginInterceptor.java:45)
at org.springframework.web.servlet.HandlerExecutionChain.applyPreHandle(HandlerExecutionChain.java:134)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:958)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
at javax.serv

 

解决方法类似(停用连接池):

spring.datasource.type=org.springframework.jdbc.datasource.DriverManagerDataSource
spring.datasource.url=jdbc:oracle:thin:@xxx:xx/xx
spring.datasource.username=xx
spring.datasource.password=xx
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
#spring.datasource.initialSize=1
#spring.datasource.maxActive=200
#spring.datasource.minIdle=5
#spring.datasource.maxIdle=20

 

必须使用连接池?

那么可以考虑把连接池设置为:得到连接时不验证连接可用性,同时缩短空闲连接可用性检查的间隔,同时设置检查可用性的超时时间。如果没有任何bug(尤其超时时间可能有问题,你设置了,jdbc驱动可不一定会用)那么理论上不会卡。祝你好运!

 

https://docs.oracle.com/javase/7/docs/technotes/guides/jpda/conninv.html

https://www.cnblogs.com/prefectjava/p/9397999.html

https://www.cnblogs.com/yeahwell/p/9252931.html

  • 大小: 49.8 KB
  • 大小: 1.9 MB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics