2017년 3월 28일 화요일

[EtC] Apache, Tomcat Load Balancing & Session Clustering


아파치2.4 와 톰켓7.0 을 이용한 로드벨런싱, 세션 클러스터 환경 구성


1) 테스트 환경
- os : ubuntu 16.04 64bit
- java : 1.7.0_80
- apache : 2.4.25
- tomcat : 7.0.76


2) java 설치
# tar zxvf jdk-7u80-linux-x64.tar.gz -C /usr/local/
# ln -s /usr/local/jdk1.7.0_80/bin/java /usr/bin/java


3) Apach2.4 설치를 위한 APR, APR-util 및 의존 패키지 설치

* 아파치 2.4 버젼 부터는 APR 과 APR-util 을 따로 컴파일 하여 설치 하여야 한다고 한다.
http://apr.apache.org/download.cgi 에서 다운로드

 3-1) APR 다운로드 및 컴파일, 설치
# wget http://apache.mirror.cdnetworks.com/apr/apr-1.5.2.tar.gz
# tar zxvf apr-1.5.2.tar.gz
# cd apr-1.5.2/
# ./configure
# make
# make install

 3-2) APR-util 다운로드 및 컴파일, 설치
# wget http://apache.mirror.cdnetworks.com/apr/apr-util-1.5.4.tar.gz
# tar zxvf apr-util-1.5.4.tar.gz
# cd apr-util-1.5.4
# ./configure --with-apr=/usr/local/apr
# make
# make install

 3-3) 의존 패키지 설치
# apt-get install libpcre3-dev
  * RPM 기반의 CentOS7 의 경우 yum을 이용하여 pcre-devel 패키지를 설치 한다.


4) Apach2.4 설치(컴파일) 및 구동 테스트
# wget http://apache.mirror.cdnetworks.com/httpd/httpd-2.4.25.tar.gz
# tar zxvf httpd-2.4.25.tar.gz 
# cd httpd-2.4.25
# ./configure --prefix=/usr/local/apache-2.4.25
# make
# make install

# /usr/local/apache-2.4.25/bin/apachectl start
 * 브라우저를 이용하여 http://localhost 에 접속하여 본다.

# /usr/local/apache-2.4.25/bin/apachectl stop


5) Apach2.4 설정 파일 수정
# cp /usr/local/apache-2.4.25/conf/httpd.conf /usr/local/apache-2.4.25/conf/httpd.conf.ori
# vi /usr/local/apache-2.4.25/conf/httpd.conf

* 아래의 내용들을 찾아 주석 해제 한다.

LoadModule slotmem_shm_module modules/mod_slotmem_shm.so
LoadModule autoindex_module modules/mod_autoindex.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
LoadModule status_module modules/mod_status.so
LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so
LoadModule lbmethod_bytraffic_module modules/mod_lbmethod_bytraffic.so
LoadModule lbmethod_bybusyness_module modules/mod_lbmethod_bybusyness.so
LoadModule lbmethod_heartbeat_module modules/mod_lbmethod_heartbeat.so

Include conf/extra/httpd-vhosts.conf


# cp /usr/local/apache-2.4.25/conf/extra/httpd-vhosts.conf /usr/local/apache-2.4.25/conf/extra/httpd-vhosts.conf.ori
vi /usr/local/apache-2.4.25/conf/extra/httpd-vhosts.conf
* httpd-vhosts.conf 기존 내용 제거 후 아래의 내용을 수정 하여 추가 한다.

<VirtualHost *:80>
ServerAdmin admin@test.co.kr
ServerName test.co.kr

ProxyRequests Off
ProxyPass / balancer://mycluster/
ProxyPassReverse / balancer://mycluster

<Proxy balancer://mycluster stickysession=JSESSIONID|jsessionid scolonpathdelim=On>
BalancerMember http://127.0.0.1:8080 route=1
BalancerMember http://127.0.0.1:8081 route=2
</Proxy>
</VirtualHost>


6) Apach2.4 서비스 등록
# vi /etc/init.d/apache

------------------- 파일 내용 // -------------------------
#!/bin/bash

### BEGIN INIT INFO
# Provides:    apache
# Required-Start:  $remote_fs $syslog
# Required-Stop:   $remote_fs $syslog
# Default-Start:   2 3 4 5
# Default-Stop:    0 1 6
# Short-Description: auto start apache web server
# Description: Start Web Server
### END INIT INFO

export APACHE_HOME="/usr/local/apache-2.4.25/"

case $1 in
start)
sh $APACHE_HOME/bin/apachectl -k start
;;
stop)
sh $APACHE_HOME/bin/apachectl -k stop
;;
restart)
sh $APACHE_HOME/bin/apachectl -k stop
sh $APACHE_HOME/bin/apachectl -k start
;;
esac
exit 0
------------------- // 파일 내용 -------------------------

# chmod 755 /etc/init.d/apache
# update-rc.d apache defaults
# chkconfig --add apache
# chkconfig -list | grep -i apache
apache                    0:off  1:off  2:on   3:on   4:on   5:on   6:off
# /etc/init.d/apache start
httpd (pid 1771) already running

# ps -ef | grep -i apache
root       670     1  0 15:05 ?        00:00:00 /usr/local/apache-2.4.25/bin/httpd -k start
daemon     671   670  0 15:05 ?        00:00:00 /usr/local/apache-2.4.25/bin/httpd -k start
daemon     672   670  0 15:05 ?        00:00:00 /usr/local/apache-2.4.25/bin/httpd -k start
daemon     674   670  0 15:05 ?        00:00:00 /usr/local/apache-2.4.25/bin/httpd -k start


7) tomcat 사용자 생성
# useradd -m tomcat
# echo 'tomcat:p@ssw0rd' | chpasswd

* 배포판에 따라 chpasswd 명령이 없는 경우 passwd tomcat 명령으로 tomcat 사용자의 비밀번호를 변경 한다.


8) Tomcat 7.0 다운로드 및 환경설정
# su - tomcat
$ cd
$ pwd 
/home/tomcat
$ wget http://apache.mirror.cdnetworks.com/tomcat/tomcat-7/v7.0.76/bin/apache-tomcat-7.0.76.tar.gz

 8-1)Tomcat 1호기, 2호기 압축 해제 및 시작, 종료 명령 변경
$ tar zxvf apache-tomcat-7.0.76.tar.gz -C apache-tomcat-7.0.76_1
$ tar zxvf apache-tomcat-7.0.76.tar.gz -C apache-tomcat-7.0.76_2

$ mv ~/apache-tomcat-7.0.76_1/bin/startup.sh ~/apache-tomcat-7.0.76_1/bin/startup1.sh 
$ mv ~/apache-tomcat-7.0.76_1/bin/shutdown.sh ~/apache-tomcat-7.0.76_1/bin/shutdown1.sh 

$ mv ~/apache-tomcat-7.0.76_2/bin/startup.sh ~/apache-tomcat-7.0.76_2/bin/startup2.sh 
$ mv ~/apache-tomcat-7.0.76_2/bin/shutdown.sh ~/apache-tomcat-7.0.76_2/bin/shutdown2.sh

 8-2) Tomcat 1호기 의 catalina.sh 파일 내용에 추가(절대 경로 입력)
$ cp ~/apache-tomcat-7.0.76_1/bin/catalina.sh ~/apache-tomcat-7.0.76_1/bin/catalina.sh.ori
$ vi ~/apache-tomcat-7.0.76_1/bin/catalina.sh
...중략...
export CATALINA_HOME=/home/tomcat/apache-tomcat-7.0.76_1
export CATALINA_BASE=/home/tomcat/apache-tomcat-7.0.76_1
CATALINA_PID=/home/tomcat/apache-tomcat-7.0.76_1/bin/tomcat.pid
...중략...

 8-3) Tomcat 2호기 의 catalina.sh 파일 내용에 추가(절대 경로 입력)
$ cp ~/apache-tomcat-7.0.76_2/bin/catalina.sh ~/apache-tomcat-7.0.76_2/bin/catalina.sh.ori
$ vi ~/apache-tomcat-7.0.76_2/bin/catalina.sh
...중략...
export CATALINA_HOME=/home/tomcat/apache-tomcat-7.0.76_2
export CATALINA_BASE=/home/tomcat/apache-tomcat-7.0.76_2
CATALINA_PID=/home/tomcat/apache-tomcat-7.0.76_2/bin/tomcat.pid
...중략...

 8-4) Tomcat 1,2 호기의 시작, 종료 명령을 PATH 에 등록
$ vi ~/.bashrc
...중략...
 export JAVA_HOME="/usr/local/jdk1.7.0_80/"
 export CATALINA_HOME1=/home/tomcat/apache-tomcat-7.0.76_1
 export CATALINA_HOME2=/home/tomcat/apache-tomcat-7.0.76_2
 export PATH=$PATH:$JAVA_HOME/bin:$CATALINA_HOME1/bin:$CATALINA_HOME2/bin
...중략...

$ source ~/.bashrc
$ java -version
 java version "1.7.0_80"
 Java(TM) SE Runtime Environment (build 1.7.0_80-b15)
 Java HotSpot(TM) 64-Bit Server VM (build 24.80-b11, mixed mode)

 8-5) Tomcat 1호기의 server.xml 파일 수정
$ cp ~/apache-tomcat-7.0.76_1/conf/server.xml ~/apache-tomcat-7.0.76_1/conf/server.xml.ori
$ vi ~/apache-tomcat-7.0.76_1/conf/server.xml

<Server port="8005" shutdown="SHUTDOWN">
... 중략 ...
<Connector port="8080"
protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
disableUploadTimeout="true"
enableLookups="false"
URIEncoding="UTF-8" />
... 중략 ...
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
... 중략 ...
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat1">
... 중략 ...
<!-- 주석 해제 및 아래 내용 추가 -->
 <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="5">
<Manager className="org.apache.catalina.ha.session.DeltaManager"
  expireSessionsOnShutdown="false"
  notifyListenersOnReplication="true"/>

 <Channel className="org.apache.catalina.tribes.group.GroupChannel">
<Membership className="org.apache.catalina.tribes.membership.McastService"
address="228.0.0.4"
port="45564"
frequency="500"
dropTime="3000"/>
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
 address="auto"
 port="4000"
 autoBind="100"
 selectorTimeout="5000"
 maxThreads="6"/>

<Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
 <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
</Sender>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
 </Channel>

 <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
filter=".*\.gif|.*\.js|.*\.jpeg|.*\.jpg|.*\.png|.*\.htm|.*\.html|.*\.css|.*\.txt"/>
 <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>

 <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
tempDir="/tmp/war-temp/"
deployDir="/tmp/war-deploy/"
watchDir="/tmp/war-listen/"
watchEnabled="false"/>

 <ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener" />
 <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener" />
</Cluster>

 8-6) Tomcat 2호기의 server.xml 파일 수정
$ cp ~/apache-tomcat-7.0.76_2/conf/server.xml ~/apache-tomcat-7.0.76_2/conf/server.xml.ori
$ vi ~/apache-tomcat-7.0.76_2/conf/server.xml

<Server port="8006" shutdown="SHUTDOWN">
... 중략 ...
<Connector port="8081"
protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
disableUploadTimeout="true"
enableLookups="false"
URIEncoding="UTF-8" />
... 중략 ...
<Connector port="8010" protocol="AJP/1.3" redirectPort="8443" />
... 중략 ...
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat2">
... 중략 ...
<!-- 주석 해제 및 아래 내용 추가 -->
 <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="5">

<Manager className="org.apache.catalina.ha.session.DeltaManager"
  expireSessionsOnShutdown="false"
  notifyListenersOnReplication="true"/>

 <Channel className="org.apache.catalina.tribes.group.GroupChannel">
<Membership className="org.apache.catalina.tribes.membership.McastService"
address="228.0.0.4"
port="45564"
frequency="500"
dropTime="3000"/>
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
 address="auto"
 port="4001"
 autoBind="100"
 selectorTimeout="5000"
 maxThreads="6"/>

<Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
 <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
</Sender>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
 </Channel>

 <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
filter=".*\.gif|.*\.js|.*\.jpeg|.*\.jpg|.*\.png|.*\.htm|.*\.html|.*\.css|.*\.txt"/>
 <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>

 <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
tempDir="/tmp/war-temp/"
deployDir="/tmp/war-deploy/"
watchDir="/tmp/war-listen/"
watchEnabled="false"/>

 <ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener" />
 <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener" />
</Cluster>


 8-7) Tomcat 1,2 호기 시작 테스트
$ startup1.sh
 Using CATALINA_BASE:   /home/tomcat/apache-tomcat-7.0.76_1
 Using CATALINA_HOME:   /home/tomcat/apache-tomcat-7.0.76_1
 Using CATALINA_TMPDIR: /home/tomcat/apache-tomcat-7.0.76_1/temp
 Using JRE_HOME:        /usr/local/jdk1.7.0_80/
 Using CLASSPATH:       /home/tomcat/apache-tomcat-7.0.76_1/bin/bootstrap.jar:/home/tomcat/apache-tomcat-7.0.76_1/bin/tomcat-juli.jar
 Tomcat started.

$ startup2.sh
 Using CATALINA_BASE:   /home/tomcat/apache-tomcat-7.0.76_2
 Using CATALINA_HOME:   /home/tomcat/apache-tomcat-7.0.76_2
 Using CATALINA_TMPDIR: /home/tomcat/apache-tomcat-7.0.76_2/temp
 Using JRE_HOME:        /usr/local/jdk1.7.0_80/
 Using CLASSPATH:       /home/tomcat/apache-tomcat-7.0.76_2/bin/bootstrap.jar:/home/tomcat/apache-tomcat-7.0.76_2/bin/tomcat-juli.jar
 Tomcat started.

 * 브라우저를 이용하여 http://192.168.0.1:8080, http://192.168.0.1:8081 에 접속하여 본다.

 8-8) Tomcat 1,2 호기 종료 테스트
$ shutdown1.sh
 Using CATALINA_BASE:   /home/tomcat/apache-tomcat-7.0.76_1
 Using CATALINA_HOME:   /home/tomcat/apache-tomcat-7.0.76_1
 Using CATALINA_TMPDIR: /home/tomcat/apache-tomcat-7.0.76_1/temp
 Using JRE_HOME:        /usr/local/jdk1.7.0_80/
 Using CLASSPATH:       /home/tomcat/apache-tomcat-7.0.76_1/bin/bootstrap.jar:/home/tomcat/apache-tomcat-7.0.76_1/bin/tomcat-juli.jar

$ shutdown2.sh
 Using CATALINA_BASE:   /home/tomcat/apache-tomcat-7.0.76_2
 Using CATALINA_HOME:   /home/tomcat/apache-tomcat-7.0.76_2
 Using CATALINA_TMPDIR: /home/tomcat/apache-tomcat-7.0.76_2/temp
 Using JRE_HOME:        /usr/local/jdk1.7.0_80/
 Using CLASSPATH:       /home/tomcat/apache-tomcat-7.0.76_2/bin/bootstrap.jar:/home/tomcat/apache-tomcat-7.0.76_2/bin/tomcat-juli.jar


 8-9) Tomcat 메니져 사용을 위한 설정 부분(필수 아님)

* 이 문서에서는 나중에 jenkins 사용을 위해 설정 하였다.

$ cp ~/apache-tomcat-7.0.76_1/conf/tomcat-users.xml ~/apache-tomcat-7.0.76_1/conf/tomcat-users.xml.ori
$ cp ~/apache-tomcat-7.0.76_2/conf/tomcat-users.xml ~/apache-tomcat-7.0.76_2/conf/tomcat-users.xml.ori
$ vi ~/apache-tomcat-7.0.76_1/conf/tomcat-users.xml
...중략...
<!-- 아래의 내용을 추가 한다 -->
<role rolename="manager-gui"/>
<role rolename="manager-script"/>
<role rolename="manager-status"/>
<role rolename="manager-gui"/>
<user username="tomcat" password="p@ssW0rd" roles="manager-gui, manager-script, manager-status, manager-gui"/>

$ vi ~/apache-tomcat-7.0.76_2/conf/tomcat-users.xml
...중략...
<!-- 아래의 내용을 추가 한다 -->
<role rolename="manager-gui"/>
<role rolename="manager-script"/>
<role rolename="manager-status"/>
<role rolename="manager-gui"/>
<user username="tomcat" password="p@ssW0rd" roles="manager-gui, manager-script, manager-status, manager-gui"/>  

9) Tomcat 1,2 호기 서비스 등록
# vi /etc/init.d/tomcat
------------------- 파일 내용 // -------------------------
#!/bin/bash

### BEGIN INIT INFO
# Provides:    Tomcat1
# Required-Start:  $remote_fs $syslog
# Required-Stop:   $remote_fs $syslog
# Default-Start:   2 3 4 5
# Default-Stop:    0 1 6
# Short-Description: Auto Start Tomcat1 Server
# Description: Start Web Application Server
### END INIT INFO

export CATALINA_HOME="/home/jhkim1981/tomcat/apache-tomcat-7.0.76_1"

case $1 in
start)
su - tomcat -c $CATALINA_HOME/bin/startup1.sh
;;
stop)
su - tomcat -c $CATALINA_HOME/bin/shutdown1.sh
;;
restart)
su - tomcat -c $CATALINA_HOME/bin/shutdown1.sh
su - tomcat -c $CATALINA_HOME/bin/startup1.sh
;;
esac
exit 0
------------------- // 파일 내용 -------------------------




# vi /etc/init.d/tomcat2
------------------- 파일 내용 // -------------------------
#!/bin/bash

### BEGIN INIT INFO
# Provides:    Tomcat2
# Required-Start:  $remote_fs $syslog
# Required-Stop:   $remote_fs $syslog
# Default-Start:   2 3 4 5
# Default-Stop:    0 1 6
# Short-Description: Auto Start Tomcat2 Server
# Description: Start Web Application Server
### END INIT INFO

export CATALINA_HOME="/home/jhkim1981/tomcat/apache-tomcat-7.0.76_2"

case $1 in
start)
su - tomcat -c $CATALINA_HOME/bin/startup1.sh
;;
stop)
su - tomcat -c $CATALINA_HOME/bin/shutdown1.sh
;;
restart)
su - tomcat -c $CATALINA_HOME/bin/shutdown1.sh
su - tomcat -c $CATALINA_HOME/bin/startup1.sh
;;
esac
exit 0
------------------- // 파일 내용 -------------------------


# chmod 755 /etc/init.d/tomcat1
# chmod 755 /etc/init.d/tomcat2

# update-rc.d tomcat1 defaults
# update-rc.d tomcat2 defaults

# chkconfig --add tomcat1
# chkconfig --add tomcat2

# chkconfig -list | grep -i tomcat
tomcat1                   0:off  1:off  2:on   3:on   4:on   5:on   6:off
tomcat2                   0:off  1:off  2:on   3:on   4:on   5:on   6:off

# /etc/init.d/tomcat1 start
Using CATALINA_BASE:   /home/tomcat/apache-tomcat-7.0.76_1
Using CATALINA_HOME:   /home/tomcat/apache-tomcat-7.0.76_1
Using CATALINA_TMPDIR: /home/tomcat/apache-tomcat-7.0.76_1/temp
Using JRE_HOME:        /usr/local/jdk1.7.0_80/
Using CLASSPATH:       /home/tomcat/apache-tomcat-7.0.76_1/bin/bootstrap.jar:/home/tomcat/apache-tomcat-7.0.76_1/bin/tomcat-juli.jar
Using CATALINA_PID:    /home/tomcat/apache-tomcat-7.0.76_1/bin/tomcat.pid
Tomcat started.

# /etc/init.d/tomcat2 start
Using CATALINA_BASE:   /home/tomcat/apache-tomcat-7.0.76_2
Using CATALINA_HOME:   /home/tomcat/apache-tomcat-7.0.76_2
Using CATALINA_TMPDIR: /home/tomcat/apache-tomcat-7.0.76_2/temp
Using JRE_HOME:        /usr/local/jdk1.7.0_80/
Using CLASSPATH:       /home/tomcat/apache-tomcat-7.0.76_2/bin/bootstrap.jar:/home/tomcat/apache-tomcat-7.0.76_2/bin/tomcat-juli.jar
Using CATALINA_PID:    /home/tomcat/apache-tomcat-7.0.76_2/bin/tomcat.pid
Tomcat started.

# ps -ef | grep -i tomcat
tomcat   899     1  9 14:43 ?        00:00:10 /usr/local/jdk1.7.0_80//bin/java -Djava.util.logging.config.file=/home/tomcat/apache-tomcat-7.0.76_2/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.endorsed.dirs=/home/tomcat/apache-tomcat-7.0.76_2/endorsed -classpath /home/tomcat/apache-tomcat-7.0.76_2/bin/bootstrap.jar:/home/tomcat/apache-tomcat-7.0.76_2/bin/tomcat-juli.jar -Dcatalina.base=/home/tomcat/apache-tomcat-7.0.76_2 -Dcatalina.home=/home/tomcat/apache-tomcat-7.0.76_2 -Djava.io.tmpdir=/home/tomcat/apache-tomcat-7.0.76_2/temp org.apache.catalina.startup.Bootstrap start
tomcat   910     1  8 14:43 ?        00:00:08 /usr/local/jdk1.7.0_80//bin/java -Djava.util.logging.config.file=/home/tomcat/apache-tomcat-7.0.76_1/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.endorsed.dirs=/home/tomcat/apache-tomcat-7.0.76_1/endorsed -classpath /home/tomcat/apache-tomcat-7.0.76_1/bin/bootstrap.jar:/home/tomcat/apache-tomcat-7.0.76_1/bin/tomcat-juli.jar -Dcatalina.base=/home/tomcat/apache-tomcat-7.0.76_1 -Dcatalina.home=/home/tomcat/apache-tomcat-7.0.76_1 -Djava.io.tmpdir=/home/tomcat/apache-tomcat-7.0.76_1/temp org.apache.catalina.startup.Bootstrap start


10) 웹 어플리케이션 배포시...

* 배포하는 WEB Applicaion 의 web.xml 에 <distributable /> 추가 한다.

<%@ page session="true" %>
<%= session.getId() %>

jsp 페이지에 위의 내용을 넣고 세션 아이디를 확인해 본다.


2017년 3월 23일 목요일

[EtC] log4j log level

로그레벨은
TRACE > DEBUG > INFO > WARN > ERROR > FATAL 순 입니다.

# Log Level
# TRACE : 추적 레벨은 Debug보다 좀더 상세한 정보를 나타냄
# DEBUG : 프로그램을 디버깅하기 위한 정보 지정
# INFO :  상태변경과 같은 정보성 메시지를 나타냄
# WARN :  처리 가능한 문제, 향후 시스템 에러의 원인이 될 수 있는 경고성 메시지를 나타냄
# ERROR :  요청을 처리하는 중 문제가 발생한 경우
# FATAL :  아주 심각한 에러가 발생한 상태, 시스템적으로 심각한 문제가 발생해서 어플리케이션 작동이 불가능할 경우


출처: http://mdj1234.tistory.com/63 [짬타이거 화이팅!]

2017년 2월 21일 화요일

[EtC] 저가형 은박담요(응급담요) 사용


인터넷 쇼핑몰에서 개당 450원 주고 10개 구매한 응급용 은박담요 입니다.

펼쳤을 경우 가로 130cm, 세로 210cm 의 크기라고 체크 되어 있습니다.




위의 사진에서 처럼 보시는바와 같이 빛이 약간 투과 되더라고요.






어린 아이 둘이 사용하기에 적당한걸 보니, 어른 한명이 사용할 만한 사이즈라 가늠 됩니다.

추운 겨울날 실내에서 사용해 보니, 그래도 체온 유지가 되긴 하더라고요.

실외에서 발생하는 응급 상황에서는 크게 도움이 될지는 아직 잘 모르겠습니다.


2017년 1월 29일 일요일

[SpRiNg] STS.ini 설정


STS.ini 파일을 열어 붉은 색상 부분을 필요에 따라 넣어 준다.

-startup
../Eclipse/plugins/org.eclipse.equinox.launcher_1.3.201.v20161025-1711.jar
--launcher.library
../Eclipse/plugins/org.eclipse.equinox.launcher.cocoa.macosx.x86_64_1.1.401.v20161122-1740
-product
org.springsource.sts.ide
--launcher.defaultAction
openFile
-vmargs
-Dosgi.requiredJavaVersion=1.8
-Xverify:none
-XX:+UseParallelGC
-XX:+AggressiveOpts
-XX:-UseConcMarkSweepGC
-XX:PermSize=128M
-XX:MaxPermSize=128M
-XX:MaxNewSize=128M
-XX:NewSize=128M
-Xms2048m
-Dosgi.module.lock.timeout=10
-XstartOnFirstThread
-Dorg.eclipse.swt.internal.carbon.smallFonts
-Xdock:icon=../Resources/sts.icns
-Xmx2048m
-javaagent:../Eclipse/lombok.jar







2016년 11월 17일 목요일

[SpRiNg] Scheduler - cron


출처 클릭


@Component("scheduler")
public class SchedulerController{

    @Scheduled(cron="*/10 * * * * *") 
    public void schedulerTest1(){
        System.out.println("10초 마다 실행 되는 스케쥴러 입니다.");
    }


    @Scheduled(cron="*/20 * * * * *") 
    public void schedulerTest2(){
        System.out.println("20초 마다 실행 되는 스케쥴러 입니다.");
    }
}


기존에 작성된 표현 방식이 잘못된 것으로 판단된다. 아래의 링크를 확인해 볼 것.

https://docs.spring.io/autorepo/docs/spring-framework/5.0.x/javadoc-api/org/springframework/scheduling/annotation/Scheduled.html#cron--





스케쥴러 cron 양식

초 0-59 , - * /
분 0-59 , - * /
시 0-23 , - * /
일 1-31 , - * ? / L W
월 1-12 or JAN-DEC , - * /
요일 1-7 or SUN-SAT , - * ? / L #
년(옵션) 1970-2099 , - * /
* : 모든 값
? : 특정 값 없음
- : 범위 지정에 사용
, : 여러 값 지정 구분에 사용
/ : 초기값과 증가치 설정에 사용
L : 지정할 수 있는 범위의 마지막 값 -> 안되는듯(For input string: "L" 에러 발생)
W : 월~금요일 또는 가장 가까운 월/금요일
# : 몇 번째 무슨 요일 2#1 => 첫 번째 월요일

예제) Expression Meaning
초 분 시 일 월 주(년)
"0 0 12 * * ?" : 아무 요일, 매월, 매일 12:00:00
"0 15 10 ? * *" : 모든 요일, 매월, 아무 날이나 10:15:00
"0 15 10 * * ?" : 아무 요일, 매월, 매일 10:15:00
"0 15 10 * * ? *" : 모든 연도, 아무 요일, 매월, 매일 10:15
"0 15 10 * * ? : 2005" 2005년 아무 요일이나 매월, 매일 10:15
"0 * 14 * * ?" : 아무 요일, 매월, 매일, 14시 매분 0초
"0 0/5 14 * * ?" : 아무 요일, 매월, 매일, 14시 매 5분마다 0초
"0 0/5 14,18 * * ?" : 아무 요일, 매월, 매일, 14시, 18시 매 5분마다 0초
"0 0-5 14 * * ?" : 아무 요일, 매월, 매일, 14:00 부터 매 14:05까지 매 분 0초
"0 10,44 14 ? 3 WED" : 3월의 매 주 수요일, 아무 날짜나 14:10:00, 14:44:00
"0 15 10 ? * MON-FRI" : 월~금, 매월, 아무 날이나 10:15:00
"0 15 10 15 * ?" : 아무 요일, 매월 15일 10:15:00
"0 15 10 L * ?" : 아무 요일, 매월 마지막 날 10:15:00
"0 15 10 ? * 6L" : 매월 마지막 금요일 아무 날이나 10:15:00
"0 15 10 ? * 6L 2002-2005" : 2002년부터 2005년까지 매월 마지막 금요일 아무 날이나 10:15:00
"0 15 10 ? * 6#3" : 매월 3번째 금요일 아무 날이나 10:15:00

2016년 11월 8일 화요일

[EtC] CAL69 Type D




사진을 클릭 하시면 크게 보실 수 있습니다.




온라인 쇼핑몰에서 구입한지 5일만에 커다란 상자에 썰렁하게(?) 도착 했습니다.




뒷면에 설명서도 읽어 보고...




앞면은 이렇게 생겼습니다.




꺼내 보았습니다. 단순한 구성 입니다. 외국인이 칼이라는거 모를까봐 영어로 칼 이라고 써 놨네요.




우선 나이프의 앞면 입니다.




뒷면에는 벨트에 고정 할 수 있는 클립이 있습니다. 




펼쳤을때 사진 입니다. 사진을 돌린다는게 깜박 했네요.




엄지 손가락 부분이 나이프를 펼쳤을때 고정 되는 부분 입니다.

안쪽으로 살짝 눌러 주면 나이프를 접을 수 있습니다.

스프링 없이 나이프를 고정 하여 내구성 면에서 좋은 점수를 주고 싶습니다.






약간 두꺼운 종이를 썰어 보았습니다.

종이를 써는 용도는 아니라서 그런지 잘 썰리는 편은 아니었습니다.

그래도 아웃도어에서 간단히 음식을 써는데는 문제 없을 것으로 판단 됩니다.




전체 길이는 위의 사진과 같습니다.




나이프의 날 모양은 사진과 같습니다.



무게감이나 나이프의 모양, 내구성 등 전체적으로 아웃도어용으로 손색이 없습니다.

녹이 잘 안스는 재질이라고 하는데, 그건 좀더 사용해 봐야 알 거 같습니다.

가격도 1만원 중반대로 나쁜편은 아니었습니다.


2016년 11월 3일 목요일

[C++] Hello World

main.cpp 예제
#include 
#include     /* getpid() 를 사용하기 위해 필요 */
#include     /* rand() 사용하기 위해 필요 */
#include 

#include "libs/testClass.h"  /* 사용자 정의 클래스 */

using namespace std;

/* prototype */
void sayHello(string msg);  /* 테스트용 메서드 */
string sayHello2(string msg); /* 테스트용 메서드2 */
int getRandInt(int maxNum);  /* 랜덤한 숫자를 얻어내기 위한 메서드 */

int main() {
 cout << "PID : " << getpid() << " ==> Hello World!!!" << endl; // prints !!!Hello World!!!

 sayHello("홍길동");
 cout << sayHello2("홍길순") << endl;
 cout << "RAND NUM : " << getRandInt(64) << endl;

 cout << "=====================================" << endl;

 testClass tc = testClass();
 cout << tc.iSay("ho~") << endl;
 cout << tc.youSay("hu~~") << endl;

 return 0;
}

/* 테스트용 메서드 */
void sayHello(string msg){
 cout << msg + "님, 안녕하세요?" << endl;
}

/* 테스트용 메서드2 */
string sayHello2(string msg){
 return msg + "님, 안녕하세요?";
}

/* 랜덤한 숫자를 얻어내기 위한 메서드 */
int getRandInt(int maxNum){
 srand(time(NULL));
 return rand() % maxNum +1;
}
testClass.h 예제
#ifndef TESTCLASS_H_
#define TESTCLASS_H_

#include 
using namespace std;

class testClass {
public:
 testClass();    /* 생성자 */
 virtual ~testClass();  /* 소멸자 */

 string iSay(string msg); /* 내가 말하는 메서드 */
 string youSay(string msg); /* 네가 말하기 메서드 */
};

#endif
testClass.cpp 예제
#include "testClass.h"

/* 생성자 */
testClass::testClass() {
 // TODO Auto-generated constructor stub
 cout << "생성자 호출 됨" << endl;
}

/* 소멸자 */
testClass::~testClass() {
 // TODO Auto-generated destructor stub
 cout << "소멸자 호출 됨" << endl;
}

/* 내가 말하는 메서드 */
string testClass::iSay(string msg){
 return "i say " + msg;
}

/* 네가 말하는 메서드 */
string testClass::youSay(string msg){
 return "you say " + msg;
}

2016년 10월 21일 금요일

[JaVa] AES256 암호화 및 복호화


출처 : http://www.imcore.net/encrypt-decrypt-aes256-c-objective-ios-iphone-ipad-php-java-android-perl-javascript-python/


import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;


 
/*
 참고 : http://www.imcore.net/encrypt-decrypt-aes256-c-objective-ios-iphone-ipad-php-java-android-perl-javascript-python/
 
 jce patch 적용 되어있어야 하며, commons-codec-1.10.jar 필요 
*/
 
public class AES256Util {

 public static byte[] ivBytes = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

 
 /**
  * 일반 문자열을 지정된 키를 이용하여 AES256 으로 암호화
  * @param  String - 암호화 대상 문자열
  * @param  String - 문자열 암호화에 사용될 키
  * @return String - key 로 암호화된  문자열 
  * @exception 
  */
 public static String strEncode(String str, String key) throws java.io.UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
  
  byte[] textBytes = str.getBytes("UTF-8");
  AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivBytes);
  SecretKeySpec newKey = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
  Cipher cipher = null;
  cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
  cipher.init(Cipher.ENCRYPT_MODE, newKey, ivSpec);
  return Base64.encodeBase64String(cipher.doFinal(textBytes));
 }

 
 
 /**
  * 암호화된 문자열을 지정된 키를 이용하여 AES256 으로 복호화
  * @param  String - 복호화 대상 문자열
  * @param  String - 문자열 복호화에 사용될 키
  * @return String - key 로 복호화된  문자열 
  * @exception 
  */ 
 public static String strDecode(String str, String key) throws java.io.UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
  
  byte[] textBytes = Base64.decodeBase64(str);
  //byte[] textBytes = str.getBytes("UTF-8");
  AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivBytes);
  SecretKeySpec newKey = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
  Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
  cipher.init(Cipher.DECRYPT_MODE, newKey, ivSpec);
  return new String(cipher.doFinal(textBytes), "UTF-8");
 }
 
}



사용은 아래 처럼...

import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import org.apache.commons.codec.binary.Base64;


public class aes256EncTest {

 public static void main(String[] args) throws UnsupportedEncodingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {


  String key = "12345678901234567890123456789012";    //key는 16~32자리
  
  AES256Util aes256Util = new AES256Util();
  
  /* XML 문자열 암호화 */
  String encStr = aes256Util.strEncode(xmlStr, key);
  System.out.println("encStr =============> " + encStr);
  
  
  /* XML 문자열 복호화 */
  String decStr = aes256Util.strDecode(encStr, key);
  System.out.println("decStr =============> " + decStr);


 }

}

[JaVa] http 통신 예제 코드


출처 : http://whitegom.tistory.com/26


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;


public class httpGetXmlTest {

 public static void main(String[] args) throws Exception {
  // TODO Auto-generated method stub
  
  URL url = new URL("http://192.168.137.130:8080/exam/xml3/admin");

  // open connection
  HttpURLConnection conn = (HttpURLConnection) url.openConnection();
  conn.setDoInput(true);          // 입력스트림 사용
  conn.setDoOutput(true);         // 출력스트림 사용
  conn.setUseCaches(false);       // 캐시사용 안함
  conn.setReadTimeout(30000);     // 타임아웃 : 3초
  conn.setRequestMethod("GET");   // GET or POST ...
        
  StringBuffer sb =  new StringBuffer();

  BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));

  for (;;) {
   String line = br.readLine();
   if (line == null)
    break;
   sb.append(line + "\n");
  }

  br.close();
  conn.disconnect();
        
  String getXml = sb.toString();

  System.out.println(sb.toString());        
 }
}

2016년 7월 12일 화요일

[JaVa] byte[] -> String

byte[] mgs; // 어떤 값이 들어 있다 치고...

try {
     System.out.println(new String(mgs, "UTF-8"));
} catch (UnsupportedEncodingException e) {
     e.printStackTrace();
}