98..Etc/Tomcat2012. 5. 8. 15:11
반응형

자세한 히스토리는 모르겠지만 Tomcat 모니터링 툴인 Lambda Probe의 개발이 중단되고, 현재는 구글에서 PSI Probe로 계속 진행이 되고 있습니다.
http://code.google.com/p/psi-probe/ 이 사이트에 가면 다운로드 및 설치 매뉴얼이 있으니참조하시기 바랍니다.

설치

  1. 최신 버전을 다운로드 받으신 후 압축을 풀면  probe.war 파일이 생성됩니다.
  2. Tomcat의 Manager GUI에 접속하셔서 War file to deploy에 probe.war 파일을 선택하고 deploy 버튼을 누르면 자동으로 Application이 설치가 됩니다.

    deploy probe

    deploy probe

  3. tomcat_home/webapps에 보시면 probe라는 디렉토리가 생성이 되어 있는걸 확인할 수 있습니다.
  4. http://domain_name/probe 에 접속해서 tomcat-users.xml에 설정한 manager의 id/pwd로 접속하여 사용하면 됩니다.
probe

probe

상단 메뉴->System Information 을 클릭한 후, 우측메뉴-> memory utilization을 클릭하면
아래와 같이 JVM memory 상태를 확인할 수 있다.
 




출처: http://dukeom.wordpress.com/2011/08/08/psi-probe-tomcat-%EB%AA%A8%EB%8B%88%ED%84%B0%EB%A7%81-%ED%88%B4/

Posted by 1010
98..Etc/Tomcat2011. 12. 19. 11:37
반응형

윈도우용 설정

%root%\bin
setenv.bat 파일 생성후

set JAVA_OPTS=-Xms256m -Xmx512m

이거 적어줌..

그리고 startup.bat 실행

질답.

1. 어플리케이션 서버에서 필요한 메모리 계산 방법
- 계산식 : (MaxProcessMemory - JVMMemory - ReservedOsMemory) / (ThreadStackSize) = Number of threads
- 메모리 계산 예
가정 : Java 1.5를 사용중이며 OS가 120MB를, 디폴트 스택사이즈는 0.5M
  • JVM에 1.5GB할당되었을 경우 : (2GB-1.5Gb-120MB)/(1MB) = ~380 threads
  • JVM에 1.0GB할당되었을 경우 : (2GB-1.0Gb-120MB)/(1MB) = ~880 threads
통계적으로 대략 200명의 동시 사용자 수용할 경우 300MB정도 필요하합니다. 이것을 고려해서 메모리를 계산하면 됩니다.

2. Application Server 에러 대처 방안(java.lang.OutOfMemoryError: PermGen space 현상)
  • Tomcat의 경우 v6.0.14이상의 안정적 릴리즈 된것을 선택
  • JDK1.4보다는 1.5, 1.6의 사용을 권고함
  • -XXMaxPermSize 설정을 통해 perm 사이즈를 증가시킴
  • JHat으로 메모리릭 원인을 찾고 JConsole, Lambda probe 등을 통해 메모리 모니터링을 함
  • Application Server운영자는 Garbage Collection에 대한 이해가 있어야 함

3. Tomcat에서 설정 예시

  • 힙메모리 정보를 출력 : -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC

위 설정을 통해 출력되는 로그를 보고 New Generation의 eden 영역, Old Generation 영역, Permanent 영역을 확인하여 각 영역이 작으면 아래와 같은 설정으로 적당 사이즈를 확보해 줍니다.

  • 도출된 설정 : -Xms256m -Xmx512m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:MaxPermSize=128m -XX:SurvivorRatio=5
    -Xms : 최소 힙 싸이즈
    -Xmx : 최대 힙 싸이즈
    -XX:NewSize : New Generation의 최소 싸이즈
    -XX:MaxNewSize : New Generation의 최대 싸이즈
    -XX:MaxPermSize : Permanent Generation의 최대 싸이즈 가 되겠다.
    -XX:SurvivorRatio : 영역비율(New Generation)

결론적으로 적용할 설정은 아래와 같습니다.

  • CATALINA_OPTS="-server -Xss256k -Xms256m -Xmx512m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:MaxPermSize=128m -XX:SurvivorRatio=5 -XX:ReservedCodeCacheSize=128m -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -Djava.net.preferIPv4Stack=true -Djava.awt.headless=true "

Open Soure는 100% 안정적이지 않기 때문에 가장 최신의 안정적인 버젼이 릴리즈되는지 항상 예의 주시하여 버전업에 게을러서는 안됩니다

출처 : http://kiboom.tistory.com/7

Posted by 1010
98..Etc/Tomcat2009. 12. 9. 13:28
반응형

보통 톰캣으로 서비스 구축할 때 안정적으로 서비스하려면 한 서버에 톰캣을 4개 정도 구동시켜야 한다고 하던데 ㅎㅎ
http://www.ibm.com/developerworks/kr/li ··· 61017%2F

웹 개발자에게 있어 톰캣은 JSP를 배우거나 간단한 테스트를 하는 정도의 웹 컨테이너로 생각하는 경우가 많다. 하지만 근래 들어 기업 및 대형 포탈에서 상용 서비스를 위한 웹 컨테이너로서 톰캣을 선택해, 성공적으로 적용한 사례들이 늘고 있다. 톰캣에서 안정적인 웹 서비스를 제공하기 위해서 지원하는 기능은 5가지가 있다. 아파치 웹서버와 연동, 로드밸런싱, 세션 클러스터링, 데이터베이스 처리, 모니터링 및 관리 등이 그것이다.
이 문서에서는 로드밸런싱과 세션 클러스터링 위주로 설명을 할 것이며, 다음에 기회가 된다면 다른 부분에 대해서도 자세히 알아보도록 하겠다.

아파치 웹 서버와 톰캣의 연동

일반적으로 정적인 페이지를 서비스할 때는 웹서버가 훨씬 더 좋은 성능을 발휘한다. 또한 이렇게 역할 분담을 함으로 톰캣에 가중되는 부하를 줄여주는 효과도 얻을 수 있다. 아파치웹서버와 톰캣을 연동하는 것을 일반적으로 ‘커넥터(Connector)'라고 부르며, 여기에는 WARP 커넥터, JK 커넥터 그리고 JK2 커넥터가 있다. 이중에서 WARP와 JK2는 공식 커넥터에서 제외되었고 현재 남아 있는 것은 JK 커넥터뿐이다. 그럼 먼저 JK 커넥터를 이용해서 아파치 웹서버와 톰캣을 연동해 보도록 하겠다.
아파치 웹사이트에서 바이너리 혹은 소스 코드를 다운로드 받도록 하자. 유닉스 혹은 리눅스는 mod_jk.so이며 윈도우용은 mod_jk.dll이다. 이 파일을 아파치 웹서버의 modules 디렉토리에 저장한다(주의, 아파치 웹서버를 컴파일해서 사용하는 경우는 컴파일시에 DSO 기능이 가능하도록 설정해줘야 한다). 저장을 한 후에 아파치 웹서버에 해당 모듈을 인식시켜야 하며 아파치 웹서버의 httpd.conf 파일에 다음 내용을 추가하도록 하자.

리스트 1. httpd.conf

        ...
LoadModule jk_module modules/mod_jk.so    # 모듈 추가
JkWorkersFile "conf/workers.properties"   # JK 설정 파일 위치 및 이름
 
JkLogFile "logs/mod_jk.log"               # JK에 대한 로그 파일 위치
JkLogLevel info                           # 로그 레벨 지정
JkLogStampFormat "[%a %b %d %H:%M:%S %Y]"   # 로그 시간 포맷 지정
JkRequestLogFormat "%w %V %T"             # 로그 내용 포맷
JkMount /* loadbalancer                   # URL 링크 -> 모든 요청을 톰캣으로 지정
JkMount /servlet/* loadbalancer           # URL 링크 -> servlet 요청을 톰캣으로 지정
...

위와 같은 설정을 하게 되면 아파치 웹서버로 들어온 모든 요청을 톰캣으로 재전송 하게 된다. 만일 JSP와 서블릿만 톰캣에서 서비스를 하고 나머지는 아파치 웹서버에서 서비스 하고자 한다면 다음과 같이 수정하면 된다.

  
JkMount /*.jsp loadbalancer                # URL 링크 -> *.jsp 요청을 톰캣으로 지정 
JkMount /servlet/* loadbalancer           # URL 링크 -> servlet 요청을 톰캣으로 지정 

httpd.conf에는 위의 내용이 전부이다. 그럼 이제 workers.properties 파일을 작성해 보도록 하겠다. 이 파일이 실제 로드밸런싱을 위한 설정이 되겠다.


위로

라운드 로빈 방식의 로드밸런싱 설정

톰캣에서 제공하는 로드밸런싱은 정확히 톰캣 자체에서 제공하는 것이 아니라 아파치 웹서버와 연동되는 커넥터에 의해서 제공된다(로드밸런싱은 JK, JK2 커넥터에서만 제공된다). 현재는 라운드 로빈(Round Robin) 방식만이 제공되며 로드밸런싱에 대한 설정은 workers.properties 파일에서 정의하게 된다.

리스트 2. workers.properties

  
worker.list=tomcat1, tomcat2, loadbalancer
 
worker.tomcat1.type=ajp13
worker.tomcat1.host=localhost
worker.tomcat1.port=11009
worker.tomcat1.lbfactor=100
 
worker.tomcat2.type=ajp13
worker.tomcat2.host=localhost
worker.tomcat2.port=12009
worker.tomcat2.lbfactor=200
 
worker.loadbalancer.type=lb
worker.loadbalancer.balanced_workers=tomcat1,tomcat2

worker라는 개념은 톰캣의 프로세스로 보면 된다. 즉 worker를 설정하는 구성 요소는 JK 커넥터를 연결하는 방식(JK는 ajp13을 이용한다), 톰캣이 실행되어 있는 IP 혹은 도메인, ajp13 서비스 포트, 그리고 작업 할당량이다. 여기서 주의 깊게 볼 것이 작업 할당량인데 로드밸런싱 시에 lbfactor라는 작업량의 비율을 보고 라운드 로빈 방식의 서비스를 제공하게 된다. 여기서는 tomcat1과 tomcat2를 1대 2의 비율로 작업량을 할당한 것이다.
그럼 이제 남은 작업은 2개의 톰캣 프로세스를 실행시키는 것이다. 톰캣 프로세스를 여러 개 띄우는 방법은 2가지가 있다.

  • 톰캣을 2개 설치해서 기동시킨다. 이때 포트 충돌을 피하기 위해 서버 포트, AJP13과 HTTP 1.1 커넥터 포트 2개를 충돌되지 않게 재정의 한다.
  • 하나의 톰캣에 2개의 서비스를 정의하고 톰캣을 기동시킨다. 이때 AJP13과 HTTP1.1 커텍터 포트 2개를 충돌되지 않게 재정의 한다.

먼저 2개의 바이너리를 설치했다고 가정하면 각각의 톰캣은 다음과 같은 형태의 server.xml 파일로 적용해 준다.

리스트 3. server.xml

리스트 4. server.xml

리스트 3은 tomcat1의 환경 설정이고 리스트 4는 tomcat2의 환경 설정이다. 두 환경 설정의 차이는 3개의 포트번호와 태그의 jvmRoute 속성이다. 태그의 포트는 톰캣을 종료 시키는 작업을 할 때 사용하는 것이며 태그의 포트들은 아파치를 통하지 않고 직접 톰캣에 접속할 경우와 아파치와 연계하여 JK 커넥터와 연동할 때 사용하는 포트이다. 마지막으로 태그는 JK 커넥 터에서 로드밸런싱을 수행할 때 해당 값을 구분자로 활용하게 되는데 이 값을 반드시 다른 톰캣 프로세스와 다른 이름으로 지정해야 한다. 지금까지의 환경 설정은 하나의 아파치 웹서버와 두 개의 톰캣 간의 연계를 위한 것이며 톰캣은 동일한 하드웨어 장비에 설치되어 있다는 가정하에 적용한 것이다. 만일 각각의 톰캣이 서로 다른 하드웨어에 존재한다면 jvmRoute명만 다르게 하고 포트명은 동일해도 상관이 없다. 하지만 만일 하나의 장비에 4개의 톰캣 프로세스를 실행시키고 로드밸런싱을 하려고 한다면 어떻게 될까? 톰캣을 4번 설치하고 각각의 환경 설정 파일을 수정해 주어야 할까? 만일 필요한 환경 설정 내용이 변경된다면(예를 들어 JNDI Resource 정보) 모두 운영자가 환경 설정 파일을 수정해 주어야 할까? 다행히도 톰캣에서는 하나의 바이너리에 여러 개의 프로세스가 뜨도록 할 수 있다. 톰캣의 server.xml 태그는 다음과 같은 구조를 가지고 있다.

--> --> --> -->

여기서 Server 태그는 유일해야 하며 Server 태그 밑에는 여러 개의 태그가 올 수 있다. 여기서 말하는 태그가 바로 하나의 톰캣 프로세스가 된다. 만일 2개의 태그를 정의했다면 2개의 프로세스가 구동되는 것이다. 리스트 5는 이렇게 구현한 환경 설정 파일이다.

리스트 5. server.xml

리스트 5는 하나의 톰캣 바이너리를 통해 2개의 프로세스를 실행시키는 것이다. 이렇게 하면 환경 설정의 편리성을 가져올 수 있지만 특정 서비스만 실행하거나 종료 시키는 것은 아직 지원되지 않는다. 즉 모든 서비스가 동시에 실행되거나 혹은 동시에 종료되는 것을 의미한다. 이런 점을 잘 판단해서 두 가지 형태의 환경 설정 중 하나를 선택하면 되겠다.
지금까지는 로드밸런싱에 대해 알아보았다. 위의 환경설정을 가지고 테스트를 하다 보면 한가지 문제가 발생한다. 예를 들어 어떤 사용자가 tomcat1을 이용해서 쇼핑몰 서비스를 받고 있다가 tomcat1이 비정상 종료를 하게 되었다. 이때 사용자가 웹 페이지를 요청하게 되면 아파치 웹서버는 tomcat1이 종료된 것을 인지하고 그 이후부터 서비스를 tomcat2로 요청하게 된다. 하지만 tomcat1에 저장되어 있던 쇼핑바구니 정보 즉 세션 정보는 사라진 상태다. 즉, 서비스는 유지되지만 사용자는 다시 이유도 모르게 처음부터 쇼핑 항목들을 등록해야 하는 문제를 가지게 된다. 이제부터는 이런 문제를 해결할 수 있는 톰캣 프로세스 간의 세션 정보 공유에 대해서 알아보겠다.


위로

세션 클러스터링 설정

클러스터링은 톰캣 5.x 버전부터 지원이 되고 있지만 아직은 초기 단계이고 세션 클러스터링만이 제공되고 있는 수준이다. 기능이 많이 부족하긴 하지만 로드밸런싱과 더불어 사용할 경우에는 좀 더 안정적인 서비스를 제공할 수 있다. 작업을 해주어야 할 것은 다음과 같다.

  • server.xml에 태그 정의
  • 웹 어플리케이션의 web.xml에 태그 추가
그럼 server.xml에 설정해 보자. 태그는 태그의 하위에 정의해 주면 된다. 즉 여러 개의 호스트(예를 들어 가상 호스트) 를 설정했다면 각각의 경우에 맞게 설정해 주어야 한다. 여기서는 tomcat1과 tomcat2가 동일한 하드웨어에 별도의 바이너리 형태로 설치되어 있다고 가정하고 진행하겠다.

리스트 6. server.xml

... ...

리스트 6은 tomcat1의 server.xml에 적용한 태그이다. 이 내용은 태그 사이에 위치하게 된다. 태그 사이에는 , , 라는 3개의 태그가 위치하는데 은 멤버 그룹을 정의하는 것으로 해당 값이 동일한 모든 톰캣 프로세스는 클러스터로 묶이게 된다. 는 클러스터 그룹에서 보내오는 메시지와 세션 정보 등을 받아오는 것이며 는 자신의 세션 정보 및 메시지를 전송하는 것이다. 위의 내용을 tomcat2의 server.xml에 Receiver 태그의 tcpListenPort 값을 4002로 변경해서 적용하도록 하자.


위로

웹 어플리케이션 작성을 통한 테스트

먼저 테스트를 위해서 간단한 웹 어플리케이션을 작성하도록 하겠다. 여기서 웹 어플리케이션 이름은 lbtest라고 하겠다.

리스트 7. index.jsp

<%@ page contentType="text/html; charset=euc-kr" %>

세션 JSP 테스트

<% Integer ival = (Integer)session.getAttribute("sessiontest.counter"); if(ival==null) { ival = new Integer(1); } else { ival = new Integer(ival.intValue() + 1); } session.setAttribute("sessiontest.counter", ival); %> 당신은 이곳을 <%= ival %> 번 방문 했습니다.

여기를 클릭하세요. 여기

request 객체와 관련된 세션 데이터
요청된 세션 ID : <%= request.getRequestedSessionId() %>
쿠키로 부터 요청된 세션 ID 인가? : <%= request.isRequestedSessionIdFromCookie() %>
URL로부터 요청된 세션 ID 인가? : <%= request.isRequestedSessionIdFromURL() %>
유효한 세션 ID 인가? : <%= request.isRequestedSessionIdValid() %>

작성된 웹 애플리케이션을 tomcat1과 tomcat2에 배포한다. 이때 가장 중요한 것이 web.xml에 반드시 이라는 항목을 넣어 야 한다. 그럼 이제 테스트를 해보도록 하자. 먼저 아파치 웹서버, tomcat1, tomcat2를 차례로 실행시켜 보자. 그리고 http://ipaddress/lbtest/index.jsp 접속하여 세션 객체를 생성해보자. 결과 화면은 그림 1과 같다. 여기서 요청된 세션ID를 보면 뒤에 어떤 톰캣에 접속한 상태인지를 알 수 있다. 이 화면상에서는 tomcat2에 접속한 세션이다. 그럼 tomcat2를 강제로 종료시켜 보도록 하자. 종료 후 화면에 보이는 “여기”를 계속 눌러 보자. 분명히 tomcat2가 종료되었음에도 불구하고 세션 값이 유지되고 있음을 알 수 있다. 이젠 반대로 tomcat2를 다시 실행시킨 후에 tomcat1을 종료시켜 보도록 하자. 역시 마찬가지로 세션 정보가 유지되는 것을 확인할 수 있을 것 이다.

test 결과화면
그림 1. 테스트 결과 화면

이상으로 톰캣을 이용한 로드밸런싱과 세션 클러스터링에 대해서 알아보았다. 일반적으로 로드밸런싱과 클러스터링은 성능 향상이라는 측면과 안정성 확보에 그 목적을 가지고 있다. 물론 고가의 상용 웹 어플리케이션 서버에 비하면 많이 부족하고 하드웨어를 이용한 로드밸런싱과 클러스터링에 비하면 안정성이 떨어질 수도 있지만 저렴한 비용으로 최대의 안정성과 성능을 얻고자 한다면 한번쯤 시도해 볼만한 좋은 기능이라고 할 수 있다. 아무쪼록 리눅스, 아파치, 톰캣 그리고 오픈소스를 통해 즐거운 웹 어플리케이션 개발 환경을 느껴보기 바란다.


위로

참고 자료
The Apache Tomcat Connector: http://tomcat.apache.org/connectors-doc/
Clustering/Session Replication HOW-TO: http://tomcat.apache.org/tomcat-5.5-doc/cluster-howto.html


출처 : http://tellus.tistory.com/63?srchid=BR1http%3A%2F%2Ftellus.tistory.com%2F63

Posted by 1010
98..Etc/Tomcat2009. 10. 30. 13:15
반응형

Tomcat FAQ

Class Not Found 문제


print-friendly
version
Preface
이 페이지에서는 당신이 Class Not Found 에러나 그와 유사한 에러를 만났을 때에 대해 논하고 있다. 당신이 다음 문서들을 읽어 보기를 강력히 추천한다: NoClassDefFoundError exception을 만났다면, 근원적인 문제는 ClassNotFound Exception과 같은 원인일 것이다.
Questions

Answers
jsp:useBean가 정상적으로 실행되지 않습니까?
다음을 확인해 보세요:
  • 당신의 빈즈는 패키지 선언이 되어 있는 클래스야 합니다.
  • 패키지 구조를 포함한 완전한 클래스 명 (예:com.bar.package.MyClass) 이나
  • JSP페이지 위에 import 를 이용 (예: <%@ pageimport="com.bar.package.MyClass"%>)하여야 합니다.

java.lang.NoClassDefFoundError: javax/servlet/Filter 라는 메시지를 받습니까?
아마도 servlet.jar파일이 있어서는 안될 어떤 곳에 복사되어 있을 수 있습니다. 이런 상황은 클래스 로더의 동작을 방해 합니다. 톰캣의 클래스 로더가 기대했던 대로 동작하지 않기 때문입니다. (위의 메시지 처럼)

NoClassDefFoundError: org/xml/sax/InputSource라는 메시지를 받습니까?
당신의 classpath안에 있는 XML api jar 파일들에 충돌이 생겼습니다. 더 많은 정보는 README나 RELEASE_NOTES를 참고하세요.
Posted by 1010
98..Etc/Tomcat2009. 6. 27. 01:18
반응형

Tomcat 에서 Oracle 연결 기준입니다.

 

첫번째! -------------------------------------------------------------------

ojdbc14.jar (ojdbc14.zip 파일이 아니다!) 를 <CATALINA_HOME>/common/lib 에 복사한다.

 

 


두번째! -------------------------------------------------------------------

server.xml 파일을 수정한다. <GlobalNamingResources></GlobalNamingResources> 사이에 다음의 내용을 추가한다.

 

<Resource name="jdbc/<alias>"
               auth="Container"
               type="javax.sql.DataSource"
               driverClassName="oracle.jdbc.driver.OracleDriver"
               factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory"
              
url="jdbc:oracle:thin:@<server>:<port>:<sid>"
               username="<user>"
              
password="<password>"
               maxActive="20"
               maxIdle="10"
               maxWait="-1" />

 

 

 

세번째! -------------------------------------------------------------------

context.xml 파일을 수정한다. <Context></Context> 사이에 다음의 내용을 추가한다.

 

<ResourceLink global="jdbc/<alias>" name="jdbc/<alias>" type="javax.sql.DataSource"/>

 

 

네번째! -------------------------------------------------------------------

web.xml 파일을 수정한다. <web-app></web-app> 사이에 다음의 내용을 추가한다.

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

 

 

 

사용법! -------------------------------------------------------------------

[JAVA]

Context initContext = new InitialContext();
Context envContext = (Context) initContext.lookup("java:/comp/env");
DataSource ds = (DataSource) envContext.lookup("jdbc/<alias>");

 

[JSP]

<%
    com.microdeveloper.db.jndi.ConnectionPool ocp =

                                  new com.microdeveloper.db.jndi.ConnectionPool();
    ocp.init();
%>

<h2>Results</h2>
Message: <%= ocp.getMessage() %>

 

 

 

Eclipse! -------------------------------------------------------------------

 

사용자 삽입 이미지

 
 
 
1) context.xml
Eclipse 에서 Tomcat 을 연결해서 사용하는 경우 context.xml 파일이 존재하지 않는다.
따라서, 프로젝트의 서버 설정 부분에 context.xml 파일을 복사하면 된다.
 
2) web.xml
Tomcat server 설정부분의 web.xml 파일을 수정하는 것이 아니라 생성한 웹 프로젝트의
WEB-INF 폴더에 있는 web.xml 파일을 수정해야 한다.
 

Posted by 1010
98..Etc/Tomcat2009. 6. 27. 01:17
반응형

Tomcat 에서 Oracle 연결 기준입니다.

 

첫번째! -------------------------------------------------------------------

ojdbc14.jar (ojdbc14.zip 파일이 아니다!) 를 <CATALINA_HOME>/common/lib 에 복사한다.

 

 


두번째! -------------------------------------------------------------------

<ContextName.xml> 파일을 추가한다.

파일 추가 경로 : ${CATALINA_HOME}\conf\Catalina\localhost

ContextRoot 와 같은 이름의 파일을 생성하고 다음의 내용을 추가한다.

 

<Context docBase="<ContextDocBase>"
             path="<ContextPath>"
             reloadable="true"
             debug="5"
             crossContext="true">

 

    

    <Resource name="jdbc/<alias>"
                   auth="Container"
                   type="javax.sql.DataSource"
                   driverClassName="oracle.jdbc.driver.OracleDriver"
                   factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory"
                  
url="jdbc:oracle:thin:@<server>:<port>:<sid>"
                   username="<user>"
                  
password="<password>"
                   maxActive="20"
                   maxIdle="10"
                   maxWait="-1"

                   removeAbandoned="true"
                   removeAbandonedTimeout="60"
                   logAbandoned="true"/>

</Context>

 

 

 

세번째! -------------------------------------------------------------------

web.xml 파일을 수정한다. <web-app></web-app> 사이에 다음의 내용을 추가한다.

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

 

 

                     

JNDI 방법과 다른점은 server.xml 파일에 추가되어야 할 내용을 ${CATALINA_HOME}\conf\Catalina\localhost 에 Context 이름의 XML 파일을 생성하여 넣는다는 것!

Posted by 1010
98..Etc/Tomcat2009. 6. 27. 01:16
반응형

Tomcat 5 JNDI DataSource를 통한 DB 커넥션 풀 사용

 

 

 

이미 눈치 채셨겠지만, 요즘 내가 RDBMS 배우기에 열을 올리고 있다.
지금까지는 JSP/Servlet에서 직접 커넥션을 맺거나, 컨텍스트내에 커넥션 라이브러리를 두고 호출에서 사용했는데, 바꿔야겠다.
JNDI
통한 커넥션 사용은 J2EE 표준이고, 현존하는 거의 모든 컨테이너가 지원한다고 한다.

 

JNDI 서버에 설정하는 방법은 WAS 별로 다르지만, 사용하는 것은 모두 동일하므로 호환성에 문제도 없다.

 

글은 Jakarta DBCP 커넥션 Tomcat JNDI 설정을 통해 데이터베이스 커넥션 풀을 사용하는 방법이다.

 

JNDI 커넥션 풀에 관한 자세한 설명이 JavaServer Pages 3rd ed. 실려있다. 너무 좋다. 읽어보라고 강력하게 권하고 싶다.

 

기본적으로 필요한 라이브러리

  • commons-dbcp.jar
  • commons-collections.jar
  • commons-pool.jar

예제 JDBC 드라이버

  • Oracle 9i classes12.jar

JNDI Naming Resource 설정

1.       라이브러리들을 $CATALINA_HOME/common/lib 복사한다. 이외 디렉토리에 두면 안된다. ZIP 파일은 JAR 확장자를 바꿔야 한다. 톰캣은 JAR파일만 클래스패스에 추가한다.

2.       Connection 풀을 이용할 경우에는 ResultSet Connection 객체를 필히 직접 닫아 줘야만 한다.

3.       $CATALINA_HOME/conf/server.xml 혹은 컨텍스트별 XML 파일의 <Context> 자식 요소로 다음을 추가한다.

4.                <Resource name="jdbc/forumDb" auth="Container" type="javax.sql.DataSource"/>

5.                <!-- Resource name 속성을 이용해서 어플리케이션에서

6.                                javax.sql.DataSource 객체를 얻어가게 된다. -->

7.               

8.               

9.                <!-- 자세한 파라미터 설정은

10.               http://jakarta.apache.org/tomcat/tomcat-5.0-doc/jndi-datasource-examples-howto.html 참조 -->

11.            <ResourceParams name="jdbc/forumDb">

12.              <parameter>

13.                <name>factory</name>

14.                <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>

15.              </parameter>

16.           

17.              <parameter>

18.                <name>maxActive</name>

19.                <value>100</value>

20.              </parameter>

21.           

22.              <parameter>

23.                <name>maxIdle</name>

24.                <value>30</value>

25.              </parameter>

26.           

27.              <parameter>

28.                <name>maxWait</name>

29.                <value>10000</value>

30.              </parameter>

31.           

32.                              <!-- DB 사용자명과 비밀번호 설정 -->

33.              <parameter>

34.               <name>username</name>

35.               <value>dbuser</value>

36.              </parameter>

37.              <parameter>

38.               <name>password</name>

39.               <value>dbpasswd</value>

40.              </parameter>

41.           

42.                              <!-- JDBC 드라이버 클래스 -->

43.              <parameter>

44.                 <name>driverClassName</name>

45.                 <value>oracle.jdbc.driver.OracleDriver</value>

46.              </parameter>

47.             

48.                              <!-- JDBC 접속 URL -->

49.              <parameter>

50.                <name>url</name>

51.                <value>jdbc:oracle:thin:@dbhost:1521:ORA</value>

52.              </parameter>

53.           

54.                  <!-- 커넥션에 문제 없는지 테스트하는 쿼리 -->

55.              <parameter>

56.                <name>validationQuery</name>

57.                <value>select sysdate</value>

58.              </parameter>

59.            </ResourceParams>

 

60.    어플리케이션의 web.xml파일에 다음을 추가하여 JNDI 리소스를 사용할 있도록 한다.

61.                              <resource-ref>

62.                                                   <description>Forum DB Connection</description>

63.                                                   <!-- 다음이 바로 리소스의 이름 -->

64.                                                   <res-ref-name>jdbc/forumDb</res-ref-name>

65.                                                   <res-type>javax.sql.DataSource</res-type>

66.                                                   <res-auth>Container</res-auth>

67.                              </resource-ref>

 

JSP/Servlet 에서 사용하기

이제 다음과 같이 JNDI 이용해 DataSource 객체를 얻고, 객체에서 커넥션을 얻어오면 된다.

 

다음은 서블릿을 작성하고, 서블릿에서 DB커넥션을 얻고, 쿼리를 날린 , 결과를 JSP 파일에 포워딩하여 JSTL 이용해 출력하는 것이다.

 

1.       예제 테이블과 데이터 SQL - 오라클 계정으로 다음과 같은 데이터를 생성했다고 가정하면

2.              create table test (

3.                                  num NUMBER NOT NULL,

4.                                  name VARCHAR2(16) NOT NULL

5.              );

6.               

7.              truncate table test;

8.               

9.              insert into test values(1,'영희');

10.          insert into test values(2, '철수');

11.          insert into test values(3, '미숙');

12.          commit;

 

13.    test.JndiDataSourceTestServlet 소스

14.          package test;

15.           

16.          import java.io.IOException;

17.          import java.sql.Connection;

18.          import java.sql.ResultSet;

19.          import java.sql.SQLException;

20.          import java.sql.Statement;

21.          import java.util.ArrayList;

22.          import java.util.HashMap;

23.          import java.util.List;

24.          import java.util.Map;

25.           

26.          import javax.naming.Context;

27.          import javax.naming.InitialContext;

28.          import javax.naming.NamingException;

29.          import javax.servlet.RequestDispatcher;

30.          import javax.servlet.ServletException;

31.          import javax.servlet.http.HttpServlet;

32.          import javax.servlet.http.HttpServletRequest;

33.          import javax.servlet.http.HttpServletResponse;

34.          import javax.sql.DataSource;

35.           

36.          public class JndiDataSourceTestServlet extends HttpServlet {

37.           

38.              protected void doGet(HttpServletRequest request,

39.                      HttpServletResponse response) throws ServletException, IOException {

40.           

41.                  Connection conn = null;

42.                  ResultSet rs = null;

43.                  Statement stmt = null;

44.           

45.                  try {

46.                      // 커넥션을 얻기 위한 전초작업. 부분을 메소드화 하면 되겠다. ------------

47.                      Context initContext = new InitialContext();

48.                      Context envContext = (Context)initContext.lookup("java:/comp/env");

49.                      DataSource ds = (DataSource)envContext.lookup("jdbc/forumDb");

50.                     

51.                      // 커넥션 얻기

52.                       conn = ds.getConnection();

53.                      //------------------------------------------------------------------

54.                     

55.                      String sql = "SELECT * from test";

56.                      stmt = conn.createStatement();

57.                     

58.                      rs = stmt.executeQuery(sql);

59.                     

60.                      List results = new ArrayList();

61.                     

62.                      while (rs.next()) {

63.                          Map row = new HashMap();

64.                         

65.                          row.put("num", rs.getString("num"));

66.                          row.put("name", rs.getString("name"));

67.                         

68.                          results.add(row);

69.                      }

70.                     

71.                      request.setAttribute("results", results);

72.                     

73.                      RequestDispatcher rd = request.getRequestDispatcher("/dbtest.jsp");

74.                      rd.forward(request, response);

75.                     

76.                  } catch (NamingException e) {

77.                      throw new ServletException("JNDI 부분 오류", e);

78.                  } catch (Exception e) {

79.                      throw new ServletException("뭔가 다른 부분 오류", e);

80.                  } finally {

81.                      // 리소스를 필히 반환할 !

82.                      if (rs != null) { try { rs.close(); } catch (Exception ignored) {} }

83.                      if (stmt != null) { try { stmt.close(); } catch (Exception ignored) {} }

84.                      if (conn != null) { try { conn.close(); } catch (Exception ignored) {} }

85.                  }

86.              }

87.          }

88.    web.xml 서블릿 등록

89.                              <servlet>

90.                                                   <servlet-name>dbtest.svl</servlet-name>

91.                                                   <servlet-class>test.JndiDataSourceTestServlet</servlet-class>

92.                              </servlet>

93.                              <servlet-mapping>

94.                                                   <servlet-name>dbtest.svl</servlet-name>

95.                                                   <url-pattern>/dbtest.svl</url-pattern>

96.                              </servlet-mapping>

97.    /dbtest.jsp 소스

98.          <%@ page contentType="text/html" pageEncoding="EUC-KR" %>

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

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

101.        

102.       <!DOCTYPE HTML PUBLIC "-//w3c//dtd html 4.0 transitional//en">

103.       <html>

104.       <head>

105.       <title>JNDI DataSource Test</title>

106.       </head>

107.                        <body                  bgcolor="#FFFFFF">

108.                           <h2>Results</h2>

109.                          

110.                           <c:forEach var="row" items="${results}">

111.                                                                    NUM : ${row.num}<br />

112.                                                                    Name : ${row.name}<br />

113.                                                                    <hr />

114.                           </c:forEach>

115.       </body>

116.       </html>

 

117.이제 브라우저에서 "/dbtest.svl" 호출해보면 결과를 있다.

 

전역적인 JNDI 리소스 이용

<Resource> <ResourceParams> 요소를 server.xml <GlobalNamingResources> 자식노드로 옮기면 특정 어플리케이션이 아니라, 톰캣에 설치된 전체 어플리케이션에서 사용 있게 된다. 하지만 어플리케이션 "<Context>" 다음과 같은 설정을 해야 한다.

                    <ResourceLink

                                         name="jdbc/forumDb"

                                         global="jdbc/forumDb"

                                         type="javax.sql.DataSource"

                      />

 

아니면 server.xml에서 <Host> 요소의 자식으로 다음을 추가하면 컨텍스트별 설정 필요없이 전체 어플리케이션 컨텍스트에서 GlobalNamingResources 지정된 JNDI 리소스를 사용할 있다.

 

                    <DefaultContext>

                                         <ResourceLink

                                                             name="jdbc/forumDb"

                                                             global="jdbc/forumDb"

                                                             type="javax.sql.DataSource"

                                           />

        </DefaultContext>

 

문제가 생겼어요!

1.       DB 커넥션이 간혹 끊어져요.
Tomcat
작동중인 JVM 가비지 컬렉션을 , 시간이 JNDI Resource 파라미터로 설정한 maxWait보다 길게 경우 DB 커넥션이 끊어질 있다.
CATALINA_OPTS=-verbose:gc
옵션을 주면 $CATALINA_HOME/logs/catalina.out 가비지 컬렉션 상황이 기록된다. 거기에 GC 작업에 걸린 시간도 나오니 그것을 참조로 maxWait 파라미터를 늘려주면 된다. 보통 10~15초로 주면 된다.
GC
시간은 거의 99% 이상 1 이내에 끝나야 하나보다..

2.       무작위로 커넥션이 close 되요.
그건.. Connection 객체를 이상 close 했기 때문이다.
DB Connection Pool
close() 호출할 정말로 닫는 것이 아니라, 단지 재사용할 있다고 표시만 뿐이다.
커넥션을 사용하다가 close()하면 다른 쓰레드이서 커넥션을 있는데, 이걸 현재 쓰레드에서 계속 잡고 있다가 다시 close() 해버리면, 다른 쓰레드에서 사용중에 close()됐다고 나와 버리게 되는 거다.

3.                  conn.close();

4.                  conn = null;

위와 같이 커넥션을 close() 뒤에 바로 null 설정하여 절대로 다시 사용할 없게 만들면 이런 실수는 생기지 않을 것이다.

Tomcat 5.5 예제

        <Resource name="jdbc/myDbResource" auth="Container" type="javax.sql.DataSource"

               maxActive="10" maxIdle="5" maxWait="10000"

               username="ao" password="ao"

               driverClassName="com.mysql.jdbc.Driver"

               url="jdbc:mysql://localhost:3306/myWebApp"

 

               removeAbandoned="true"

               removeAbandonedTimeout="60"

               logAbandoned="true"

               validationQuery="select 1"

               testOnBorrow="true"

               testWhileIdle="true"

               timeBetweenEvictionRunsMillis="10000"

               minEvictableIdleTimeMillis="60000"

       />

 

저기서 removeAbandoned 리소스 반환에 실패한 (혹은 안한) 커넥션을 자동으로 닫아주는 것이다.

 

validationQuery 커넥션이 살아 있는지 테스트하는 코드이다.

 

MySQL, Connector/J Tomcat 5 예제

http://dev.mysql.com/doc/connector/j/en/cj-tomcat-config.html 나온 내용임.

<Context ....>

 

  ...

 

  <Resource name="jdbc/MySQLDB"

               auth="Container"

               type="javax.sql.DataSource"/>

 

  <!-- The name you used above, must match _exactly_ here!

 

       The connection pool will be bound into JNDI with the name

       "java:/comp/env/jdbc/MySQLDB"

  -->

 

  <ResourceParams name="jdbc/MySQLDB">

    <parameter>

      <name>factory</name>

      <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>

    </parameter>

 

    <!-- Don't set this any higher than max_connections on your

         MySQL server, usually this should be a 10 or a few 10's

         of connections, not hundreds or thousands -->

 

    <parameter>

      <name>maxActive</name>

      <value>10</value>

    </parameter>

 

        <!-- You don't want to many idle connections hanging around

         if you can avoid it, onl    y enough to soak up a spike in

         the load -->

 

    <parameter>

      <name>maxIdle</name>

      <value>5</value>

    </parameter>

 

    <!-- Don't use autoReconnect=true, it's going away eventually

         and it's a crutch for older connection pools that couldn't

         test connections. You need to decide if your application is

         supposed to deal with SQLExceptions (hint, it should), and

         how much of a performance penalty you're willing to pay

         to ensure 'freshness' of the connection -->

 

    <parameter>

      <name>validationQuery</name>

      <value>SELECT 1</value>

    </parameter>

 

   <!-- The most conservative approach is to test connections

        before they're given to your application. For most applications

        this is okay, the query used above is very small and takes

        no real server resources to process, other than the time used

        to traverse the network.

 

        If you have a high-load application you'll need to rely on

        something else. -->

 

    <parameter>

      <name>testOnBorrow</name>

      <value>true</value>

    </parameter>

 

   <!-- Otherwise, or in addition to testOnBorrow, you can test

        while connections are sitting idle -->

 

    <parameter>

      <name>testWhileIdle</name>

      <value>true</value>

    </parameter>

 

    <!-- You have to set this value, otherwise even though

         you've asked connections to be tested while idle,

         the idle evicter thread will never run -->

 

    <parameter>

      <name>timeBetweenEvictionRunsMillis</name>

      <value>10000</value>

    </parameter>

 

    <!-- Don't allow connections to hang out idle too long,

         never longer than what wait_timeout is set to on the

         server...A few minutes or even fraction of a minute

         is sometimes okay here, it depends on your application

         and how much spikey load it will see -->

 

    <parameter>

      <name>minEvictableIdleTimeMillis</name>

      <value>60000</value>

    </parameter>

 

    <!-- Username and password used when connecting to MySQL -->

 

    <parameter>

     <name>username</name>

     <value>someuser</value>

    </parameter>

 

    <parameter>

     <name>password</name>

     <value>somepass</value>

    </parameter>

 

    <!-- Class name for the Connector/J driver -->

 

    <parameter>

       <name>driverClassName</name>

       <value>com.mysql.jdbc.Driver</value>

    </parameter>

 

    <!-- The JDBC connection url for connecting to MySQL, notice

         that if you want to pass any other MySQL-specific parameters

         you should pass them here in the URL, setting them using the

         parameter tags above will have no effect, you will also

         need to use & to separate parameter values as the

         ampersand is a reserved character in XML -->

 

    <parameter>

      <name>url</name>

      <value>jdbc:mysql://localhost:3306/test</value>

    </parameter>

 

  </ResourceParams>

</Context>

 

Oracle 만을 위한 JNDI 설정

원문 : http://www.microdeveloper.com/html/JNDI_Orcl_Tomcat1p.html

 

1) Modify the server.xml file
In<CATALINA_HOME>/conf/server.xml between <GlobalNamingResources> and </GlobalNamingResources> add the following

   <Resource name="jdbc/<alias>"

   auth="Cont   ainer"

   type="oracle.jdbc.pool.OracleDataSource"

   driverClassName="oracle.jdbc.driver.OracleDriver"

   factory="oracle.jdbc.pool.OracleDataSourceFactory"

   url="jdbc:oracle:thin:@<host>:<port>:<sid>"

   [user=<user>]

   [password=<password>]

   maxActive="20"

   maxIdle="10"

   maxWait="-1" />

   

 

Example

<!-- Global JNDI resources -->

 <GlobalNamingResources>

 

 <!-- Test entry for demonstration purposes -->

 <Environment name="simpl   eVal   ue" type="java.lang.Integer" value="30"/>

 

 <!-- Editable user database that can also be used by

   UserDatabaseRealm to authenticate users -->

 <Resource name="UserDatabase" auth="Container"

   type="org.apache.catalina.UserDatabase"

   description="User database that can be updated and saved"

   factory="org.apache.catalina.users.MemoryUserDatabaseFactory"

   pathname="conf/tomcat-users.xml" />

    <!-- Every connection to 'db1' uses the same user -->

 <Resource name="jdbc/db1"

   auth="Container"

   type="oracle.jdbc.pool.OracleDataSource"

   driverClassName="oracle.jdbc.driver.OracleDriver"

   factory="oracle.jdbc.pool.OracleDataSourceFactory"

   url="jdbc:oracle:thin:@oracle.microdeveloper.com:1521:db1"

   user="scott"

   password="tiger"

   maxActive="20"

   maxIdle="10"

   maxWait="-1" />

    <!-- Every connection to 'db2' must provide a username and password -->  <Resource name="jdbc/db2"

   auth="Container"

   type="oracle.jdbc.pool.OracleDataSource"

   driverClassName="oracle.jdbc.driver.OracleDriver"

   factory="oracle.jdbc.pool.OracleDataSourceFactory"

   url="jdbc:oracle:thin:@oracle.microdeveloper.com:1521:db2"

   maxActive="20"

   maxIdle="10"

   maxWait="-1" />

</GlobalNamingResources>

 

2) Modify the context.xml file
In <CATALINA_HOME>/conf/context.xml between <Context> and </Context> add the following for each entry in the JNDI resource list:

<ResourceLink global="jdbc/<alias>" name="jdbc/<alias>" type="oracle.jdbc.pool.OracleDataSource"/>

 

Example

<!-- The contents of this file will be loaded for each web application -->

 <Context>

 

 <!-- Default set of monitored resources -->

 <WatchedResource>WEB-INF/web.xml</WatchedResource>

 <WatchedResource>META-INF/context.xml</WatchedResource>

    <!-- Uncomment this to disable session persistence across Tomcat restarts -->

 <!--

 <Manager pathname="" />

   -->

 <ResourceLink global="jdbc/db1" name="jdbc/db1" type="oracle.jdbc.pool.OracleDataSource"/>

 <ResourceLink global="jdbc/db2" name="jdbc/db2" type="oracle.jdbc.pool.OracleDataSource"/>

 </Context>

 

3) Modify the context's web.xml file (5.0.x step only - not necessary for 5.5.x)
In the <CONTEXT>/WEB-INF/web.xml between <web-app> and </web-app> add the following:

<resource-ref>

   <description><Your Description></description>

   <res-ref-name>jdbc/<alias></res-ref-name>

   <res-type>oracle.jdbc.pool.OracleDataSource</res-type>

   <res-auth>Container</res-auth>

</resource-ref>

 

Example

 

<resource-ref>

   <description>Oracle Development Datasource</description>

   <res-ref-name>jdbc/db1</res-ref-name>

   <res-type>oracle.jdbc.pool.OracleDataSource</res-type>

   <res-auth>Container</res-auth>

</resource-ref>

 

<resource-ref>

   <description>Oracle Development Datasource</description>

   <res-ref-name>jdbc/db2</res-ref-name>

   <res-type>oracle.jdbc.pool.OracleDataSource</res-type>

   <res-auth>Container</res-auth>

</resource-ref>

 

 

4) Restart Tomcat

 

Posted by 1010
98..Etc/Tomcat2009. 6. 27. 01:15
반응형

Apache 2 + Tomcat 5.x mod_jk 1.2 연동시 한글 문제


Apache 2 + Tomcat 5.x mod_jk 1.2 연동시 GET 방식으로 넘어온 파라미터의 한글이 몽땅 깨져버리는 문제가 발생합니다.

이 문제의 해결 책은

<Connector port="8009"
enableLookups="false" redirectPort="8443" debug="0"
protocol="AJP/1.3" URIEncoding="euc-kr"/>

server.xml의 jk 커넥터 부분에도 URIEncoding을 추가해주는 것입니다. 

Posted by 1010
98..Etc/Tomcat2009. 6. 27. 01:14
반응형

1. $TOMCAT_HOME/conf/server.xml(Tomcat4) or

    $TOMCAT_HOME/conf/Catalina/host/context.xml(Tomcat5)


   <Resource name="jdbc/obcon" auth="Container" type="javax.sql.DataSource"/>
   <ResourceParams name="jdbc/obcon">
        <parameter>
            <name>username</name>
            <value>club</value>
        </parameter>
        <parameter>
            <name>password</name>
            <value>obcl</value>
        </parameter>
        <parameter>
            <name>driverClassName</name>
            <value>oracle.jdbc.driver.OracleDriver</value>
        </parameter>
        <parameter>
            <name>url</name>
            <value>jdbc:oracle:thin:@172.16.1.17:1526:ORA8</value>
        </parameter>
        <parameter>
            <name>removeAbandoned</name>
            <value>true</value>
        </parameter>
        <parameter>
            <name>removeAbandonedTimeout</name>
            <value>60</value>
        </parameter>
        <parameter>
            <name>logAbandoned</name>
            <value>true</value>
        </parameter>
        <parameter>
            <name>maxActive</name>

            <value>20</value>
        </parameter>
        <parameter>
            <name>maxIdle</name>
            <value>10</value>
        </parameter>
        <parameter>
            <name>minIdle</name>
            <value>5</value>
         </parameter>
        <parameter>
            <name>maxWait</name>
            <value>10000</value>
        </parameter>
    </ResourceParams>


2. $WEB_ROOT/WEB-INF/web.xml


    <resource-ref>
        <res-ref-name>jdbc/obcon</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
    </resource-ref>


** jdbc jar 파일이 $TOMCAT_HOME/common/lib 에 위치할 것.

Posted by 1010
98..Etc/Tomcat2009. 6. 27. 01:06
반응형

DBCP의 POOL 상태를 모니터링 하는 페이지

톰캣에 default 로 설치된 dbcp 라이브러리를 이용하면 org.apache.tomcat.dbcp.dbcp.*

이고 일반적인 dbcp를 다운받아 사용할경우 org.apache.commons.dbcp.* 로 import 하도록 한다.


<%@ page language="java" contentType="text/html; charset=EUC-KR" %>
<%@ page import="
    javax.naming.*,
    javax.sql.*,
    org.apache.tomcat.dbcp.dbcp.*"
%>
<%
 Context initContext = new InitialContext();
 Context envContext  = (Context)initContext.lookup("java:/comp/env");
 DataSource ds   = (DataSource)envContext.lookup("jdbc/mydb");
 
 BasicDataSource bds = (BasicDataSource)ds;
 String dbname  = "caelum";
 
 try {
   int bdsNumActive  = bds.getNumActive();
   int bdsMaxActive  = bds.getMaxActive();
   int bdsNumIdle   = bds.getNumIdle();
   long bdsMaxWait  = bds.getMaxWait();
   
   String fontcolor  = "";
   
   if (bdsNumActive <= 400) {
    fontcolor = "<font color='green'>";
   } else if (bdsNumActive > 400 && bdsNumActive <= 500) {
    fontcolor = "<font color='orange'>";
   } else {
    fontcolor = "<font color='red'>";
   }
%>
   <table cellpadding='3' cellspacing='0' border='1'>
    <tr>
     <td colspan='4' align='center'><b><%=dbname%></b> DataSource</td>
    </tr>
    <tr>
     <td height='24' align='center' alt='connections that are processing'># Active Connections</td>
     <td height='24' align='center' alt='total size of pool'>Maximum Active Connections</td>
     <td height='24' align='center' alt='connections that are idle in the pool'># of Idle Connections</td>
     <td height='24' align='center'>Maxium Wait period before timeout</td>
    </tr>
    <tr>
     <td align='right'><%=fontcolor%><%=bdsNumActive%></font></td>
     <td align='right'><%=bdsMaxActive%></td>
     <td align='right'><%=bdsNumIdle%></td>
     <td align='right'><%=bdsMaxWait%></td>
    </tr>
   </table>
<%
 } catch(Exception e) {
  out.println(e.toString());
 }
%>

Posted by 1010
98..Etc/Tomcat2009. 6. 27. 01:05
반응형

Tomcat 5.5에서는 기존에 사용하던 ResourceParams 태그를 지원하지 않습니다.

대신 다음과 같이 설정합니다.


- server.xml

 <Resource name="jdbc/mydb" auth="Container" type="javax.sql.DataSource"
   maxActive="100"
   maxIdle="30"
   maxWait="10000"
   username="test"
   password="1234"
   driverClassName="com.mysql.jdbc.Driver"
   url="jdbc:mysql://localhost:3306/test?autoReconnect=true"
   removeAbandoned="true"
   removeAbandonedTimeout="60"
   logAbandoned="true"
 />

<Context ~>

<ResourceLink name="jdbc/mydb" global="jdbc/mydb" type="javax.sql.DataSource"/>

</Context>


-web.xml

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

Posted by 1010
98..Etc/Tomcat2009. 6. 21. 04:52
반응형




JSP를 처음 접하고 Connection Pool 부분에서 막히더군요. 거의 이틀 동안 삽질한듯 싶네요 ㅠ.ㅜ.

이러한 일이 다시 일어나지 않기를 기원하며 이렇게 글을 올립니다.

다른 강좌들 보단 최대한 자세히 쓰려고 노력했으니 분명히 도움이 되시리라 생각됩니다.

 

그리고 이 문제로 몇 일동안 힘들어했던 저에게 정말 많은 도움을 주셨던 기로로님에게 감사의 말씀을 드립니다.

 

 

 

 

 

 

 

 

본 강좌는 Eclipse J2EE, Tomcat 6.0 과 My-SQL 기준으로 작성된 것임을 미리 알려드립니다.

그리고 Tomcat의 버전이 맞지 않으면 설정 환경이 조금씩 다를 수 있다는 것 또한 알려드립니다.




1. 첨부된 파일들을 다운 받는다.

   



2. 다음 순서대로 받은 파일들을 해당 폴더에 넣는다.

 


commons-collections-3.1.jar

commons-dbcp-1.2.1.jar

commons-pool-1.2.jar

 

이 파일들을 자신이 이클립스에서 만들어둔 프로젝트/WebContent/WEB-INF/lib 폴더에 복사한다..


mysql-connector-java-3.0.14-production-bin.jar

 

그리고 위의 JDBC 라이브러리는 설치된 톰캣의 lib 폴더 안에 복사한다.

 



3. 프로젝트/WebContent/META-INF 폴더에 context.xml 파일을 생성한다.

 

<?xml version="1.0" encoding="UTF-8"?>

<Context path="/프로젝트" docBase="프로젝트" reloadable="true">
   
    <WatchedResource>WEB-INF/web.xml</WatchedResource>

   

    <Resource name="jdbc/임의의 DBCP명"
               auth="Container"
               type="javax.sql.DataSource"
               driverClassName="드라이브명"
               url="DB URL"

               username="DB 아이디"
               password="DB 비밀번호"

               <!-- 사용 하고 있는 커넥션의 최대수 -->
               maxActive="20"
               <!-- 사용 안하고 있는 커넥션의 최대수 -->

               maxIdle="10"

               <!-- 커넥션을 열기위해 최대 기다리는 시간 "-1" 이라면 무기한 기다림 -->
               maxWait="-1"
    />
   
</Context>



4. 프로젝트/WebContent/WEB-INF 폴더에 web.xml 파일의 web-app 태그 안에 코드를 추가한다.


<web-app .... 이하 중략...>

<resource-ref>        
    <description>MySQL DB Connection</description>        
    <res-ref-name>jdbc/임의의 DBCP명</res-ref-name>        
    <res-type>javax.sql.DataSource</res-type>        
    <res-auth>Container</res-auth>   
</resource-ref>


</web-app>



 

5. DBCPTest.jsp 실행하기.


<%@ page contentType="text/html; charset=euc-kr" %>
<%@ page import="java.sql.*, javax.naming.*, javax.naming.Context, javax.naming.InitialContext, javax.sql.DataSource" %>
<html>
<head>
    <title>DBCP Test</title>
</head>
<body>
<%
    Statement stmt = null;
    ResultSet rs = null;
    Connection conn = null;
   
    try {
        Context initCtx = new InitialContext();
        Context envCtx = (Context)initCtx.lookup("java:/comp/env");
        DataSource ds = (DataSource)envCtx.lookup("jdbc/임의의 DBCP명");       
        conn = ds.getConnection();
       
        out.write("DBCP Connection..<br><br>");
       
        String sQuery = "select 1 + 1";
        stmt = conn.createStatement();
        rs = stmt.executeQuery(sQuery);
       
        while (rs.next())
        {
            out.write("1 + 1 = " + rs.getString(1) + "<br>");
        }
    } catch(Exception ex) {
        ex.printStackTrace();
    } finally {
        if (rs != null) try {rs.close(); } catch (Exception ex2) {}
        if (stmt != null) try {stmt.close(); } catch (Exception ex3) {}
        if (conn != null) try {conn.close(); } catch (Exception ex4) {}
    }

%>
</body>
</html>

 


[ 결과 화면 ]

 




Posted by 1010
98..Etc/Tomcat2009. 6. 19. 15:44
반응형
  1. tomcat5.0 에서 datasource 설정하기

강좌보기

Posted by 1010
98..Etc/Tomcat2009. 6. 13. 16:11
반응형
Apress Pro Apache Tomcat 6


Posted by 1010
98..Etc/Tomcat2009. 6. 13. 16:09
반응형
Posted by 1010
98..Etc/Tomcat2009. 4. 28. 13:24
반응형

목차

1 Apache/Tomcat 연동시 jsp/servlet 은 Tomcat으로, 나머지는 Apache가 처리하게 설정하기
2 TOMCAT5에서 한글넘겨받을때
3 TOMCAT5 에서 Altibase DB Pool 설정
4 Tomcat5 Only 일때 디렉토리 내 심볼릭 링크가 안먹힐 때
5 Apache Tomcat Native library not found on the java.library.path
6 80 포트로 띄우고 싶을때
6.1 ipchains/iptables 이용하기
6.2 JSVC 를 이용하기
6.3 CoyoteConnector
7 @include 로 포함한 페이지의 한글이 깨질 때
8 common-fileupload 사용시 넘겨받은 한글 파라메터가 깨질 때
9 Tomcat 5.x 에서 jsp 내의 스크립틀릿 사용금지하기
10 Tomcat 5.0 -> Tomcat 5.5 이후 forward 된 jsp 에서 request.getRequestURI() 의 값이 이상해진 경우


1 Apache/Tomcat 연동시 jsp/servlet 은 Tomcat으로, 나머지는 Apache가 처리하게 설정하기 #


mod_jk로 연동하는 경우 아파치의 httpd.conf 에

JkMount /* worker1

와 같은 식으로 처리해 버리는 경우가 많은데, 이렇게 하면 jsp/servlet 같은것들 뿐만 아니라 이미지/css/js 같은 static resource 들도 죄다 tomcat 이 처리하게 된다.
기본적으로 static resource 들은 apache 가 처리하도록 하고 jsp/servlet 등의 처리만 Tomcat 이 맡아 처리하는 것이 좋다.
만약 jsp 파일 또는 Struts1/Struts2 만 사용한다면(그리고 확장자를 .do 와 .action 으로 쓴다면) 이런 경우 설정을

JkMount /*.do worker1
JkMount /*.action worker1
JkMount /*.jsp worker1

와 같은 식으로 하면 된다.

물론 worker1 은 jk.properties 에서 worker.list 에 지정한 그 이름으로 맞추어야 한다.


2 TOMCAT5에서 한글넘겨받을때 #


요즘은 웹사이트를 만들때 UTF-8로 인코딩을 하는 경우가 많은데, UTF-8 페이지에서 게시물을 한글로 입력한 다음 jsp 또는 servlet 에서 넘겨받아서 DB 에 저장하거나 할때 한글이 깨지는 경우가 있다. (당근 POST 로 넘기겠지...)

그럴때는 jsp 또는 serlvet 상단에

request.setCharacterEncoding("utf-8");

라고 해주면 깔끔하게 해결된다. (request 가 내장객체로 있으니 뭐.. Servlet 이라면 함수파라메터명에 맞춰서 적어주면 되겠다)
물론 Tomcat4 도 마찬가지.
당연한 이야기지만 setCharacterEncoding 은 request.getParameter 등의 함수를 호출하기 전에 사용되어야 한다.

3 TOMCAT5 에서 Altibase DB Pool 설정 #


며칠동안 삽퍼면서 이것저것 바꿔봤다.

<Resource name="jdbc/mmsgw" auth="Container" type="javax.sql.DataSource"
        driverClassName="Altibase.jdbc.driver.AltibaseDriver"
        url="jdbc:Altibase://xxx.xx.xxx.xxx/mydb"
        initialSize="20"
        maxActive="50"
        maxIdle="20"
        maxWait="5000"
        removeAbandoned="true"
        removeAbandonedTimeout="60"
        logAbandoned="true"
        username="user"
        password="passwd"/>

파라메터 뜻은 대충

  • initialSize : 초기 DB Pool 생성시 connection 갯수
  • maxActive : connection 최고 증가 갯수
  • maxIdle : 노는 애들을 제거하지 않고 몇개나 놔둘것인가
  • maxWait : DB Pool 에서 Connection 을 가져올때 얼마나 기다릴 것인가 ( 밀리초 단위 )
  • removeAbandoned : 커넥션 끊어진거 제거해버리고 새로 넣고 어쩌구등등으로 할것인지 말것인지
  • removeAbandonedTimeout : 얼마나 자주 removeAbandoned 를 실행시킬것인지 (초단위)
  • logAbandoned : 처리상황 로깅

이정도?


4 Tomcat5 Only 일때 디렉토리 내 심볼릭 링크가 안먹힐 때 #


apache 등의 웹서버와의 연동 없이 tomcat만으로 웹서버까지 함께 쓸때 symbolic link 를 걸면 정상적으로 URL이 걸리지 않는다.
(404 not found 에러남)

이럴때는 Context 설정할에

allowLinking = "true"

로 설정해주면 된다.

예)
<Context 
path=""
docBase="httpd/html"
reloadable="true"
allowLinking="true"
debug="0">
</Context>

5 Apache Tomcat Native library not found on the java.library.path #


tomcat 을 실행시킬때 저런 에러가 계속 뜨는게 싫고 해결하고 싶다면

APR(Apache Protable Runtime) 을 우선 설치한 다음 설치되어 있는 톰캣 디렉토리의 bin 에 있는

tomcat-native.tar.gz

의 압축을 풀고, 그 아래에서

configure
make
make install

을 차례대로 해주면 된다.

만약 configure 시에 apr 못찾겠다는 오류가 나오면

./configure --with-apr=/usr/local/apr ( 아마 apr을 그냥 설치했으면 저 경로에 설치되었을 것이다 )

로 해주면 넘어간다.

그리고 LD_LIBRARY_PATH 를 apr 설치경로의 lib 로 잡아주면 된다. ( /usr/local/apr/lib 쯤 될것임 )

6 80 포트로 띄우고 싶을때 #


apache 와 같은 웹서버에서는 실행은 root로 하더라도 내부 설정에 User 또는 Group 을 지정할 수가 있는데 반해 tomcat 을 80포트로 띄우기 위해서는 root 로만 가능하다.
80포트를 쓰면서 root가 아닌 계정으로 톰캣을 띄우기 위한 몇가지 방법을 찾아서 정리해본다.
뭐 소스코드를 바꾸느니 어쩌니 하는 말들이 있는데 아무래도 그건 방법이 아니라고 생각한다.

6.1 ipchains/iptables 이용하기 #


ipchains 가 설치되어 있다면 다음과 같이 수정하면 된다.

ipchains -A input -d xx.xx.xxx.xx 80 -p tcp -j REDIRECT 톰캣리스닝포트

iptables 라면

iptables -t nat -A OUTPUT -d localhost -p tcp --dport 80 -j REDIRECT --to-ports 8080
iptables -t nat -A OUTPUT -d your hostname -p tcp --dport 80 -j REDIRECT --to-ports 8080
iptables -t nat -A PREROUTING -d your hostname -p tcp --dport 80 -j REDIRECT --to-ports 8080

이런식으로 하면 된다.


6.2 JSVC 를 이용하기 #


쓰고 있는 톰캣이 버전 5.0 이라면 저런거 안하더라도 jsvc 라는 걸로 특정 유저의 권한으로 tomcat 이 동작하도록 할 수 있다.
(jsvc : http://tomcat.apache.org/tomcat-5.5-doc/setup.html )

tomcat5 의 bin 에 보면

jsvc.tar.gz 라는게 있는데 다음 순서로 실행하면 된다.

    cd $CATALINA_HOME/bin
    tar xvfz jsvc.tar.gz
    cd jsvc-src
    autoconf
    ./configure
    make
    cp jsvc ..
    cd ..

실행은

   cd $CATALINA_HOME
    ./bin/jsvc -Djava.endorsed.dirs=./common/endorsed -cp ./bin/bootstrap.jar \
        -outfile ./logs/catalina.out -errfile ./logs/catalina.err \
        org.apache.catalina.startup.Bootstrap

이런식으로 하면 된다.
압축을 푼 디렉토리의 native/ 아래에 보면

Tomcat5.sh

라는 쉘스크립트가 있는데 나중에 /etc/init.d 같은데 넣어서 쓸 수 있도록 만들어준 스크립트다.
이걸 $CATALINA_HOME/bin/ 에다가 복사해 넣고 다음과 같이 살짝 바꿔서 쓰면 편리하다.

JAVA_HOME=/usr/java/jdk1.5.0_12
CATALINA_HOME=/usr/local/tomcat/5.5.23
DAEMON_HOME=/usr/local/tomcat/5.5.23/bin
TOMCAT_USER=사용자ID

# for multi instances adapt those lines.
TMP_DIR=/var/tmp
PID_FILE=/var/tmp/jsvc.pid
CATALINA_BASE=$CATALINA_HOME

CATALINA_OPTS=""
CLASSPATH=\
$JAVA_HOME/lib/tools.jar:\
$CATALINA_HOME/bin/commons-daemon.jar:\
$CATALINA_HOME/bin/bootstrap.jar

case "$1" in
  start)
    #
    # Start Tomcat
    #
    $DAEMON_HOME/jsvc \
    -user $TOMCAT_USER \
    -home $JAVA_HOME \
    -Dcatalina.home=$CATALINA_HOME \
    -Dcatalina.base=$CATALINA_BASE \
    -Djava.io.tmpdir=$TMP_DIR \
    -wait 10 \
    -pidfile $PID_FILE \
    -outfile $CATALINA_HOME/logs/catalina.out \
    -errfile '&1' \
    $CATALINA_OPTS \
    -cp $CLASSPATH \
    org.apache.catalina.startup.Bootstrap
    #
    # To get a verbose JVM
    #-verbose \
    # To get a debug of jsvc.
    #-debug \
    exit $?
    ;;

  stop)
    #
    # Stop Tomcat
    #
    $DAEMON_HOME/jsvc \
    -stop \
    -pidfile $PID_FILE \
    org.apache.catalina.startup.Bootstrap
    exit $?
    ;;

  *)
    echo "Usage tomcat.sh start/stop"
    exit 1;;
esac

6.3 CoyoteConnector #


CoyoteConnector 같은걸 쓴다면 HttpConnector 설정을 다음과 같이 바꿔서 해결할 수도 있다고 한다.(확인해보지 못했음)

<Connector
  className="org.apache.catalina.connector.http.HttpConnector"
  port="8080"
  proxyPort="80"
>


7 @include 로 포함한 페이지의 한글이 깨질 때 #


웹에 뒤져보니까 encoding filter 를 추가하는 방법부터 별별 쑈를 다해놨더라.
기본적으로 A.jsp 에서 B.jsp 를 인클루드하는 경우
파일 둘 다 UTF-8로 작성되어 있다면

A.jsp 에서
<%@page contentType="text/html;charset=utf-8"%>
<%@page pageEncoding="utf-8" %>

로 되어 있고
<%
    response.setContentType("text/html;charset=utf-8");
%>

로 되어 있다면

B.jsp 의 최상단에

<%@page pageEncoding="utf-8"%>

한줄만 추가해주면 끝난다.


아.. 물론 매 페이지마다 저런 짓 하기 싫으면 인코딩 세팅하는 필터 하나 구현해서 등록해서 써도 된다.


8 common-fileupload 사용시 넘겨받은 한글 파라메터가 깨질 때 #


resin 이나 다른곳에서도 그런지는 모르겠지만, 아무튼 tomcat5에서 common-fileupload 를 이용해서 넘겨받은 파라메터 중 한글이 깨지는 경우

item.getString();

대신

item.getString(인코딩타입);

을 적어주면 된다.

setCharacterEncoding
pageEncodping
setContentType

을 죄다 UTF-8로 해줘도, multipart/form-data 로 넘어오는 데이터를 실제로 처리하는 common-fileupload 에서는 인코딩이 별도로 먹히는 것 같다.
그럴때는 슬그머니

item.getString("utf-8");

로 적어주면 문제해결됨.

9 Tomcat 5.x 에서 jsp 내의 스크립틀릿 사용금지하기 #

<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<scripting-invalid>true</scripting-invalid>
</jsp-property-group>
</jsp-config>

10 Tomcat 5.0 -> Tomcat 5.5 이후 forward 된 jsp 에서 request.getRequestURI() 의 값이 이상해진 경우 #


해결책부터 적는다면 5.5에서는 getRequestURI() 대신에

request.getAttribute("javax.servlet.forward.request_uri");

를 사용하면 된다.

좀 더 자세하게 언급하자면 톰캣 5.5.7 이전의 구현이 잘못된 것이었고 SRV 8.4 에 따라 수정되었다.


이유가 궁금하신 분들은 아래쪽을 참고하시길.

Tomcat 은 버전별로 구현된 servlet 및 jsp 의 spec 버전이 다른데, Tomcat 5.x 류는 Servlet 2.4와 JSP 2.0 의 규격을 따른다.
Tomcat 6은 각각 2.5/2.1, Tomcat 4 는 2.3/1.2의 규격을 다른다.

Tomcat 5.x 가 따르는 Servlet 2.4 규격의 2.3. ReuqestDispatcher Forward Attribute 를 살펴보면

SRV.8.4 “The path elements of the request object exposed to the target servlet must reflect the path 
used to obtain the RequestDispatcher.”

와 같은 설명이 되어 있는데, getRequestURI 가 path method 인지의 여부가 불분명했기 때문에 getRequestURI() 에 대한 구현이 여러가지로 만들어졌다.

하지만 SRV.4.4 의

SRV.4.4 “It is important to note that, except for URL encoding differences between the request URI and the 
path parts, the following equation is always true: requestURI = contextPath + servletPath + pathInfo”

로 인해서 이 부분은 해결이 되었다.
requestURI 가 저렇게 구성이 되기 때문에 RequestDispatcher 를 통해 forward 된 다음에는 HttpServletRequest.getRequestURI() 의 값이 바뀌어야만 했고, 이로 인해서 client 로부터 들어왔던 원래의 request uri 를 알수가 없게 되었다.

바로 이 부분에서 기존의 Tomcat 5.0 은 이 부분의 구현을 규격대로 하지 않았던 것 같고, Tomcat 5.5 로 넘어오면서 규격대로 제대로 구현이 되며서 문제가 발생한다. ( 프로그래머의 입장에서는 잘 되던 코드가 동작하지 않게 된 것이겠지만... )


이 문제를 해결하기 위해서 규격 2.4에서는 다음의 forward 속성들을 추가했다.

javax.servlet.forward.request_uri
javax.servlet.forward.context_path 
javax.servlet.forward.servlet_path 
javax.servlet.forward.path_info
javax.servlet.forward.query_string

이 값들은 request.getAttribute(); 를 이용해서 가져올 수가 있다.
만약 해당 서블릿이 다른 곳에서도 재사용되는 것이라면 client 에서 요청한 uri 와 실제의 서비스된 uri (포워딩된 uri) 를 알기 이해서 아래와 같이 더블 체크해야 한다.

public void doGet(HttpServletRequest request, HttpServletResponse response)
{
  String uriUsedByClient=(String)
    request.getAttribute("javax.servlet.forward.request_uri");
  if (uriUsedByClient==null)
    uriUsedByClient=request.getRequestURI();
  String uriToServe=(String)
    request.getAttribute("javax.servlet.include.request_uri");
  if (uriToServe==null)
    uroToServer=request.getRequestURI();
  // ...
}

아래의 톰캣 5.5 chage log 를 살펴보면 5.5.7 버전의 Catalina 쪽 수정사항에 해당 부분의 버그가 수정되었다고 기록되어 있습니다.
http://tomcat.apache.org/tomcat-5.5-doc/changelog.html

28222: request.getRequestURL() in forwarded jsp/servlet returns original url rather than new url as per SRV8.4 (markt)


getRequestURL() 과 getRequestURI() 두개 모두 실제tomcat 5.5.7 이후부터는 forward 된 jsp 의 값이 출력되며 request.getAttribute("javax.servlet.forward.request_uri"); 를 써야 한다.
javax.servlet.forward.request_url 같은 속성값은 없다.
Posted by 1010
98..Etc/Tomcat2009. 4. 22. 14:03
반응형
JNDI를 이용한 커넥션 풀에 대해서 정리해봤습니다.
블로그에 쓴글이라 반말이예요... 양해를 ^^
원문 : http://kr.blog.yahoo.com/kwon37xi/1236540.html

Tomcat 5 JNDI DataSource를 통한 DB 커넥션 풀 사용

이미 눈치 채셨겠지만, 요즘 내가 RDBMS 배우기에 열을 올리고 있다.
지금까지는 JSP/Servlet에서 직접 커넥션을 맺거나, 웹 컨텍스트내에 커넥션 풀 라이브러리를 두고 호출에서 사용했는데, 좀 바꿔야겠다.
JNDI를 통한 커넥션 풀 사용은 J2EE 표준이고, 현존하는 거의 모든 웹 컨테이너가 지원한다고 한다.

JNDI를 서버에 설정하는 방법은 각 WAS 별로 다르지만, 사용하는 것은 모두 동일하므로 호환성에 문제도 없다.

이 글은 Jakarta의 DBCP 커넥션 풀과 Tomcat JNDI 설정을 통해 데이터베이스 커넥션 풀을 사용하는 방법이다.

JNDI와 커넥션 풀에 관한 자세한 설명이 JavaServer Pages 3rd ed.에 실려있다. 이 책 너무 좋다. 꼭 읽어보라고 강력하게 권하고 싶다.

* 참조 URL : http://jakarta.apache.org/tomcat/tomcat-5.0-doc/jndi-datasource-examples-howto.html
이 글은 사실상 저 참조 URL의 번역에 가깝다.
* Tomcat Admin을 이용한 DataSource 설정 : http://www.okjsp.pe.kr/lecture/viewlet/okjsp2005/05_webdev_datasource.html

기본적으로 필요한 라이브러리

* commons-dbcp.jar
* commons-collections.jar
* commons-pool.jar

예제 JDBC 드라이버

* Oracle 9i classes12.jar

JNDI Naming Resource 설정

1. 위 라이브러리들을 $CATALINA_HOME/common/lib 에 복사한다. 그 이외 디렉토리에 두면 안된다. ZIP 파일은 JAR로 확장자를 바꿔야 한다. 톰캣은 JAR파일만 클래스패스에 추가한다.

2. Connection 풀을 이용할 경우에는 ResultSet과 Connection 객체를 필히 직접 닫아 줘야만 한다.

3. $CATALINA_HOME/conf/server.xml 혹은 각 웹 컨텍스트별 XML 파일의 <Context>의 자식 요소로 다음을 추가한다.

<Resource name="jdbc/forumDb" auth="Container" type="javax.sql.DataSource"/>
<!-- Resource의 name 속성을 이용해서 각 어플리케이션에서
javax.sql.DataSource 객체를 얻어가게 된다. -->


<!-- 자세한 파라미터 설정은
http://jakarta.apache.org/tomcat/tomcat-5.0-doc/jndi-datasource-examples-howto.html 참조 -->
<ResourceParams name="jdbc/forumDb">
<parameter>
<name>factory</name>
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
</parameter>

<parameter>
<name>maxActive</name>
<value>100</value>
</parameter>

<parameter>
<name>maxIdle</name>
<value>30</value>
</parameter>

<parameter>
<name>maxWait</name>
<value>10000</value>
</parameter>

<!-- DB 사용자명과 비밀번호 설정 -->
<parameter>
<name>username</name>
<value>dbuser</value>
</parameter>
<parameter>
<name>password</name>
<value>dbpasswd</value>
</parameter>

<!-- JDBC 드라이버 클래스 -->
<parameter>
<name>driverClassName</name>
<value>oracle.jdbc.driver.OracleDriver</value>
</parameter>

<!-- JDBC 접속 URL -->
<parameter>
<name>url</name>
<value>jdbc:oracle:thin:@dbhost:1521:ORA</value>
</parameter>
</ResourceParams>


4. 웹 어플리케이션의 web.xml파일에 다음을 추가하여 JNDI 리소스를 사용할 수 있도록 한다.

<resource-ref>
<description>Forum DB Connection</description>
<!-- 다음이 바로 리소스의 이름 -->
<res-ref-name>jdbc/forumDb</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>


JSP/Servlet 에서 사용하기
이제 다음과 같이 JNDI를 이용해 DataSource 객체를 얻고, 그 객체에서 커넥션을 얻어오면 된다.

다음은 서블릿을 작성하고, 그 서블릿에서 DB커넥션을 얻고, 쿼리를 날린 뒤, 그 결과를 JSP 파일에 포워딩하여 JSTL을 이용해 출력하는 것이다.

1. 예제 테이블과 데이터 SQL - 오라클 계정으로 다음과 같은 데이터를 생성했다고 가정하면

create table test (
num NUMBER NOT NULL,
name VARCHAR2(16) NOT NULL
);

truncate table test;

insert into test values(1,'영희');
insert into test values(2, '철수');
insert into test values(3, '미숙');
commit;


2. test.JndiDataSourceTestServlet 소스

package test;

import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

public class JndiDataSourceTestServlet extends HttpServlet {

protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {

Connection conn = null;
ResultSet rs = null;
Statement stmt = null;

try {
// 커넥션을 얻기 위한 전초작업. 이 부분을 메소드화 하면 되겠다. ------------
Context initContext = new InitialContext();
Context envContext = (Context)initContext.lookup("java:/comp/env");
DataSource ds = (DataSource)envContext.lookup("jdbc/forumDb");

// 커넥션 얻기
conn = ds.getConnection();
//------------------------------------------------------------------

String sql = "SELECT * from test";
stmt = conn.createStatement();

rs = stmt.executeQuery(sql);

List results = new ArrayList();

while (rs.next()) {
Map row = new HashMap();

row.put("num", rs.getString("num"));
row.put("name", rs.getString("name"));

results.add(row);
}

request.setAttribute("results", results);

RequestDispatcher rd = request.getRequestDispatcher("/dbtest.jsp");
rd.forward(request, response);

} catch (NamingException e) {
throw new ServletException("JNDI 부분 오류", e);
} catch (SQLException e) {
throw new ServletException("SQL 부분 오류", e);
} finally {
// 리소스를 필히 반환할 것!
if (rs != null) { try { rs.close(); } catch (Exception ignored) {} }
if (stmt != null) { try { stmt.close(); } catch (Exception ignored) {} }
if (conn != null) { try { conn.close(); } catch (Exception ignored) {} }
}
}
}

3. web.xml에 서블릿 등록

<servlet>
<servlet-name>dbtest.svl</servlet-name>
<servlet-class>test.JndiDataSourceTestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>dbtest.svl</servlet-name>
<url-pattern>/dbtest.svl</url-pattern>
</servlet-mapping>

4. /dbtest.jsp 소스

<%@ page contentType="text/html" pageEncoding="EUC-KR" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql" %>

<!DOCTYPE HTML PUBLIC "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
<title>JNDI DataSource Test</title>
</head>
           <body            bgcolor="#FFFFFF">
<h2>Results</h2>

<c:forEach var="row" items="${results}">
NUM : ${row.num}<br />
Name : ${row.name}<br />
<hr />
</c:forEach>
</body>
</html>


5. 이제 웹 브라우저에서 "/dbtest.svl" 을 호출해보면 결과를 볼 수 있다.


전역적인 JNDI 리소스 이용
<Resource>와 <ResourceParams> 요소를 server.xml의 <GlobalNamingResources> 의 자식노드로 옮기면 특정 웹 어플리케이션이 아니라, 이 톰캣에 설치된 전체 웹 어플리케이션에서 사용 할 수 있게 된다. 하지만 각 웹 어플리케이션 "<Context>"에 다음과 같은 설정을 해야 한다.

<ResourceLink
name="jdbc/forumDb"
global="jdbc/forumDb"
type="javax.sql.DataSource"
/>


아니면 server.xml에서 <Host> 요소의 자식으로 다음을 추가하면 각 컨텍스트별 설정 필요없이 전체 웹 어플리케이션 컨텍스트에서 GlobalNamingResources로 지정된 JNDI 리소스를 사용할 수 있다.

<DefaultContext>
<ResourceLink
name="jdbc/forumDb"
global="jdbc/forumDb"
type="javax.sql.DataSource"
/>
</DefaultContext>


문제가 생겼어요!

1. DB 커넥션이 간혹 끊어져요.
Tomcat이 작동중인 JVM이 가비지 컬렉션을 할 때, 그 시간이 JNDI Resource에 파라미터로 설정한 maxWait보다 길게 갈 경우 DB 커넥션이 끊어질 수 있다.
CATALINA_OPTS=-verbose:gc 옵션을 주면 $CATALINA_HOME/logs/catalina.out에 가비지 컬렉션 상황이 기록된다. 거기에 GC 작업에 걸린 시간도 나오니 그것을 참조로 maxWait 파라미터를 늘려주면 된다. 보통 10~15초로 주면 된다.
GC 시간은 거의 99% 이상 1초 이내에 끝나야 하나보다..

2. 무작위로 커넥션이 close 되요.
그건.. Connection 객체를 두 번 이상 close 했기 때문이다.
DB Connection Pool은 close()를 호출할 때 정말로 닫는 것이 아니라, 단지 재사용할 수 있다고 표시만 할 뿐이다.
커넥션을 사용하다가 close()하면 다른 쓰레드이서 이 커넥션을 쓸 수 있는데, 이걸 현재 쓰레드에서 계속 잡고 있다가 또 다시 close()를 해버리면, 다른 쓰레드에서 사용중에 close()됐다고 나와 버리게 되는 거다.

conn.close();
conn = null;

위와 같이 커넥션을 close()한 뒤에 바로 null 로 설정하여 절대로 다시 사용할 수 없게 만들면 이런 실수는 생기지 않을 것이다.
Posted by 1010
98..Etc/Tomcat2009. 1. 30. 19:18
반응형

// tomcat - server.xml파일에 DB Connection생성을 위한 설정(<Host>태그 내부에 추가함)


<Context Path="/myapp" docBase="myapp" debug="5" reloadable="true" crossContext="true">

<Resource name="jdbc/TestDB" auth="Container" type="javax.sql.DataSource"

                maxActive="100" maxIdle="30" maxWait="10000"

                username="sys" password="password" driverClassName="com.mysql.jdbc.Driver"

                url="jdbc:mysql://localhost:3306/javatest?autoReconnect=true"/>

</Context>


//내용설명

Context - path : URL 호출시 사용될 이름

            - docBase : 실제 웹 어플리케이션이 위치한 폴더명

            - debug : 로그 작성 레벨

            - reloadable : 톰캣서버의 재시작 없이 수정된 내용을 불러오기 위한 옵션

            - crossContext : myapp이외의 Context에서도 사용 가능하도록 하는 옵션

Resource - name : Resource명칭(JNDI Lookup 시 사용할 명칭)

              - auth : Resource 관리자를 지정. 여기서는 톰캣컨테이너가 관리자임

              - type : Resource 의 형태 지정. 데이타소스 형태를 지정함

              - maxActive : 최대 연결 가능한 Connection 숫자를 지정함

              - maxIdle : Connection pool 유지를 위해 최대 대기 connection 숫자

              - maxWait : Connection 재 사용을 위해 대기해야 하는 최대 시간(단위:ms)

              - username : DB접속 계정

              - password : DB접속 암호

              - driverClassName : DB와 접속하기 위한 driver 클래스를 지정. 예에서는 MySql임

              - url : 접속한 DB가 위치한 서버명, 포트명, 사용할 데이타베이스명을 지정



// tomcat - web.xml파일에 DB Connection생성을 위한 설정

<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>


//내용설명

resource-ref - description : 참조할 resource에 대한 설명

                  - res-ref-name : 참조할 resource의 명칭. Server.xml에 정의된 이름과 일치해야함

                  - res-type : 참조할 resource 형태로 여기서는 DataSource를 지정함

                  - res-auth : 참조할 resource를 관리할 주체로 톰캣컨테이너를 지정함

Posted by 1010
98..Etc/Tomcat2009. 1. 29. 13:13
반응형
ache Load balancing && Terracotta Sessions Clustering


Apache 2.2.11 + (proxy_ajp, proxy_balancer) + Tomcat 5.5.27 + Terracotta 2.7.2

어제 오늘 열라 삽질한 결과물 입니다.

상용와스 사용하며 개발만 하다보니...

아파치 톰켓 제대로 세팅할 일도 없었고...

Load balancing 할 일은 더욱이 없었고..

Sessions Clustering 할 일은 더더욱 없었는데...


이번에 고객이 와스를 구입 하지 않는 데다..

사이트 두개의 세션을 공유시켜 달라고 해서...

이참에 한 번 세팅해보자 해서.. 시도해봤습니다...


짧은 실력에 더 짧은 영어 실력까지 함께하다 보니...

삽질의 연속.. -_-;;


삽질 해서 돌아가게는 했는데...

저도 이해하고 한게 아니라서... 뭐라 설명 드리긴 뭐 하구요...

혹시 필요하신 분들 있으실까봐...

올려 봅니다...

나~ 중에 어느분이 더 나은 세팅법을 공유해 주시길 바라며.. 이만.. ^^;;



=========================== 설치파일 ===========================
jdk-1_5_0_17-windows-i586-p.exe
apache_2.2.11-win32-x86-no_ssl.msi
apache-tomcat-5.5.27.zip
terracotta-generic-2.7.2.tar.gz



=========================== 설치 디렉토리 ===========================
C:\Program Files\Java\jdk1.5.0_17
D:\test\Apache2.2
D:\test\apache-tomcat-5.5.27
D:\test\terracotta-2.7.2



=========================== System Path 설정 ===========================
JAVA_HOME=C:\Program Files\Java\jdk1.5.0_17
TC_INSTALL_DIR=D:\test\terracotta-2.7.2
CATALINA_HOME=D:\test\apache-tomcat-5.5.27



=========================== 호스트파일에 추가 ===========================
C:\WINDOWS\system32\drivers\etc\hosts

127.0.0.1   server1.example.com
127.0.0.1   server2.example.com



=========================== 아파치 설정 ===========================
D:\test\Apache2.2\conf\httpd.conf

# LoadModule -- 주석을 푼다.
    LoadModule proxy_module modules/mod_proxy.so
    LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
    LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
    LoadModule rewrite_module modules/mod_rewrite.so

# Virtual hosts -- 주석을 푼다.
    Include conf/extra/httpd-vhosts.conf


=========================== 아파치 가상호스트 설정 ===========================
D:\test\Apache2.2\conf\extra\httpd-vhosts.conf

NameVirtualHost *:80

<VirtualHost *:80>
    ServerAdmin server1@example.com

    ServerName server1.example.com
    ServerAlias server2.example.com

    ErrorLog "logs/server1.example.com-error.log"
    CustomLog "logs/server1.example.com-access.log" common

    DocumentRoot "D:/test/sample/WebContent"

    <Directory />
        Options FollowSymLinks
        AllowOverride None
    </Directory>

    <Location /*>
        ProxyPass balancer://tomcat_cluster stickysession=JSESSIONID
    </Location>

    ## mod_proxy_balancer
    ## 필요한 만큼 BalancerMember를 추가하면 자동으로 분산 요청
    ## 아래 주소는 단지 예시일 뿐
    ##
    <Proxy balancer://tomcat_cluster>
        BalancerMember ajp://127.0.0.1:9071 route=tomcat1 loadfactor=50
        BalancerMember ajp://127.0.0.1:9072 route=tomcat2 loadfactor=50
    </Proxy>

    <Directory "D:/test/sample/WebContent">
        Options Indexes FollowSymLinks
        AllowOverride None
        Order allow,deny
        Allow from all

        ## jsp 파일도 index 파일로 추가
        ##
        DirectoryIndex index.html index.jsp

        ## Rewrite를 이용해서 jsp 파일을 proxy_ajp로 Tomcat으로 넘기기
        ##
        RewriteEngine On
        RewriteCond %{REQUEST_URI} /servlet* [OR]
        RewriteCond %{REQUEST_FILENAME} .jsp
        RewriteRule (.*) balancer://tomcat_cluster/$1 [P]
    </Directory>

</VirtualHost>



=========================== 테라코타 설정파일 수정 ===========================

D:\test\terracotta-2.7.2\tools\sessions\configurator-sandbox\tomcat5.5\tc-config.xml

server host 에 테라코타 서버가 설치된 아이피 입력

...
  <servers>
    <server host="127.0.0.1" name="sample">
      <data>data/server-data</data>
      <logs>logs/server-logs</logs>
    </server>
    <update-check>
      <enabled>true</enabled>
    </update-check>
  </servers>
...

...
      <web-applications>
        <web-application>ROOT</web-application>
        <!--
        <web-application>Cart</web-application>
        <web-application>DepartmentTaskList</web-application>
        <web-application>Townsend</web-application>
        -->
      </web-applications>

...


D:\test\terracotta-2.7.2\tools\sessions\configurator-sandbox\tomcat5.5\start.bat

세션을 공유할 도메인 입력(server1.example.com 과 server2.example.com 이 세션을 공유해야 하는 경우에만 필요함)

...
set OPTS=%TC_JAVA_OPTS% -Dwebserver.log.name=tomcat-%1
set OPTS=%OPTS% -Dcom.sun.management.jmxremote
set OPTS=%OPTS% -Dproject.name=Configurator
set OPTS=%OPTS% -Dcom.tc.session.cookie.domain=.example.com
set JAVA_OPTS=%OPTS% %JAVA_OPTS%
...


=========================== 톰켓 server.xml 수정 ===========================

D:\test\terracotta-2.7.2\tools\sessions\configurator-sandbox\tomcat5.5\9081\conf\server.xml

<Server port="9051" shutdown="SHUTDOWN">
  <Service name="Catalina">

    <!-- Define a non-SSL HTTP/1.1 Connector on port 8080 -->
    <Connector port="9081" maxHttpHeaderSize="8192"
               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
               enableLookups="false" redirectPort="8443" acceptCount="100"
               connectionTimeout="20000" disableUploadTimeout="true" />

    <!-- Define an AJP 1.3 Connector on port 8009 -->
    <Connector port="9071"
               enableLookups="false" redirectPort="8443" protocol="AJP/1.3" />

    <Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat1">
      <Host name="localhost" appBase="webapps"
            unpackWARs="true" autoDeploy="true"
            xmlValidation="false" xmlNamespaceAware="false">
        <Context path="/" reloadable="true" docBase="D:\test\sample\WebContent" workDir="work" />
      </Host>
    </Engine>
  </Service>
</Server>


D:\test\terracotta-2.7.2\tools\sessions\configurator-sandbox\tomcat5.5\9082\conf\server.xml

<Server port="9052" shutdown="SHUTDOWN">
  <Service name="Catalina">

    <!-- Define a non-SSL HTTP/1.1 Connector on port 8080 -->
    <Connector port="9082" maxHttpHeaderSize="8192"
               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
               enableLookups="false" redirectPort="8443" acceptCount="100"
               connectionTimeout="20000" disableUploadTimeout="true" />

    <!-- Define an AJP 1.3 Connector on port 8009 -->
    <Connector port="9072"
               enableLookups="false" redirectPort="8443" protocol="AJP/1.3" />

    <Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat2">
      <Host name="localhost" appBase="webapps"
            unpackWARs="true" autoDeploy="true"
            xmlValidation="false" xmlNamespaceAware="false">
        <Context path="/" reloadable="true" docBase="D:\test\sample\WebContent" workDir="work" />
      </Host>
    </Engine>
  </Service>
</Server>


=========================== 셈플소스 복사 ===========================

D:\test\terracotta-2.7.2\tools\sessions\configurator-sandbox\tomcat5.5\9081\webapps\Cart

하위의 소스를 아래 디렉토리로 복사

D:\test\sample\WebContent


=========================== 테라코타 서버 실행 ===========================
D:\test\terracotta-2.7.2\bin>start-tc-server.bat

=========================== 아파치 서버 실행 ===========================
Apache Service Monitor [start] 버튼 클릭

=========================== 톰켓 서버(테라코타 클라이언트) 실행 ===========================
D:\test\terracotta-2.7.2\tools\sessions\configurator-sandbox\tomcat5.5>start.bat 9081
D:\test\terracotta-2.7.2\tools\sessions\configurator-sandbox\tomcat5.5>start.bat 9082


=========================== 잘 돌아가는가 확인 ===========================
http://server1.example.com/carts.jsp
http://server2.example.com/carts.jsp


=========================== 끝!!! ===========================



참고 사이트들....


http://www.javaservice.net/~java/bbs/read.cgi?m=&b=qna2&c=r_p&n=1224247277&p=7&s=d

http://okjsp.pe.kr/seq/127429

http://www.ibm.com/developerworks/kr/library/opendw/20071231/

http://www.terracotta.org/web/display/orgsite/Tomcat+Integration#TomcatIntegration-SessionContinuityAcrossServers

http://www.terracotta.org/web/display/orgsite/Sessions+Quick+Start#SessionsQuickStart-UnclusteredWebApplications


http://judy98.tistory.com/116

http://wiki.kldp.org/wiki.php/Apache2Tomcat5Howto2

http://openframework.or.kr/Wiki.jsp?page=Apache_tomcat_using_modproxy_on_windows#section-Apache_tomcat_using_modproxy_on_windows-_EB_AA_A8_EB_93_88_ED_99_95_EC_9D_B8

http://www.okjsp.pe.kr/seq/130244

http://www-128.ibm.com/developerworks/kr/library/opendw/20061017/#main

http://www.javamania.pe.kr/zbxe/?sort_index=voted_count&order_type=desc&mid=qna&comment_srl=4920&listStyle=webzine&document_srl=2895

http://sakuragis.egloos.com/4590029

http://hmjkor.tistory.com/tag/Apache2

http://theeye.pe.kr/entry/Proxt-AJP-mod_rewrite%B8%A6-%C0%CC%BF%EB%C7%CF%BF%A9-Apache-22-Tomcat-%BF%CF%BA%AE-%BF%AC%B5%BF%C7%CF%B1%E2

http://www.superuser.co.kr/home/edu/offline/gnu3/?doc=bbs/gnuboard.php&bo_table=review_sw&mode=body&page=1&wr_id=33&mode=body

http://leadingkorea.kr/62

http://forcemax.tistory.com/69

외 다수~~~~~~~~

Posted by 1010
98..Etc/Tomcat2008. 10. 27. 15:01
반응형
톰캣에서 java.lang.IllegalStateException: Post too large 가 발생하는 경우


http://confluence.atlassian.com/display/DOC/Max+size+of+HTTP+POST+request+and+Confluence+page+size

아래는 $TOMCAT_HOME/conf/server.xml에 설정을 해야 하는 옵션이다.
maxPostSize에 필요한 용량제한을 셋팅하면 된다.

<Connector port="8102" minProcessors="1" maxProcessors="5"
            enableLookups="false" redirectPort="8443" acceptCount="100"
            debug="0" connectionTimeout="120000" useBodyEncodingForURI="true"
            maxPostSize="3145728"
            protocol="AJP/1.3" />
Posted by 1010
98..Etc/Tomcat2008. 8. 17. 02:48
반응형

1. jdk 1.5이상이면 아래 설정을 JAVA_OPTS안에 추가한다면 YourKit을 가지고 힙덤프를 분석할 수 있다.
 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/logs/heapdump


 

2. Jasper 2 JSP Engine 지원을 위해 $CATALINA_BASE/conf/web.xml 설정 변경하라.
 - development : false, genStringAsCharArray : true, modificationTestInterval : true, trimSpaces : true
 - 자세한 건 여기를 참조하라.


3. 가용성 확보를 위해 Tomcat의 clustering/session replication을 사용하라.
 - 사용방법은 여기를 참조하라.


4. error pages를 작성하여 적용하라.(web.xml)
 - <error-page>
      <error-code>404</error-code>
      <location>/error/404.html</location>
   </error-page>


5. 어플리케이션에서 System.out과 System.err를 제거하고 Log4j를 사용하라.


6. application마다 같은 라이브러리는 WEB-INF/lib에서 CATALINA_HOME/shared/lib로 옮겨서 공유하라.
 - 메모리를 절약할 수 있다.


7. memory parameters를 잘 활용하라.


8. 불필요한 어플리케이션을 제거하라.


9. Manager서버의 보안을 강화하라.
 - CATALINA_HOME/conf/tomcat-users.xml
  <role rolename="manager">
   <user username="darren" password="ReallyComplexPassword" roles="manager"></user>
  </role>
 - CATALINA_HOME/conf/server.xml에 IP 블럭킹 기능도 유용하다.
  <Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="192.168.1.*"></Valve>


10. server.xml을 최적화 하라.
 - 서버 환경에 맞는 CATALINA_HOME/conf/server-original.xml, CATALINA_HOME/conf/server-minimal.xml 선택하여 server.xml로 변경하라.


11. 톰켓 업그레이드는 설치디렉토리를 분리하여 적용하라.


12. Tomcat 서버는 root로 띄우지 마라.
 - 자세한 내용은 여기를 참조하라.


13. Precompile JSPs (at build time)
 - 자세한 내용은 여기를 참조하라.


14. 디렉토리 보이는 걸 막아라.
  - CATALINA_HOME/conf/web.xml
  <servlet>
   <servlet-name>default</servlet-name>
   <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
   <init-param>
   <param-name>debug</param-name>
   <param-value>0</param-value>
   </init-param>
   <init-param>
   <param-name>listings</param-name>
   <param-value>false</param-value>  <!-- make sure this is false -->
   </init-param>
   <load-on-startup>1</load-on-startup>
  </servlet>


15. 듀얼 코어 CPU를 사용할 경우 쓰레드풀을 250개 이상 설정하라.


16. Tomcat MBeans이나 다양한 모니터링 도구를 활용하여 서버를 모니터링하라.
 - 자세한 내용은 여기를 참조하라.


17. jdk1.5, 1.6이 성능이 좋다.


18. -server JVM option을 사용하라.


19. GZIP compression을 사용하라.
 - <Connector>compression="on"
   compressableMimeType="text/html,text/xml,text/plain,application/xml"
   </Connector>
 - 자세한 건 여기를 참조하라.


20. Security Manager를 잘 사용하라.
 - 자세한건 여기를 참조하라.



출처 : http://blog.paran.com/pmang/21456729
Posted by 1010