아파치 톰캣 서블릿/JSP 컨테이너

아파치 톰캣 7

Version 7.0.28-dev, Oct 2 2013
Apache Logo

Links

User Guide

참고

아파치 톰캣 개발

JNDI(Java Naming Directory Interface) 데이타베이스 다루는 방법

차례
소개

JNDI 데이타베이스 환경설정은 JNDI-자원-사용법에 (JNDI-Resources-HOWTO) 광범위하게 퍼져있다. 그러나, 톰캣-사용자로 부터 피드백(feedback)중에서, 특히 개인적인 환경설정에 대해 매우 까다롭게 될 수 있다는 것을 보여줬다.

여기 환경설정에 대한 몇가지 예시가 있다. 톰캣 유저들을 위한 대중적인 데이타베이스(databases)와 디비(db)사용법에 대한 몇가지 일반적인 작은 조언들(tips)이 게시되었었다.

환경설정으로부터 얻어낸 주의사항들과(혹은 이나)톰캣-사용자에게 게시된 YMMV(Your Mileage May Vary) -'귀하의 마일리지는 변할 수 있다는 뜻'를 사용자들이 잘 인식해야 한다. 만약 당신이 그밖에 다른 검증된 환경설정을 한다면, 당신은 넓은 분위기에서 사용하는 것을 느낄수도 있고, 아니면 혹시 당신이 우리가 이 부분을 어떤 방법으로든 (환경설정과 관련하여)개선할 수 있다고 느낀다면 우리에게 알려달라.

JNDI 자원 환경설정은 톰캣 5.0.x과 톰캣 5.5.x간에 약간 변했다는 것에 주의하라. 당신은 주로 더 오래된 자원 환경설정을 변경하고, 톰캣 7.x.x에서의 과업을 그들이(환경설정) 제대로 만드는 것을 위해 아래의 예시가 필요할 것이다.

또한, 일반으로 JNDI 데이터소스 설정과, 그리고 특히 이 튜토리얼에서는 여러분이 이후 레퍼런스에 나오는 자동 애플리케이션 배치에 관한 섹션을 포함해서, ContextHost를 읽어서 이해하고 있다고 가정한다는 것을 알아주기 바란다.

드라이버 매니저, 서비스공급자 구조와 메모리 낭비

java.sql.DriverManager 서비스 공급자구조를 지원하는 것이다. 모든 이용가능한 JDBC 드라이버들의 특징은 메타-INF/서비스/자바의 SQL 드라이버(META-INF/services/java.sql.Driver) 파일들을 자동적으로 발견하며 JDBC 드라이버 자신들을 제공하며 나타내는 것이고, 로드(load)하고, 등록하고, 당신이 JDBC접속하기 전, 데이타베이스 드라이버를 불르기 위해 필요한 사람들의 부담을 확실하게 당신으로부터 덜어준다. 하지만, 이러한 것의 실행은 서블릿(servlet)컨테이너 환경에 대한 모든 자바 버전들이 기본적으로 순조롭지 않다. java.sql.DriverManager에서의 문제점은 오직 한번 드라이버들을 자세히 살피는 것이다.

JRE 메모리 낭비 예방 리스너는 아파치 톰캣이 시작하는 동안 드라이버를 자세히 살피기 시작하면서 해결하는 것이 함께 포함된다. 이것은 기본적으로 가능하게 된다. 그것이 의미하는 것은 오직 라이브러리들을 리스너에서 보는 것이다. 예를 들면 각각의 $CATALINA_BASE/lib는 데이타베이스 드라이버들에 대해 자세히 살펴보게 될것이다. 만약 이것의 특징을 당신이 바꿀것을 고려 중이라면, 사용중인 JDBC가 첫번째 웹 프로그램에 의해 사용하게 되는지 보면서 주의 하고, 웹 프로그램이 재실행되고, 다른 웹 프로그램에 대하여 JDBC에 의존하는 것이 실패가 따르는 것도 주의하라.

따라서, 웹 프로그램은 그들의 WEB-INF/lib파일목록에서 서비스공급자 구조에 의존할 수 없고, 드라이버들을 분명하게 등록해야 할 수 있는 내부에서의 데이타베이스 드라이버들을 가지고 있다.

java.sql.DriverManager는 또한 메모리 낭비의 일부라고 알려져 있다. 웹 프로그램에 의해 등록된 어떤 드라이버들은 웹 프로그램이 (작동을)멈추면 반드시 등록을 취소하게 된다. 톰캣은 자동적으로 발견하고 웹 프로그램 클래스 로더에 의해 불려진 어떠한 JDBC 드라이버들의 등록 취소는 웹 프로그램이 멈추었을 때, 시도할 것이다. 그러나, 프로그램들이 프로그램 자신을 위해 ServletContextListener를 통해서 하는 것을 기대하게된다.

데이타베이스 연결 풀(DBCP) 환경설정

아파치 톰캣에서의 기본 데이타베이스 연결 풀 구현은 Apache Commons 프로젝트에서 가져온 라이브러리들에 의존한다. 다음의 라이브러리들이 사용된다:

  • Commons DBCP
  • Commons Pool

이 라이브러리들은 $CATALINA_HOME/lib/tomcat-dbcp.jar의 단 하나의 jar 안에 위치해있다. 그러나 오직 클래스들은 연결 풀링이 포함되는 것을 필요로 하고, 그리고 그런 패키지들은 프로그램들과 간섭하는 것을 피하기 위해 개명하게 되었다.

DBCP 1.4는 JDBC 4.0을 지원한다.

설치

환경설정 인수들의 전체 목록은 DBCP 문서를 보라.

Preventing database connection pool leaks

데이타베이스 연결 풀은 데이타베이스에 여러개의 공통된 접속을 만들고 관리한다. 이미 존재하고 있는 데이타베이스의 접속상태를 다시쓰고 재활용 하는 것이 (데이타베이스를)새롭게 여는것보다 더욱 효율적이다.

여기 공통으로 접속하는 것과 함께 하나의 문제점이 있다. 웹 프로그램은 명확하게 설정한 결과(ResultSet)와 문장(Statement) 그리고 접속(Connection)을 기록하고 종료처리해야 한다. 웹 프로그램의 실수를 차단 하기 위하여 이런 자원들이 절대 웹 프로그램에 재사용을 위해 다시 이용가능하게 끝낼 수 없다(데이타베이스 접속 공통 "낭비"). 만약 더 이상 이용가능한 접속이 없다면, 이것이 결국에는 당신의 웹 프로그램 데이타베이스 접속이 실패로 끝날 수 있다.

이 문제에 대해 하나의 해결책이 있다. 아파치 Commons DBCP는 이런 폐기된 데이타베이스 접속을 회복하고 추적하기 위해 환경설정을 할 수 있게 되었다. 단순히 데이타베이스연결을 회복할 뿐만 아니라, 거기에 개방된 자원들과 결코 차단되지 않은 데이타베이스 연결 코드에 대한 임시기억의 흔적을 찾아낸다.

폐기된 데이타베이스 연결들은 삭제되고, 당신의 DBCP 데이타소스를 위한 Resource 환경설정을 더하며 데이터 처리를 되풀이하며, 뒤따르는 자원에게 돌려주는 것은 DBCP 데이타자원을 설정하기 위해서이다.

removeAbandoned="true"

낮은 실행의 DBCP를 이용가능한 데이타베이스의 연결이 회복하고, 어떤 폐기된 데이타베이스를 연결에서 그것을 찾고, 같은 데이타를 반복하여 처리한다. 기본값은 false이다.

removeAbandonedTimeout을 설정하고 되돌려서 사용하기 위한 일정시간의 데이터베이스 연결은 그것이 고려되어 폐기되기 이전에 작동이 멈추었다.

removeAbandonedTimeout="60"

제거하여 폐기된 접속을 위한 기본 남은시간은 300초이다.

그런 logAbandoned 속성은 순서에 맞고, true 설정되어 질 수 있다. 만약 당신이 DBCP에 파기된 데이타베이스 접속 자원 코드의 일시적인 흔적을 기록하고 싶다면 말이다.

logAbandoned="true"

기본값은 false이다.

MySQL DBCP 예시

0. 소개

MySQL의 버전(판)과 JDBC드라이버는 작업하기 위해 보고되었다.

  • MySQL 3.23.47, MySQL 3.23.47 이노디비를 사용하고 있다(using InnoDB,). MySQL 3.23.58, MySQL 4.0.1알파
  • Connector/J 3.0.11-안정적인 (공식적인 JDBC 드라이버)
  • mm.mysql 2.0.14 (JDBC 드라이버의 오래된 3번째 그룹)

여러분은 이것을 진행하기 전에, $CATALINA_HOME/lib안에 JDBC Driver's jar를 복사하는 걸 잊지 말라.

1. MySQL 환경설정

이것을 따라하면서 변경한다면 문제가 발생할 수 있다는 것을 명심하라.

새로운 시험 사용자를 새로운 데이타베이스와 단 하나의 시험 테이블과 함께 생성하라. 당신의 MySQL 사용자는 반드시 지정된 하나의 암호를 가지고 있어야 한다. 당신이 암호가 없이 접속을 시도하려 한다면 드라이버에 접속실패 할 것이다.

mysql> GRANT ALL PRIVILEGES ON *.* TO javauser@localhost
    ->   IDENTIFIED BY 'javadude' WITH GRANT OPTION;
mysql> create database javatest;
mysql> use javatest;
mysql> create table testdata (
    ->   id int not null auto_increment primary key,
    ->   foo varchar(25),
    ->   bar int);
주의: 테스팅을 마치면 위 사용자는 제거되어야 한다!

다음으로 testdata 테이블에 테스트 데이터를 넣는다.

mysql> insert into testdata values(null, 'hello', 12345);
Query OK, 1 row affected (0.00 sec)

mysql> select * from testdata;
+----+-------+-------+
| ID | FOO   | BAR   |
+----+-------+-------+
|  1 | hello | 12345 |
+----+-------+-------+
1 row in set (0.00 sec)

mysql>

2. Context configuration

2.Context 환경설정

톰캣에서 JNDI 데이타소스는 여러분의 Context에서 당신의 자원을 위해 추가함으로써 나타내며 환경설정한다.

예를 들면:

<Context>

    <!-- maxActive: 데이타베이스 연결 풀의 최대값
  여러분은 확실하게 당신의 mysqld의 엄청난 접속을 충분히 많은 것을, 
  당신의 디비 접속에서의 모든것을 다루기 위해 환경설정하라.
  제한없기 위해 -1값에서 정하라.(0보다 작고,-값에선 무한대기)
         -->
    <!-- maxIdle: 특별한 일 없이 유지하는 데이타베이스 접속풀의 최대 갯수 
  제한없기위해 -1에서 지정하라. 이것을 또한 DBCP 문서에서 보고, 
  minEvictableIdleTimeMillis(사용되지 않는 커넥션을 추출할때 지정한 시간 
  이상 비활성화 상태인 것만 추출하는 최소한의 시간)의 환경설정 매개변수와 
  minEvictableIdleTimeMillis도 그렇게 하라. 
         -->
    <!-- maxWait: ms에서 이용가능케 되기 위한 어떤 데이타베이스 접속을 
    위해 기다리는 최대의 시간, 예를들어 10초 이다. 어떤 예외는 이것이 남는 시간이 
    초과되면 동작된다.
    지정된 시간없이 기다리게 하기 위해서 -1값으로 지정하라.
         -->



 
<!-- 사용자이름과 비밀번호: 데이터베이스 접속을 위한 MySQL 사용자이름과 비밀번호 -->

    <!-- driverClassName: 오래된 mm.mysql JDBC driver를 위한 클래스 이름은 
    org.gjt.mm.mysql.Driver -이다. 우린 Connector/J를 통해 사용하는 것을 추천한다.
    공식적인 MySQL Connector/J 드라이버에 대한 클래스 이름은 com.mysql.jdbc.Driver이다.
         -->


    <!-- url: MySQL 데이타베이스 접속을 위한 JDBC 접속경로. -->


  <Resource name="jdbc/TestDB" auth="Container" type="javax.sql.DataSource"
               maxActive="100" maxIdle="30" maxWait="10000"
               username="javauser" password="javadude" driverClassName="com.mysql.jdbc.Driver"
               url="jdbc:mysql://localhost:3306/javatest"/>

</Context>

3. web.xml의 환경설정

테스트 프로그램을 위해 WEB-INF/web.xml을 지금 만들어보자.

<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
    version="2.4">
  <description>MySQL Test App</description>
  <resource-ref>
      <description>DB Connection</description>
      <res-ref-name>jdbc/TestDB</res-ref-name>
      <res-type>javax.sql.DataSource</res-type>
      <res-auth>Container</res-auth>
  </resource-ref>
</web-app>

4. 테스트 코드

이제 나중에 사용하기 위해 간단한test.jsp를 지금 만들어보자.

<%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<sql:query var="rs" dataSource="jdbc/TestDB">
select id, foo, bar from testdata
</sql:query>

<html>
  <head>
    <title>DB Test</title>
  </head>
  <body>

  <h2>Results</h2>

<c:forEach var="row" items="${rs.rows}">
    Foo ${row.foo}<br/>
    Bar ${row.bar}<br/>
</c:forEach>

  </body>
</html>

이 JSP페이지는 JSTL's SQL과 핵심 태그라이브러리에 사용된다. You can get it from 여러분은 아파치 톰캣 태그라이브러리 - 표준 태그 라이브러리 프로젝트 —로부터 얻을 수 있고, 당신은 확실히 1.1.x release를 얻을 수 있다. 당신이 JSTL을 얻으면, jstl.jarstandard.jar를 당신의 web app's WEB-INF/lib의 디렉토리에 복사하라.

마지막으로 여러분의 웹 앱안에 $CATALINA_BASE/webapps 워파일(warfile)이라 불리는 DBTest.war이나 DBTest라고 불리는 하위 디렉토리안에 파일들을 배치하라.

배치하고 하면, http://localhost:8080/DBTest/test.jsp에서 브라우저를 당신의 결과물을 보기위해 지정하라.

오라클 8i, 9i & 10g

0. 소개

오라클은 MySQL 환경설정의 통상적인 사용법을 제외하고 나서, 최소한의 변화가 요구된다. :-)

드라이버는 오라클의 오래된 버전을 위해서 *.jar 파일보다 오히려 *.zip 파일이 더 배포되었을 수도 있다. 톰캣은 오직$CATALINA_HOME/lib안에서 설치된 *.jar파일을 사용하는 프로그램 일 것이다. 그러므로, classes111.zip이나 classes12.zip.jar의 확장명으로의 개명이 필요하게 될 것이다. jarfiles이 zipfiles이기 때문에, 이 jar파일들의 압축을 풀지않아도 되고, 간단한 개명으로 언급할 것이다.

오라클 9i의 사용을 위하여 사용자는 앞으로 oracle.jdbc.driver.OracleDriver보다 oracle.jdbc.OracleDriver를 오라클이 제시했던 것처럼 대로 사용해야 한다. oracle.jdbc.driver.OracleDriver는 덜 친숙했었고, 이것의 드라이버 클래스를 지원한 다음 주요 릴리즈에서 계속 사용되지 않을 것이다.

1. 컨텍스트 환경설정

mysql 환경설정안에서의 비슷한 방식으로, 사용자는 사용자의 Context에서 사용자의 데이타소스를 정의할 필요가 있다. 여기서 우리는 하나의 데이타소스를 myoracle(마이 오라클)이라고 정의하고 유저 스캇으로 연결하기 위해 내장된 드라이버(thin driver)에서 사용중에 있다. 비밀번호는 mysid라고 불려지는 sid에서 타이거(tiger)라고 되어 있다.(주의사항: 내장된 드라이버(thin driver)와 sid(Segment IDentifier)는 tnsname이 동일하지 않다.) 스키마는 기본적인 스키마로 사용자 스캇을 위해 사용될 것이다.

1. 컨텍스트 환경설정

oci안에의 URL주소에서 변하는 저사양고객(changing thin)에 분명하게 포함되어야 한다.

<Resource name="jdbc/myoracle" auth="Container"
              type="javax.sql.DataSource" driverClassName="oracle.jdbc.OracleDriver"
              url="jdbc:oracle:thin:@127.0.0.1:1521:mysid"
              username="scott" password="tiger" maxActive="20" maxIdle="10"
              maxWait="-1"/>

2. web.xml 환경설정

사용자는 web.xml 파일을 프로그래밍 할때, DTD에 의한 요소의 정리법을 정의한 것을 반드시 우선순위로 삼아야 한다.

<resource-ref>
 <description>Oracle Datasource example</description>
 <res-ref-name>jdbc/myoracle</res-ref-name>
 <res-type>javax.sql.DataSource</res-type>
 <res-auth>Container</res-auth>
</resource-ref>

3. 코드 환경설정

사용자는 위와 같이(사용자가 만든 필수적인 DB인스턴스나 테이블 등.) 대체가능한 데이타소스코드와 이런 비슷한 종류와 함께 동일하게 예시된 어플리케이션을 사용할 수 있다.

Context initContext = new InitialContext();
Context envContext  = (Context)initContext.lookup("java:/comp/env");
DataSource ds = (DataSource)envContext.lookup("jdbc/myoracle");
Connection conn = ds.getConnection();
//etc.
PostgreSQL

0. 소개

PostgreSQL은 오라클에서 유사한 방법으로 설정되있다.

1. 필요한 파일들

$CATALINA_HOME/lib의 장소에 Postgres JDBC jar를 복사하라. 오라클과 함께, 복사한 자르(jars)파일은 그것들로 하여금 DBCP's Classloader를 찾기 위해서 해당폴더안에 있어야 한다. 이 설정은 사용자의 원활한 진행을 위해 필요하다.

2. 자원(Resource) 환경설정

여기서도 역시 사용자에게 2가지 선택권이 있다:모든 톰캣 어플리케이션 쪽에 데이타소스를 정의하여 공유시키거나 하나의 어플리케이션을 위해 특별한 데이타소스를 정의하는 것이다.

2a. 공유된자원 환경설정

사용자가 데이타소스(다양하게 공유되는 톰캣 어플리케이션)를 정의하길 바란다면 이런 옵션을 사용하거나, 사용자가 파일안에서 사용자의 데이타소스를 정의하는 것을 선호할 것이다.

저자가 이 경우에 성공한 적이 없었다., 비록 다른 사람들이 제시했어도 말이다. 여기 분명하게 제시한다.

<Resource name="jdbc/postgres" auth="Container"
          type="javax.sql.DataSource" driverClassName="org.postgresql.Driver"
          url="jdbc:postgresql://127.0.0.1:5432/mydb"
          username="myuser" password="mypasswd" maxActive="20" maxIdle="10" maxWait="-1"/>

2b. 어플리케이션 특수자원 환경설정

만약 사용자의 어플리케이션에서 그 자신이 특별하게 데이터소스를 정의하길 바란다면, 다른 톰캣 어플리케이션에 보이지 않는 옵션을 사용하라. 이 방법은 사용자의 톰캣 설치에 있어서 작은 간섭이 필요하다.

사용자의 컨텍스트를 위해 리소스 정의를 만들어라. 제시한 컨텍스트 요소는 아래와 같이 뭔가를 봐야한다.

<Context>

<Resource name="jdbc/postgres" auth="Container"
          type="javax.sql.DataSource" driverClassName="org.postgresql.Driver"
          url="jdbc:postgresql://127.0.0.1:5432/mydb"
          username="myuser" password="mypasswd" maxActive="20" maxIdle="10"
maxWait="-1"/>
</Context>

3. web.xml 환경설정.

<resource-ref>
 <description>postgreSQL Datasource example</description>
 <res-ref-name>jdbc/postgres</res-ref-name>
 <res-type>javax.sql.DataSource</res-type>
 <res-auth>Container</res-auth>
</resource-ref>

4. 데이타소스에 접근하는 것.

데이타소스 프로그램에 맞게 접근 할 때, 사용자의 JNDI 룩업에 java:/comp/env을 넣는 것을 기억하면서, 코드의 작은부분도 따라하라. 또한 주의할 것이 있는데, "jdbc/postgres"는 사용자의 선호에 따라서 함께 대체될 수 있고, 또한 제공된 것을 사용자가 정의된 파일소스 내에서 바꾸는 것을 말한다.

InitialContext cxt = new InitialContext();
if ( cxt == null ) {
   throw new Exception("Uh oh -- no context!");
}

DataSource ds = (DataSource) cxt.lookup( "java:/comp/env/jdbc/postgres" );

if ( ds == null ) {
   throw new Exception("Data source not found!");
}
DBCP 이외의 해결책들

이런 해결책들은 하나의 단순한 연결로 데이터베이스에 사용하거나(시범 이외의 다른 어떤 것도 추천하지 않는다!) 몇몇 다른 풀링(Pooling)기술이다.

오라클 8i과 OCI 고객
소개

윌스트(Whilst)는 모호하게 OCI 클라이언트가 사용하는 JNDI 데이터소스의 탄생을 언급하지 않고, 이런 점들을 오라클과 DBCP 해결책 위에 조합하게 되었다.

OCI 드라이버의 사용을 위해서, 사용자는 설치된 오라클 클라이언트를 가지고 있어야 한다. 그리고 사용자는 cd에서 오라클8i(8.1.7) 클라이언트를 설치했어야 하고, 적용가능한 JDBC/OCI driver(Oracle8i 8.1.7.1 JDBC/OCI Driver)를 otn.oracle.com 에서 다운 받아야 한다.

그 다음에, classes12.zip파일을 classes12.jar으로 톰캣에서 정정하고, $CATALINA_HOME/lib에 복사하여 넣어야 한다. 사용자는 톰캣과 JDK의 버전에 이런 파일로부터 종속하고 있는 javax.sql.*클래스들을 또한 제거해야 할수도 있다.

모든 것을 다같이 대입할때

당신이 ocijdbc8.dll.so를 당신의 $PATHLD_LIBRARY_PATH에 (가능하다면 $ORAHOME\bin안에)확실히 가지고 있으면, 원래 라이브러리에 사용하고 있는 System.loadLibrary("ocijdbc8");에 단순한 테스트 프로그램에 의해 적재되어질 수 있다.

사용자는 간단한 테스트용 서블릿을 만들거나 jsp에 만들어야 한다. You should next create a simple test servlet or jsp that has these 크리스탈 라인:

DriverManager.registerDriver(new
oracle.jdbc.driver.OracleDriver());
conn =
DriverManager.getConnection("jdbc:oracle:oci8:@database","username","password");

데이타베이스의 형식(host:port:SID)이고, 만약에 지금 사용자가 사용자의 시험용 servlet/jsp의 URL에 접근하는 것을 시도한다면, 사용자가 java.lang.UnsatisfiedLinkError:get_env_handle의 근원과 함께 ServletException을 획득한다.

첫째로, UnsatisfiedLinkError는 사용자가 다음의 상황에 처해있다는 것을 알려준다.

  • 사용자의 JDBC 파일과 사용자의 오라클 클라이언트 버전(client version)이 일치하지 않는다는 것이다. 그것은 라이브러리 파일을 찾을 수 없게되었다는 메세지에서 명시한다. 예를 들어, 사용자는 오라클 버전 8.1.5와 함께 오라클 버전 8.1.6버전부터 클래스12 파일(classes12.zip file)을 사용하고 있을지도 모른다. 이런 클래스xxx파일(classeXXXs.zip file)과 오라클 클라이언트 소프트웨어 버전은 반드시 일치해야 한다.
  • A $PATH, LD_LIBRARY_PATH의 문제.
  • 이것으로서 당신이 otn과 $ORAHOME\jdbc\lib에서 작동할 그 디렉토리로부터 사용하고 있는 클래스12 압축파일에 대해 설명되었다.

다음으로 사용자는 ORA-06401 NETCMN: invalid driver designator에러에 대하여 경험할 수도 있다.

오라클 문서는 "원인: 로그인(연결)문자는 유효하지 않은 드라이버 설계자를 포함한다. 지침행동: 문자와 다시제출하고 연결하라." 이렇게 제시할 것이다. 데이타베이스 연결 문자를(host:port:SID의 양식에서) 다음과 같이 바꾸어라. (description=(address=(host=myhost)(protocol=tcp)(port=1521))(connect_data=(sid=orcl)))

Ed.흠, 나는 만약에 사용자가 사용자의 TNSNames를 정리하는 것이 정말로 필요하지 않는다고 봐요. 오라클 데이터베이스 관리자가 아니니까요:-)

공통적인 문제들

여기에 몇가지 공통적인 문제들이 웹 어플리케이션과 함께 데이터베이스를 사용할 때와 그것들을 어떻게 해결하는가에 있다.

간간이 발생하는 데이터베이스 연결 실패

톰캣은 자바버츄얼머신(JVM)안에서 운영한다. 이 JVM은 주기적으로 가비지 콜렉션(GC)에서 더이상 사용되어 지지 않는 자바 객체들을 지우기 위하여 운영한다. JVM을 톰캣 프리즈(freezes)안에서 코드의 실행을 위해 운영할 때, 만약 데이터베이스 연결의 설정을 위해 최대 환경설정 시간은 GC의 시간의 총량보다 적다면 사용자는 데이터베이스 연결 획득 실패할 수 있다.

장기간에 걸친 불필요한 정보정리(garbage collection)에서 자료를 모으기 위한것은 톰캣을 시작할 때, -verbose:gc 독립변수를 당신의 CATALINA_OPTS환경에 추가로 가져가고 있는 것이다. 어지러운 gc(garbage collection)는 당신의 $CATALINA_BASE/logs/catalina.out 로그 파일이 장기간에 걸친 gc를 가져가는 것에 포함하면서 모든 불필요한 정보정리를 위해 자료를 포함할 것이다.

사용자의 JVM의 해당 시간에 99% 가깝게 조정된 GC는 1초보다 적게 걸린다. 나머지는 오직 몇초만이 걸릴 것이다. 드물게도, 언제든지 GC가 10초 보다 더욱 GC를 가져가야 한다.

디비 접속 시간초과는 10~15초로 되어 있는것을 확실히 해라. 이런 DBCP(DataBase Connection Pool)를 위하여 사용자는 maxWait의 사용중인 인자값을 정하라.

무작위의 접숙과 닫혀진 예외들

이런 것들은 어떤 요청있어서 디비접속의 이런 접속 풀(Pool)과 2것을 다시 닫을 때로부터 발생할 수 있다. 이런 접속 풀을 사용할 때, 접속했던 접속을 닫고 다른 요청으로 재사용을 하기 위해, 해당 풀로 다시 돌아오라. 그렇게 한다면 접속이 닫히지 않는다. 그리고 톰캣은 다중 쓰레드로 동시발생 요청을 다루기 위해 사용한다. 여기에서 톰캣 내부의 에러의 원인에 대한 이벤트 발생의 예문이 제시되있다.

  하나의 요청, 1번째 쓰레드 안의 1개의 실행중인 디비 접속.

  하나의 요청이 디비 접속을 닫는다.

  JVM(자바 버츄얼 머신)이 실행중인 1번째 쓰레드를 2번째 쓰레드로 전환한다.

  2번째 쓰레드 안에서 실행중인 2번째 요청이 디비 접속을 한다.
  (이 동일한 디비 접속은 1번째 요청에 의해 종료했다.).

  JVM은 운영중인 쓰레드(2번째 쓰레드)를 1번째 쓰레드에게 되돌려준다.

  1번째 쓰레드는 마지막 블록안에서 2번 디비 접속을 종료한다.

  JVM 2번째 쓰레드에게 운영중인 쓰레드(1번째 쓰레드)를 전환한다.

  2번째 요청의 2번째 쓰레드는 디비 접속을 사용하려 시도하지만, 1번째 요청으로 닫혀있어서 실패한다.
  

커넥션 풀에서 데이터베이스를 사용하기 위한 적절하게 쓰여진 코드의 예제가 여기 있다.

  Connection conn = null;
  Statement stmt = null;  // Or PreparedStatement if needed
  ResultSet rs = null;
  try {
    conn = ... get connection from connection pool ...
    stmt = conn.createStatement("select ...");
    rs = stmt.executeQuery();
    ... iterate through the result set ...
    rs.close();
    rs = null;
    stmt.close();
    stmt = null;
    conn.close(); // Return to connection pool
    conn = null;  // Make sure we don't close it twice
  } catch (SQLException e) {
    ... deal with errors ...
  } finally {
    // Always make sure result sets and statements are closed,
    // and the connection is returned to the pool
    if (rs != null) {
      try { rs.close(); } catch (SQLException e) { ; }
      rs = null;
    }
    if (stmt != null) {
      try { stmt.close(); } catch (SQLException e) { ; }
      stmt = null;
    }
    if (conn != null) {
      try { conn.close(); } catch (SQLException e) { ; }
      conn = null;
    }
  }
컨텍스트와 글로벌네이밍리소스(GlobalNamingResources)

비록 위의 지시한 장소가 JNDI 선언장소의 컨텍스트 요소 내부일지라도, 그것은 가능하고 때때로 바람직하게 서버 환경설정파일의 GlobalNamingResources부분에 이런 선언들을 위치시키는 것에 유의하라. 해당 자원은 글로벌네이밍리소스 부분에 위치며 있으며 서버의 컨텍스트 중에서 공유될 것이다.

JNDI 자원의 정의와 범위의 상호작용

작업 공간을 얻기 위하여, 이 공간은 반드시 정의된 <GlobalNamingResources>나 or <Context> 부분에서 데이타소스를 참조하여야 하며 사용하고 있는 재정의된 <ResourceLink>는 안된다.


Copyright © 1999-2013, Apache Software Foundation