Code Bye

ssh2 项目 Tomcat 假死

各位大侠,如何解决项目不稳定,经常出现假死情况(最好不重启)
项目采用SSH2框架,数据连接池是 c3po通过SPRING来管理seesion,连接SQL2008数据库
SPRING配置如下:

	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
		destroy-method="close">
		<property name="driverClass" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
		<property name="jdbcUrl" value="jdbc:sqlserver://192.168.0.188:1433" />
		<property name="user" value="sa" />
		<property name="password" value="sa" />
		<property name="minPoolSize" value="2" />
		<property name="maxPoolSize" value="100" />
		<property name="maxIdleTime" value="1800" />
		<property name="acquireIncrement" value="2" />
		<property name="maxStatements" value="0" />
		<property name="initialPoolSize" value="2" />
		<property name="idleConnectionTestPeriod" value="1800" />
		<property name="acquireRetryAttempts" value="30" />
		<property name="breakAfterAcquireFailure" value="true" />
		<property name="testConnectionOnCheckout" value="false" />
	</bean>
	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="packagesToScan" value="com.xmm.bean" />
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
					<prop key="hibernate.hbm2ddl.auto">validate</prop> -->
				<prop key="hibernate.hbm2ddl.auto">validate</prop>
				<prop key="hibernate.show_sql">true</prop>
				<prop key="hibernate.format_sql">true</prop>
				<prop key="hibernate.jdbc.fetch_size">50</prop>
				<prop key="hibernate.jdbc.batch_size">30</prop>
				<prop key="hibernate.cache.use_query_cache">true</prop>
				<prop key="hibernate.cache.use_second_level_cache">true</prop>
				<prop key="hibernate.generate_statistics">true</prop>
				<prop key="hibernate.cache.use_structured_entries">true</prop>
				<prop key="hibernate.cache.region.factory_class">
					org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory
				</prop>
				<prop key="hibernate.current_session_context_class">
					org.springframework.orm.hibernate4.SpringSessionContext
				</prop>
			</props>
		</property>
	</bean>
	<bean id="transactionManager"
		class="org.springframework.orm.hibernate4.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>
	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<tx:method name="add*" propagation="REQUIRED" />
			<tx:method name="del*" propagation="REQUIRED" />
			<tx:method name="update*" propagation="REQUIRED" />
			<tx:method name="get*" propagation="REQUIRED" read-only="true" />
			<tx:method name="count*" propagation="REQUIRED" read-only="true" />
			<tx:method name="find*" propagation="REQUIRED" read-only="true" />
			<tx:method name="list*" propagation="REQUIRED" read-only="true" />
			<tx:method name="*" read-only="true" />

		</tx:attributes>
	</tx:advice>

	<aop:config>
		<aop:pointcut id="serviceMethods" expression="execution(* com.xmm.service..*.*(..))" />
		<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods" />
	</aop:config>
	<bean id="messageSource"
		class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
		<property name="basename" value="classpath:messages_zh_CN" />
	</bean>

操作一段时间 TOMCAT假死,访问项目里的最简单的HTML页面(没有任何代码,纯静态页面)也没有反应

日志
后台输出假死代码(不一定):

[2014-08-01 14:06:26.234] [DEBUG] [http-bio-8080-exec-112] [org.hibernate.internal.SessionImpl:1002] - Initializing proxy: 
[2014-08-01 14:06:26.234] [DEBUG] [http-bio-8080-exec-112] [org.hibernate.loader.Loader:2099] - Loading entity: 

TOMCAT 日志
localhost_access_log

192.168.0.100 - - [01/Aug/2014:14:06:24 +0800] "GET /xmm/dispatchingdetail/dispatching_detail!listAll.do?_=1406873061665 HTTP/1.1" 200 5707
192.168.0.100 - - [01/Aug/2014:14:06:36 +0800] "GET /favicon.ico HTTP/1.1" 404 -
127.0.0.1 - - [01/Aug/2014:14:08:12 +0800] "GET /favicon.ico HTTP/1.1" 404 -

通过IP 100访问最后的日志,然后本机127访问只记录访问 /favicon.ico,后面的就不记录了。

查看TCP端口

Active Connections

  Proto  Local Address          Foreign Address        State           PID
  TCP    0.0.0.0:135            0.0.0.0:0              LISTENING       1276
  TCP    0.0.0.0:445            0.0.0.0:0              LISTENING       4
  TCP    0.0.0.0:1108           0.0.0.0:0              LISTENING       4100
  TCP    0.0.0.0:1433           0.0.0.0:0              LISTENING       1800
  TCP    0.0.0.0:2383           0.0.0.0:0              LISTENING       1256
  TCP    0.0.0.0:2401           0.0.0.0:0              LISTENING       1192
  TCP    0.0.0.0:8009           0.0.0.0:0              LISTENING       4100
  TCP    0.0.0.0:8080           0.0.0.0:0              LISTENING       4100
  TCP    127.0.0.1:1033         0.0.0.0:0              LISTENING       3148
  TCP    127.0.0.1:1101         127.0.0.1:1102         ESTABLISHED     3300
  TCP    127.0.0.1:1102         127.0.0.1:1101         ESTABLISHED     4100
  TCP    127.0.0.1:1434         0.0.0.0:0              LISTENING       1800
  TCP    127.0.0.1:1670         127.0.0.1:24367        ESTABLISHED     1924
  TCP    127.0.0.1:2097         127.0.0.1:24367        ESTABLISHED     1924
  TCP    127.0.0.1:2105         127.0.0.1:8080         FIN_WAIT_2      1108
  TCP    127.0.0.1:2106         127.0.0.1:8080         FIN_WAIT_2      1108
  TCP    127.0.0.1:2113         127.0.0.1:8080         ESTABLISHED     1108
  TCP    127.0.0.1:2133         127.0.0.1:8580         TIME_WAIT       0
  TCP    127.0.0.1:2135         127.0.0.1:8580         ESTABLISHED     1108
  TCP    127.0.0.1:2136         127.0.0.1:24367        ESTABLISHED     1924
  TCP    127.0.0.1:2138         127.0.0.1:24367        ESTABLISHED     1924
  TCP    127.0.0.1:2402         0.0.0.0:0              LISTENING       124
  TCP    127.0.0.1:4550         127.0.0.1:4551         ESTABLISHED     3300
  TCP    127.0.0.1:4551         127.0.0.1:4550         ESTABLISHED     3300
  TCP    127.0.0.1:5037         0.0.0.0:0              LISTENING       5224
  TCP    127.0.0.1:8005         0.0.0.0:0              LISTENING       4100
  TCP    127.0.0.1:8080         127.0.0.1:2105         CLOSE_WAIT      4100
  TCP    127.0.0.1:8080         127.0.0.1:2106         CLOSE_WAIT      4100
  TCP    127.0.0.1:8080         127.0.0.1:2113         ESTABLISHED     4100
  TCP    127.0.0.1:8580         0.0.0.0:0              LISTENING       1924
  TCP    127.0.0.1:8580         127.0.0.1:2132         TIME_WAIT       0
  TCP    127.0.0.1:8580         127.0.0.1:2135         ESTABLISHED     1924
  TCP    127.0.0.1:8580         127.0.0.1:2145         TIME_WAIT       0
  TCP    127.0.0.1:8580         127.0.0.1:2146         TIME_WAIT       0
  TCP    127.0.0.1:8580         127.0.0.1:2151         TIME_WAIT       0
  TCP    127.0.0.1:8580         127.0.0.1:2152         TIME_WAIT       0
  TCP    127.0.0.1:9000         0.0.0.0:0              LISTENING       1924
  TCP    127.0.0.1:24367        0.0.0.0:0              LISTENING       1924
  TCP    127.0.0.1:24367        127.0.0.1:1670         ESTABLISHED     1924
  TCP    127.0.0.1:24367        127.0.0.1:2097         ESTABLISHED     1924
  TCP    127.0.0.1:24367        127.0.0.1:2136         ESTABLISHED     1924
  TCP    127.0.0.1:24367        127.0.0.1:2138         ESTABLISHED     1924
  TCP    192.168.0.188:139      0.0.0.0:0              LISTENING       4
  TCP    192.168.0.188:1108     192.168.0.188:1109     ESTABLISHED     4100
  TCP    192.168.0.188:1108     192.168.0.188:1110     ESTABLISHED     4100
  TCP    192.168.0.188:1108     192.168.0.188:1112     ESTABLISHED     4100
  TCP    192.168.0.188:1109     192.168.0.188:1108     ESTABLISHED     4448
  TCP    192.168.0.188:1110     192.168.0.188:1108     ESTABLISHED     4448
  TCP    192.168.0.188:1112     192.168.0.188:1108     ESTABLISHED     4448
  TCP    192.168.0.188:1433     192.168.0.188:1983     ESTABLISHED     1800
  TCP    192.168.0.188:1433     192.168.0.188:2010     ESTABLISHED     1800
  TCP    192.168.0.188:1983     192.168.0.188:1433     ESTABLISHED     4100
  TCP    192.168.0.188:2010     192.168.0.188:1433     ESTABLISHED     4100
  TCP    192.168.0.188:2134     106.38.184.108:80      ESTABLISHED     1108
  TCP    192.168.0.188:2137     218.30.116.73:80       TIME_WAIT       0
  TCP    192.168.0.188:2144     101.226.178.110:80     ESTABLISHED     1108
  TCP    192.168.0.188:2147     117.79.93.210:80       ESTABLISHED     1108
  TCP    192.168.0.188:2155     218.30.118.213:80      TIME_WAIT       0
  TCP    192.168.0.188:2156     220.181.132.88:80      ESTABLISHED     176
  TCP    192.168.0.188:8080     192.168.0.100:62001    CLOSE_WAIT      4100
  TCP    192.168.0.188:8080     192.168.0.100:62121    ESTABLISHED     4100
  TCP    192.168.0.188:8080     192.168.0.100:62123    ESTABLISHED     4100
  TCP    192.168.0.188:8080     192.168.0.100:62256    ESTABLISHED     4100

1433数据库端口正常,8080端口也正常

14:06假死,用jconsole查看内存情况,发现java还在运行当中。




内存完全充足,对里面的每一个线程死锁检测,未检测到死锁,线程也在40左右,
不知道是哪里出现问题。麻烦各位给点意见。


40分
看看线程有没有block的。
tomcat没有error日志,那就是processRequest线程没有挂掉,那么,应该是block住了,jconsole应该会有记录哦

刚刚发现已启动的线程有218个,活动的有40,
不过对于线程检测这方面还不太了解,现在还不知道是不是,还有如何进行检查和修补?
jconsole再哪里可以查找到线程的BLOCK信息,我在线程里看线程堵塞数的确很多,但是,并没有死锁呀!
我上面说错了,在jconsole 的线程里
阻塞总数 和 等待总数 的确很多,是不是指这个呢?
何须死锁,阻塞就要命了啊
谢谢提示,那么一般情况下SSH2项目阻塞是因为什么情况下设计不合理造成的呢?像数据连接池,SESSION都交给SPRING解决,
名称: com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#2
状态:TIMED_WAITING 在 com.mchange.v2.async.ThreadPoolAsynchronousRunner@84bb67 上
阻塞总数:647  等待总数: 1,367

这个都是C3PO的情况造成的阻塞,我的基础DAO层

	@Override
	public List<T> listAll() {
		log.debug("listAll " + this.entityClass + " instance");
		return getSession().createQuery(
				"from " + getEntityName(entityClass) + " as model ").list();
	}
  <filter>
    <filter-name>openSessionInView</filter-name>
    <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>openSessionInView</filter-name>
    <url-pattern>*.do</url-pattern>
  </filter-mapping>

进行控制 的,怎么会造成数据库未释放呢?

spring不熟,等高人来帮忙分析一下。
谢谢提示,对于线程这方面知识还不太了解,这几天看看去,不过现在最重要的是解决一下假死的问题,我希望有高人帮我提点一下对于C3P0的未释放造成的阻塞或数据连接的未释放有几种原因造成的!
不过看了一会线程我怀疑是不是我理解线程BLOCK错了,
jconsole里的 阻塞总数 和 等待总数 的数字跟阻塞没有关系吧?
因为我操作了一会儿程序,发现jvisualvm的Thread Dump里面
"com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#2" daemon prio=6 tid=0x1fd7b400 nid=0x169c in Object.wait() [0x215ef000..0x215efb94]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	- waiting on <0x08b39990> (a com.mchange.v2.async.ThreadPoolAsynchronousRunner)
	at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:534)
	- locked <0x08b39990> (a com.mchange.v2.async.ThreadPoolAsynchronousRunner)

   Locked ownable synchronizers:
	- None

随便复制了一个,未发现
java.lang.Thread.State:  BLOCK 状态的,
还有觉的 jconsole里的 (已启动的线程总数:?64)=(  活动线程:?41) + (已完成的线程数)
就像上面假死一样,线程数只有41个,并没有大量的线程产生!
下面的图用jconsole 查看的线程状态

这帖子好冷清呀!各位看客大侠,麻烦你们给点意见和看法,即使解决不了,我相信通过大家的讨论也能学习到很多知识的!


15分
楼主,我觉得最大的可能是你的C3P0连接池,使用以后连接未释放。

去查一查show processlist; 

是不是hibernate获取到session以后,session没有clear或close?

getSession().createQuery(
            “from ” + getEntityName(entityClass) + ” as model “).list();

这里,你应该是没有关闭session。最后就会导致这个结果。

public List findByPage(Page page) {
Session session = getSession(true);
Criteria cri = session.createCriteria(page.getListClass());
List<Criterion> criterions = page.getParam();
if(criterions != null){
for (int i = 0; i < criterions.size(); i++) {
cri.add(criterions.get(i));
}
}
if(page.getOrder() != null){
cri.addOrder(page.getOrder());
}
if(page.getStart()!=0){
cri.setFirstResult((page.getStart()-1)*page.getLimit());
cri.setMaxResults(page.getLimit());
}
List list = null;
try{
list = cri.list();
}catch(Exception e){
}
session.clear();
session.close();
return list;
}

这是我程序里的公用查询的代码,用的QBC,其实类似于你那个查询,不过也得获取到session,然后查询,最后关闭session啊。


15分
-最好把事务也交给spring管理 ,这样会自动帮你关掉session的.你确定你没有自己手动管理session,比如说你在dao层自己又打开了session,然后关闭,如果都没有的话,那么我觉得可能是这个问题。
 <filter>
    <filter-name>openSessionInView</filter-name>
    <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>openSessionInView</filter-name>
    <url-pattern>*.do</url-pattern>
  </filter-mapping>

我在整合hibernate4的时候发现这个配置完全没有用!至今不知道为什么,我觉得最有可能的就是这里的原因了


25分
用spring管理数据库事务会造成数据源的死锁,无法解决,能不用spring最好还是别用。但你这个我看像tomcat的问题,换个版本或者重新安装一下。
我也看到过关于SPRING事务所造成的文章,好像是说:OpenSessionInViewFilter 也是SPRING写的云云,现在对于这样的问题暂时只能多多设置修改一下TOMCAT增加线程内存配置等等,换换版本看看,

5分
这年头 怎么还getsession 万一有一个session忘了关闭 
我的配置已经完成SPRING管理了,从LOG4J的日志就可以看出
Spring[  Closing Hibernate Session in OpenSessionInViewFilter]
Hibernate [Releasing JDBC connection]
C3PO [trace com.mchange.v2.resourcepool.BasicResourcePool]
[2014-08-01 15:24:41.375] [DEBUG] [http-bio-8080-exec-19] [com.opensymphony.xwork2.interceptor.I18nInterceptor:65] - intercept } 
[2014-08-01 15:24:41.375] [DEBUG] [http-bio-8080-exec-19] [org.springframework.orm.hibernate4.support.OpenSessionInViewFilter:160] - Closing Hibernate Session in OpenSessionInViewFilter
[2014-08-01 15:24:41.375] [DEBUG] [http-bio-8080-exec-19] [org.hibernate.engine.jdbc.internal.LogicalConnectionImpl:232] - Releasing JDBC connection
[2014-08-01 15:24:41.375] [DEBUG] [http-bio-8080-exec-19] [com.mchange.v2.resourcepool.BasicResourcePool:1644] - trace com.mchange.v2.resourcepool.BasicResourcePool@ca8735 [managed: 2, unused: 1, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection@a312c6)
[2014-08-01 15:24:41.375] [DEBUG] [http-bio-8080-exec-19] [org.hibernate.engine.jdbc.internal.LogicalConnectionImpl:250] - Released JDBC connection
[2014-08-01 15:24:41.375] [DEBUG] [http-bio-8080-exec-19] [org.springframework.security.web.access.ExceptionTranslationFilter:115] - Chain processed normally

对于  luodaoren1984 同学,我不推荐这个种方法
自己主动关掉SESSION会将HIBERNATE 关联映射弱化。

C3P0连接池应该是释放掉的。
1.从jconsole线程数,发现只有三个。
2.windows的性能监控图,只有8个

3.通过查看SQL SERVER 2008  查看使用连接数 (语句好多)

SP_WHO ""sa""

SELECT*FROM sys.dm_exec_sessions WHERE host_name IS NOT NULL

SELECT * FROM 
[Master].[dbo].[SYSPROCESSES] WHERE [DBID] 
IN 
(
  SELECT 
   [DBID]
  FROM 
   [Master].[dbo].[SYSDATABASES] 
  WHERE 
   NAME=""minbao""
)

SELECT login_name,COUNT(session_id)AS session_count  
 
FROM sys.dm_exec_sessions  
 
GROUP BY login_name; 

SELECT COUNT(*) AS CONNECTIONS FROM master..sysprocesses 

select connectnum=count(distinct net_address)-1 from master..sysprocesses 

SELECT cntr_value AS User_Connections FROM master..sysperfinfo as p  
WHERE p.object_name = ""SQLServer:General Statistics"" And p.counter_name = ""User Connections"" 

里面有多条查看语句,看的结果没有多大变化。


CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明ssh2 项目 Tomcat 假死