老项目采用tomcat出现异常:Connection reset by peer: socket write error 异常解决方法
项目一段时间就出现异常,导致无法登陆系统,数据库无法连接上
异常信息如下:
java.sql.SQLException: Io 异常: Connection reset by peer: socket write error at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:134) at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:179) at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:333) at oracle.jdbc.driver.OracleConnection.rollback(OracleConnection.java:1380) at com.newland.So.Transaction.executeQuery(Transaction.java:107) at com.newland.Dao.UserInfoDao.findUser(UserInfoDao.java:184) at com.newland.Blo.UserInfoBlo.findUser(UserInfoBlo.java:119) at org.apache.jsp.loginAction_jsp._jspService(loginAction_jsp.java:111) at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70) at javax.servlet.http.HttpServlet.service(HttpServlet.java:723) at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:388) at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:313) at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:260) at javax.servlet.http.HttpServlet.service(HttpServlet.java:723) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at com.newland.So.EncodeFilter.doFilter(EncodeFilter.java:32) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:620) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489) at java.lang.Thread.run(Thread.java:744)
解决过程:
出现上面的异常时因为tomcat的conf/context.xml没有加入数据库断开重连配置,配置如下(红字部分):
<Context> <!-- Default set of monitored resources --> <WatchedResource>WEB-INF/web.xml</WatchedResource> <!-- Uncomment this to disable session persistence across Tomcat restarts --> <!-- <Manager pathname="" /> --> <!-- Uncomment this to enable Comet connection tacking (provides events on session expiration as well as webapp lifecycle) --> <!-- <Valve className="org.apache.catalina.valves.CometConnectionManagerValve" /> --> <!--join break line reconnection config--> <span style="color:#ff0000;"><parameter> <name>validationQuery</name> <value>SELECT COUNT(*) FROM DUAL</value> </parameter> <parameter> <name>testOnBorrow</name> <value>true</value> </parameter> <parameter> <name>testOnReturn</name> <value>true</value> </parameter> <parameter> <name>testWhileIdle</name> <value>true</value> </parameter></span> </Context>
配置完成重启还是会出现错误,怎么办呢,考虑用连接池获取连接的方式替代原来的jdbc连接,我选用了C3P0
下面是部分关键代码:
dataSource = new ComboPooledDataSource(); dataSource.setUser(ConnUserName); dataSource.setPassword(ConnPassWord); dataSource.setJdbcUrl(ConnUrl); dataSource.setDriverClass("oracle.jdbc.driver.OracleDriver"); dataSource.setInitialPoolSize(initialPoolSize); dataSource.setMinPoolSize(minPoolSize); dataSource.setMaxPoolSize(maxPoolSize); dataSource.setMaxStatements(maxStatements); dataSource.setMaxIdleTime(maxIdleTime);
//连接池 if(dataSource!=null){ conn = dataSource.getConnection(); }
用这种方式暂时解决了问题,至少不会出现登录不了系统的情况了
然后接着几天又出现问题了,登录不了了,重新想办法,设置连接池配置,不靠谱,因为IO断了,重连有问题,还是自己改程序吧
添加异常自动重连,以下是initDataSource关键代码,其他数据库连接的简单写法就不写了:
//如果是重连的,获取连接池的连接 try { conn = dataSource.getConnection(); conn.setAutoCommit(false); } catch (SQLException e) { e.printStackTrace(); reConnect();//自动重连 }
/** 如果初始化数据库失败无限次重连,直到连接成功为止 * 为了解决异常:java.sql.SQLException: Io 异常: Connection reset by peer: socket write error */ public static void reConnect() { while (true) { if (conn == null) { logger.info("-----------------start reinit dataSource-----------------"); Transaction.initDataSource(); } else { break; } } }
/** * 查询数据,conn为空就自动重连 * @param qstr * @return * @throws SQLException */ public ResultSet executeQuery(String qstr) throws SQLException{ ResultSet cResultSet = null; try{ if(conn==null ){ reConnect(); } stmt = conn.createStatement(); cResultSet = stmt.executeQuery(qstr); } catch(SQLException e) { stmt.close(); conn.rollback(); throw e; } return cResultSet; } /** * 数据更新,conn为空就自动重连 * @param qstr * @throws SQLException */ public void executeUpdate(String qstr) throws SQLException{ try{ if(conn==null ){ reConnect(); } stmt = conn.createStatement(); stmt.executeUpdate(qstr); stmt.close(); } catch(SQLException e) { stmt.close(); conn.rollback(); throw e; } }
在系统登录模块异常注入重连机制:
catch(SQLException e){ e.printStackTrace(); Transaction.initDataSource(); }
不知其他人是否有更好的方法来解决此类问题