Tomcat Multi Instance 설정하기
Tomcat 7 서버는 Multi Instance 라는 기능을 가지고 있습니다. 하나의 엔진에 다수의 Instance 를 구동하게하는 것을 말합니다.
Tomcat 7 용어 정리
Tomcat Multi Instance 설정하기 전에 용어를 설명하겠습니다. Tomcat 은 엔진과 인스턴스(Intance) 로 나뉩니다. 이는 디렉토리별로 구분이 가능한데, 엔진부분과 인스턴스 부분의 디렉토리는 다음과 같습니다.
- Tomcat Engine 부분: bin, lib
- Tomcat Instance 부분: conf, logs, temp, work, webapps
사실 Tomcat 을 다운받아 압축을 해제하면 엔진부분과 인스턴스부분이 함께 들어 있기 때문에 별 구별이 안되는 측면이 있지만 엄밀히 따지면 위와같이 구분을 할 수 있습니다.
사실 Tomcat 엔진은 아무것도 아닙니다. Tomcat 엔진은 실제로 단독으로 구동되지 않습니다. Tomcat 엔진의 역활은 자바 소프트웨어를 실행시켜주는 역활만 담당합니다. 여기서 자바 소프트웨어라는 것이 바로 Tomcat 인스턴스 입니다.
Tomcat 엔진이 자바 소프트웨어를 실행시킨다는 말은 결국에는 JVM 이 작동하는 것입니다. 따라서 Tomcat 인스턴스는 JVM 이 구동된다는 것이며 Multi Instance 는 여러개의 Tomcat JVM 을 구동한다는 것을 의미 합니다.
Tomcat 구동
Tomcat 이 구동될때에는 시스템 환경변수에 의존 합니다. bin/startup.sh 스크립트는 Tomcat 을 구동되도록하는 스크립트인데, 이 스크립트는 환경변수를 세팅하고 catalina.sh 스크립트를 호출하는 역활을 합니다. 실제 실행하면 환경변수내용을 볼수 있습니다.
1 2 3 4 5 6 7 |
]# ./startup.sh Using CATALINA_BASE: /opt/apache-tomcat-7.0.57 Using CATALINA_HOME: /opt/apache-tomcat-7.0.57 Using CATALINA_TMPDIR: /opt/apache-tomcat-7.0.57/temp Using JRE_HOME: /usr Using CLASSPATH: /opt/apache-tomcat-7.0.57/bin/bootstrap.jar:/opt/apache-tomcat-7.0.57/bin/tomcat-juli.jar Tomcat started. |
먼저, Tomcat 엔진은 CATALINA_HOME 환경변수만 세팅합니다. 이는 Tomcat 엔진의 기본 디렉토리를 정의하는 것으로 Tomcat 의 바이너리 파일과 라이브러리가 어디에 있는지를 지정해 주는 것입니다.
CATALINA_BASE 는 Tomcat 인스턴스의 설정과 웹애플리케이션의 루트(Root) 디렉토리를 정의 합니다. CATALINA_BASE 가 Tomcat 인스턴스에 대한 환경변수이기 때문에 Tomcat 인스턴스 디렉토리인 conf, logs, temp, work, webapps 에 대한 디렉토리를 정의하는 것과 같습니다. 이는 다시 말해서 Tomcat 에서 실행시킬 자바 웹 소프트웨어의 루트 디렉토리를 지정하는 것이다라고 말 수 있습니다.
그렇다면 CTALINA_BASE 를 다르게하면 하나의 Tomcat 엔진에서 여러개의 인스턴스를 구동할 수 있다는 것이 됩니다.
Multi Instance 만들기
이 포스트에서는 다음과 같이 해보도록 하겠습니다.
- Tomcat Engine : /opt/tomcat-7
- Tomcat Instance: 리눅스의 시스템 계정을 만들고 자바 웹 애플리케이션 디렉토리 생성.
먼저 Tomcat Engine 을 설치해줍니다.
1 |
cp -a apache-tomcat-7.0.57 /opt/tomcat-7 |
Tomcat Instance 를 위한 시스템 계정을 생성해 줍니다. 계정을 생성할때는 먼저 시스템 그룹을 생성하고 Tomcat 시스템 계정은 전부 이 시스템 그룹에 등록하는 방법으로 생성 합니다.
1 2 3 4 |
groupadd tomcat useradd -g tomcat -s /usr/sbin/nologin instance1 useradd -g tomcat -s /usr/sbin/nologin instance2 useradd -g tomcat -s /usr/sbin/nologin instance3 |
그리고 다음과 같이 Tomcat Instance 관련 파일들을 전부 복사해 줍니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# instance1 cp -a conf /home/instance1 cp -a webapps /home/instance1 mkdir /home/instance1/logs mkdir /home/instance1/work chown instance1:tomcat -R /home/instance1 # instance2 cp -a conf /home/instance2 cp -a webapps /home/instance2 mkdir /home/instance2/logs mkdir /home/instance2/work chown instance2:tomcat -R /home/instance2 # instance3 cp -a conf /home/instance3 cp -a webapps /home/instance3 mkdir /home/instance3/logs mkdir /home/instance3/work chown instance3:tomcat -R /home/instance3 |
각각의 Tomcat Instance 는 각각의 자바 웹 애플리케이션들이기 때문에 서로 가진 설정들에서 포트(port)를 변경해줍니다. Tomcat 의 포트는 다음과 같은 것들이 있습니다.
- Shutdown port: 이 포트는 톰캣을 셧다운하는데 사용되어 집니다. shutdown.sh 스크립트가 호출되면 이 포트로 시그널(Signal)을 보냅니다. 이 포트는 Tomcat 자바 프로세스로 리스닝되고 있습니다. 만약 시그널을 받으면, 프로세스는 종료됩니다.
- Connector port: 이 포트는 외부 클라이언트에게 애플리케이션을 보여주기위한 실제적인 포트 입니다.
- Ajp port: 이 포트는 웹 서버가 Tomcat 과 커뮤니케이션을 위해서 사용되어 집니다. 또, 이 포트는 로드 밸런스 서버를 세팅할때에도 사용되어 집니다.
- Redirect port: SSL 접속 요청이 들어올경우에 Catalina 는 자동적으로 이 포트로 redirect 합니다.
각각의 Tomcat Instance 는 위에서 나열한 포트들이 중복되지 않도록 설정해 줍니다. 이 설정은 각 인스턴스의 server.xml 파일에 정의되어 있습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
<!-- instance1 ports --> <Server port="8105" shutdown="SHUTDOWN"> <Listener className="org.apache.catalina.startup.VersionLoggerListener" /> .... <Connector port="8180" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="81443" /> .... <Connector port="8109" protocol="AJP/1.3" redirectPort="81443" /> <!-- instance2 ports --> <Server port="8205" shutdown="SHUTDOWN"> <Listener className="org.apache.catalina.startup.VersionLoggerListener" /> .... <Connector port="8280" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="82443" /> .... <Connector port="8209" protocol="AJP/1.3" redirectPort="82443" /> <!-- instance3 ports --> <Server port="8305" shutdown="SHUTDOWN"> <Listener className="org.apache.catalina.startup.VersionLoggerListener" /> .... <Connector port="8380" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="83443" /> .... <Connector port="8309" protocol="AJP/1.3" redirectPort="83443" /> |
start.sh, shutdown.sh
각각의 인스턴스들에 대해서 start.sh, shutdown.sh 를 다음과 같이 만들어 줍니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#!/bin/sh export INSTANCE_OWNER=instance1 export CATALINA_HOME=/opt/tomcat-7 export CATALINA_BASE=/home/$InSTANCE_OWNER export CATALINA_PID=/home/$INSTANCE_OWNER/conf/instance1.pid export JMX_OPTS=" -Dcom.sun.management.jmxremote \ -Dcom.sun.management.jmxremote.port=8090 \ -Dcom.sun.management.jmxremote.authenticate=false \ -Djava.rmi.server.hostname=localhost \ -Dcom.sun.management.jmxremote.ssl=false " #export MEM_OPTS="-Xms4G -Xmx4G -XX:PermSize=256m -XX:MaxPermSize=256m" # ParallelGC export JVM_OPTS="-XX:NewRatio=3 -XX:ParallelGCThreads=4 -XX:+DisableExplicitGC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/instance1/logs -verbosegc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:/home/instance1/logs/gc_`date "+%Y%m%d%H"`.log -Djava.security.egd=file:/dev/./urandom" # CMS GC #export JVM_OPTS="-XX:NewRatio=7 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSFullGCsBeforeCompaction=0 -XX:+DisableExplicitGC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/instance1/logs -verbosegc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:/home/instance1/logs/gc_`date "+%Y%m%d%H"`.log -Djava.security.egd=file:/dev/./urandom" export CATALINA_OPTS=" ${JMX_OPTS} ${CATALINA_OPTS} ${JVM_OPTS}" /bin/su -p -s /bin/sh $INSTANCE_OWNER $CATALINA_HOME/bin/startup.sh |
1 2 3 4 5 6 7 8 |
#!/bin/sh export INSTANCE_OWNER=instance1 export CATALINA_HOME=/opt/tomcat-7 export CATALINA_BASE=/home/$INSTANCE_OWNER export CATALINA_PID=/home/$INSTANCE_OWNER/conf/instance1.pid /bin/su -p -s /bin/sh $INSTANCE_OWNER $CATALINA_HOME/bin/shutdown.sh |
‘INSTANCE_OWNER’ 환경변수에 인스턴스 계정명을 알맞게 넣고 작성해주면 됩니다.
그리고 이 스크립트를 실행하면 각각의 인스턴스들이 실행이 됩니다.