다수의 사용자가 사용하는 WAS 환경에서는 서비스가 지연되는 경우가 많다.
그 중에서 DB Connection Pool의 모든 Connection이 사용되거나 반납되지 않아
지연됐을 때의 로그와 그 해결책을 기록한다.
1. ConnectionPool 설정
현재 ConnectionPool의 min : 1, max : 3, step : 1로 설정되었다.
Wait free Connection은 모든 Connection이 사용 중일 때에
1) idle한 Connection이 나올때 까지(Enable Wait : true) - 얼마동안(Wait Time) 기다릴 것인지 아니면
2) 일회성의 Connection을 생성 후 사용(Enable Wait : false)할 것인지
설정 한다.
Connection Leak이 있을 경우 세션이 상당 수 생성될 수 있기 때문에 Enable Wait은 true로 설정한다.
2. Connection Pool 사용 테스트
SelectTable.jsp를 아래와 같이 정상적인 코드를 작성한다.
<%@page import="java.sql.Statement"%> <%@page import="java.sql.ResultSet"%> <%@page import="java.sql.Connection"%> <%@page import="javax.naming.InitialContext"%> <%@page import="javax.sql.DataSource"%> <%@page import="javax.naming.Context"%> <%@ page language="java" contentType="text/html; charset=EUC-KR" pageEncoding="EUC-KR"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=EUC-KR"> <title>SelectTable</title> </head> <body> <% Context ctx = null; DataSource ds = null; Connection con = null; Statement stmt = null; ResultSet rs = null; try { ctx = new InitialContext(); ds = (DataSource)ctx.lookup("TmaxDB"); con = ds.getConnection(); stmt = con.createStatement(); String sql = "SELECT * FROM tb_DUMMY WHERE ROWNUM=1"; rs = stmt.executeQuery(sql); while (rs.next()){ out.println("ID : " + rs.getInt(1) + ", VAL_A : " + rs.getString(2) + ", VAL_B : " + rs.getString(3) + ", VAL_C : " + rs.getString(4)); } } catch (Exception e) { e.printStackTrace(); } finally { if (con != null) con.close(); if (stmt != null) stmt.close(); if (rs != null) rs.close(); } %> </body> </html> |
Connection Leak을 발생시키기 위해 finally에 con.close() 코드를 주서처리한다.
서비스 호출시 아래와 같이 "The resources were not closed" 로그가 발생된다.
subject에 호출 url이 나오므로 해당 소스를 수정하면 된다.
또 JEUS에서 Leak이 발생된 Resource 들을 자동으로 처리해주는 설정이 있다.
Servers 메뉴 -> 해당 ManagedServer 선택 -> Basic 탭의 "Action On Resource Leak" 설정이며 기본값은 Warning이며 위와 같이 로그만 남긴다.
Auto Close 값으로 설정하면 로그를 남기고 Connection을 Close 해준다.
No Action 값으로 설정하면 로그를 남기는 것을 포함 아무런 동작도 하지 않는다.
Connection Leak이 발생되어 가용한 Connection이 없는 경우에
Enable Wait 설정으로 인해 아래와 같이 WaitTimeoutException이 발생된다.
해결책으로는 Worker Thread의 갯수와 Connection Pool의 갯수가 같게끔 설정하여 병목현상을 없애거나 Connection Leak이 발생될만한 요소를 제거한다.
[2017.01.09 23:51:30][1] [ftech1_jjoo-68] [JDBC-0363] Getting the physical connection from the pool [TmaxDB] failed. <<__Exception__>> jeus.jdbc.connectionpool.WaitTimeoutException: A timeout occurred: TmaxDB at jeus.jdbc.connectionpool.ConnectionPoolImpl.throwWaitTimeoutException(ConnectionPoolImpl.java:437) at jeus.connector.pool.PhysicalConnectionPool.waitAndGetPhysicalConnection(PhysicalConnectionPool.java:587) at jeus.connector.pool.PhysicalConnectionPool.getPhysicalConnection(PhysicalConnectionPool.java:438) at jeus.jdbc.connectionpool.ConnectionPoolImpl.innerGetConnection(ConnectionPoolImpl.java:241) at jeus.jdbc.connectionpool.ConnectionPoolImpl.getConnection(ConnectionPoolImpl.java:217) at jeus.jdbc.connectionpool.DataSourceWrapper.getConnection(DataSourceWrapper.java:50) at jeus_jspwork._700_SelectTable_5fjsp._jspService(_700_SelectTable_5fjsp.java from InMemoryJavaFile:97) at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70) at javax.servlet.http.HttpServlet.service(HttpServlet.java:847) at jeus.servlet.jsp.JspServletWrapper.executeServlet(JspServletWrapper.java:78) at jeus.servlet.engine.ServletWrapper.execute(ServletWrapper.java:149) at jeus.servlet.jsp.JspServletWrapper.execute(JspServletWrapper.java:51) at jeus.servlet.engine.RequestProcessor.run(RequestProcessor.java:211) at jeus.util.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:1211) at jeus.util.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:1261) at jeus.servlet.engine.WebThreadPoolExecutor$WebRequestWorker.run(WebThreadPoolExecutor.java:340) at java.lang.Thread.run(Thread.java:662) <<__!Exception__>> |