Category: JBoss EAP
Java WAS 서버인 JBoss 에 대한 기사들에 대한 묶음.
보호된 글: JBoss EAP 6 Clustering
보호된 글: JBoss EAP 6.x MySQL JNDI 설정
보호된 글: JBOSS EAP 6 Standalone 환경 구성하기
JBoss EAP 6.4 설치
JBoss EAP 6.4 설치
JBoss EAP 6.4 설치에 대해 다룬다. JBoss EAP 6.4 설치는 GUI와 Text 기반 설치 두가지를 지원 한다. 여기서는 Linux 터미널에서 Text 기반 설치에 대해서 다룬다.
사전준비
JBoss EAP 6.4 를 설치하기 위해서는 JDK 1.7 이상 필요하다. JDK 1.6도 지원한다고 되어 있지만 현시점(2016. 06) 에서 1.6은 너무나 구형이라 권장하지 않는다.
설치를 위해서는 설치 파일이 필요한데, zip 파일과 installer 파일 형태로 제공된다. zip 파일은 그냥 압축해제하면 되지만 installer 는 인스톨 과정을 거쳐야 한다. 여기서는 installer를 이용한 설치에 대해서만 다룬다.
설치
설치 레이아웃은 다음과 같다.
- JBOSS_HOME: /opt/EAP-6.4.0
- JAVA_HOME: /opt/jdk1.8.0_40
JBoss EAP 6.4 의 인스톨 파일은 jboss-eap-6.4.0-installer.jar 이다. Text 기반으로 설치를 위해서는 다음과 같이 명령어를 쳐주면 시작된다.
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
~]$ java -version java version "1.8.0_40" Java(TM) SE Runtime Environment (build 1.8.0_40-b26) Java HotSpot(TM) 64-Bit Server VM (build 25.40-b25, mixed mode) ~]$ java -jar jboss-eap-6.4.0-installer.jar -console Select language : 0: eng 1: chn 2: deu 3: fra 4: jpn 5: por 6: spa Please choose [-1] : 0 Copyright (c) 2013 Red Hat, Inc. All rights reserved. Red Hat, JBoss and the JBoss logo are registered trademarks of Red Hat, Inc. All other trademarks are the property of their respective owners. press 1 to continue, 2 to quit, 3 to redisplay. 1 Select the installation path: [/opt/EAP-6.4.0] press 1 to continue, 2 to quit, 3 to redisplay. 1 Select the packs you want to install: 1 [x] [Required] [Red Hat JBoss Enterprise Application Platform] (542.89 KB) 2 [x] [AppClient] (34.24 KB) 3 [x] [Required] [Bin] (10.99 MB) 4 [x] [Required] [Bundles] (1.01 MB) 5 [x] [Docs] (4.75 MB) 6 [x] [Required] [Domain] (125.56 KB) 7 [x] [Required] [Domain Shell Scripts] (17.35 KB) 8 [x] [Required] [Modules] (147.01 MB) 9 [x] [Required] [Standalone] (152.77 KB) 10 [x] [Required] [Standalone Shell Scripts] (14.16 KB) 11 [x] [Required] [Welcome Content] (2.11 MB) 12 [x] [Red Hat JBoss Enterprise Application Platform Natives] (8 KB) 13 [x] [Native RHEL7 x86_64] (76 KB) 14 [x] [Native Utils RHEL7 x86_64] (53.04 KB) 15 [x] [Native Webserver RHEL7 x86_64] (254.97 KB) Total Size Required: 167.11 MB Press 0 to confirm your selections Please select which packs you want to install 0 Pack Selection Done press 1 to continue, 2 to quit, 3 to redisplay. 1 Create an administrative user This user will be added to the host container's management realm for administrative purposes. It can be used to access the management console, the management CLI or other applications secured in this realm. The password must be at least eight characters long, with one alphabetic character, one digit, and one non-alphanumeric character not including &. Admin username: [admin] admin Admin password: [] ********** Confirm admin password: [**********] ********** press 1 to continue, 2 to quit, 3 to redisplay. 1 Quickstarts Red Hat JBoss Enterprise Application Platform comes with a series of quickstart examples designed to help users begin writing applications using the Java EE 6 technologies. Would you like to install quickstarts? 0 [x] No 1 [ ] Yes Input Selection: 0 press 1 to continue, 2 to quit, 3 to redisplay. 1 Socket Bindings Configure the socket bindings for Red Hat JBoss Enterprise Application Platform. Select Port Configuration: 0 [x] Use the default port bindings for standalone and domain modes. 1 [ ] Configure an offset for all default port bindings. 2 [ ] Configure custom port bindings. Input Selection: 0 If this computer is using a pure IPv6 configuration, please check the box below. [ ] Enable pure IPv6 configuration Input 1 to select, 0 to deselect: 0 press 1 to continue, 2 to quit, 3 to redisplay. 1 Server Launch Choose server startup mode: 0 [x] Don't start the server 1 [ ] Standalone Mode 2 [ ] Domain Mode Input Selection: 0 press 1 to continue, 2 to quit, 3 to redisplay. 1 Logging Options Configure the logging levels for Red Hat JBoss Enterprise Application Platform? 0 [x] No 1 [ ] Yes Input Selection: 0 press 1 to continue, 2 to quit, 3 to redisplay. 1 Configure runtime environment There are several additional options for configuring Red Hat JBoss Enterprise Application Platform now that the server has been installed. Each option can be individually chosen, and will be configured in the order displayed upon pressing next. Would you like to do this now? 0 [x] Perform default configuration 1 [ ] Perform advanced configuration Input Selection: 0 press 1 to continue, 2 to quit, 3 to redisplay. 1 [ Starting to unpack ] [ Processing package: Red Hat JBoss Enterprise Application Platform (1/15) ] [ Processing package: AppClient (2/15) ] [ Processing package: Bin (3/15) ] [ Processing package: Bundles (4/15) ] [ Processing package: Docs (5/15) ] [ Processing package: Domain (6/15) ] [ Processing package: Domain Shell Scripts (7/15) ] [ Processing package: Modules (8/15) ] [ Processing package: Standalone (9/15) ] [ Processing package: Standalone Shell Scripts (10/15) ] [ Processing package: Welcome Content (11/15) ] [ Processing package: Red Hat JBoss Enterprise Application Platform Natives (12/15) ] [ Processing package: Native RHEL7 x86_64 (13/15) ] [ Processing package: Native Utils RHEL7 x86_64 (14/15) ] [ Processing package: Native Webserver RHEL7 x86_64 (15/15) ] [ Unpacking finished ] [ Starting processing ] Starting process Logging installation information (1/4) IzPack variable state written to /opt/EAP-6.4.0/installation/InstallationLog.txt Starting process Adding temporary admin user (2/4) Exit code: 0 Command completed successfully. Starting process Adding admin user (3/4) Exit code: 0 Command completed successfully. Starting process Unpacking natives (4/4) Command success: cp -rP /opt/EAP-6.4.0/jboss-eap-6.4/modules /opt/EAP-6.4.0 Command success: cp /opt/EAP-6.4.0/jboss-eap-6.4/SHA256SUM /opt/EAP-6.4.0 Unpacking complete. Create shortcuts in the Start-Menu (y/n) [y]:n Installation has completed successfully. Application installed on /opt/EAP-6.4.0 Would you like to generate an automatic installation script and properties file? (y/n) [n]:n [ Console installation done ] |
설치 중간중간에 관리자가 선택해야할 사항들이 존재한다. 설치할 패키지들 목록과 포트 설정, 서버 설정, 로깅 설정등을 보다 디테일하게 할 수도 있다.
삭제
삭제는 설치한 디렉토리를 삭제하면 되지만 uninstaller 를 제공한다. EAP_HOME 디렉토리에 Uninstaller 디렉토리에 보면 uninstaller.jar 파일을 제공한다. 역시 Text 기반 삭제는 다음과 같이 하면 된다.
1 |
]$ java -jar uninstaller.jar -console |
JBoss 5 MySQL Replication 접속
만일 MySQL 이 Replication 되어 있다고 한다면 Master 는 read/write 를 Slave 는 read Only 만 하도록 접속을 하고 싶을 것이다. MySQL Connector/J 의 최신버전은 이러한 접속을 지원 한다.
다음은 MySQL Replication 접속을 위한 mysql-ds.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 32 33 34 |
<?xml version="1.0" encoding="UTF-8"?> <!-- $Id: mysql-ds.xml 41017 2006-02-07 14:26:14Z acoliver $ --> <!-- Datasource config for MySQL using 3.0.9 available from: http://www.mysql.com/downloads/api-jdbc-stable.html --> <datasources> <!-- mysql DS --> <local-tx-datasource> <jndi-name>MySQLDS</jndi-name> <connection-url>jdbc:mysql:replication://address=(protocol=tcp)(host=192.168.96.31)(port=3306)(type=master),address=(protocol=tcp)(host=192.168.96.30)(port=3306)(type=slave)/spring?useUnicode=true&characterEncoding=UTF-8&autoReconnect=false&useSSL=false&failOverReadOnly=true&loadBalanceStrategy=random&readFormMasterNoSlaves=true</connection-url> <driver-class>com.mysql.jdbc.ReplicationDriver</driver-class> <user-name>spring</user-name> <password>12345</password> <min-pool-size>5</min-pool-size> <max-pool-size>50</max-pool-size> <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name> <!-- should only be used on drivers after 3.22.1 with "ping" support --> <!-- <valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLValidConnectionChecker</valid-connection-checker-class-name> --> <!-- sql to call when connection is created <new-connection-sql>some arbitrary sql</new-connection-sql> --> <!-- sql to call on an existing pooled connection when it is obtained from pool - MySQLValidConnectionChecker is preferred for newer drivers <check-valid-connection-sql>some arbitrary sql</check-valid-connection-sql> --> <!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml (optional) --> <metadata> <type-mapping>mySQL</type-mapping> </metadata> </local-tx-datasource> </datasources> |
‘connection-url’, ‘driver-class’ 을 유심히 봐야 한다.
mysql-ds 에서의 설정은 MySQL 의 접속을 이중으로 하도록만하고 실제 쿼리를 분기하기 위해서는 DAO 에서 @Transactional(readOnly=true) 를 주어야 한다. 이 어노테이션은 읽기만을 하다는 것을 알려주고 이는 MySQL Slave 에 접속하게 된다.
각 메소드마다 어노테이션을 주기 싫다면 AOP 를 이용하는 방법도 있다.
1 2 3 4 5 6 7 8 9 10 11 12 |
<!-- required to connect Slave Server only for get* method on MySQL Replication --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="*" propagation="REQUIRED"/> <tx:method name="get*" read-only="true"/> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut expression="execution (* com.sbhyun.service.*.*(..))" id="services"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="services"/> </aop:config> |
service 클래스에 get* 메소드들에는 자동으로 read-only=true 가 설정된다. 이렇게 되면 쿼리를 보낼때마다 Slave 서버에 보내게 되어 쿼리연산이 분산된다.
JBoss EAP 5 MySQL JNDI 설정
JNDI 는 자바 애플리케이션 서버라면 거의 다 지원하는 기능이다. 이는 특정한 자원의 접근을 디렉토리 접근하듯이 하도록 해준다. 여기서 자원이라면 대부분 외부 서버에 있는 저장소들을 말한다.
MySQL, PostgreSQL, Oracle, MS SQL 등 외부 저장소에 접속할때마다 저수준의 드라이버를 올리고 인증을 넣는게 아니라 자바 애플리케이션이 구동되면서 접속하을 해놓고 이것을 디렉토리화해서 올려놓으면 자바 애플리케이션에서는 이 디렉토리에 접근하는 것만으로 외부자원에 접속이 끝이 나게 되어 간편해진다.
이 글은 JBoss EAP 5 MySQL JNDI 설정에 관한 글이다.
MySQL Connector/j
MySQL에서는 자바 애플리케이션을 위해서 접속 드라이버를 제공한다. jar 파일로 작성되 배포되고 있어 다운받아서 지정된 위치에 넣기만 하면 된다.
JBoss EAP 5 는 글로벌 library 디렉토리, Node Library 디렉토리가 존재하는데 node 디렉토리에 다운받아 넣는다. 다시말하면, Jboss EAP 5 의 경우에, jboss-as/server 아래에보면 all, default, production, standard 등의 디렉토리가 보이는데 이걸 node 라고 한다. 여기서 나는 all node 에 lib 디렉토리에 MySQL Connector/J 를 넣어주면 된다.
현 시점에서의 버전은 5.1.39 이다.
1 |
]# mv mysql-connector-java-5.1.39-bin.jar $JBOSS_HOME/server/all/lib/ |
MySQL DataSource
이제 JBoss 에 MySQL DataSource 를 설정해준다. 앞에서 잠깐 말했지만 특정 node 에 설정을 해주게되는데 나는 all 노드에 설정을 할 것이다.
일단 mysql-ds.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 32 |
<?xml version="1.0" encoding="UTF-8"?> <!-- $Id: mysql-ds.xml 41017 2006-02-07 14:26:14Z acoliver $ --> <!-- Datasource config for MySQL using 3.0.9 available from: http://www.mysql.com/downloads/api-jdbc-stable.html --> <datasources> <!-- mysql DS --> <local-tx-datasource> <jndi-name>MySQLDS</jndi-name> <connection-url>jdbc:mysql://192.168.96.25:3306/mysql?useUnicode=true&characterEncoding=UTF-8</connection-url> <driver-class>com.mysql.jdbc.Driver</driver-class> <user-name>root</user-name> <password>12345</password> <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name> <!-- should only be used on drivers after 3.22.1 with "ping" support --> <valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLValidConnectionChecker</valid-connection-checker-class-name> <!-- sql to call when connection is created <new-connection-sql>some arbitrary sql</new-connection-sql> --> <!-- sql to call on an existing pooled connection when it is obtained from pool - MySQLValidConnectionChecker is preferred for newer drivers <check-valid-connection-sql>some arbitrary sql</check-valid-connection-sql> --> <!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml (optional) --> <metadata> <type-mapping>mySQL</type-mapping> </metadata> </local-tx-datasource> </datasources> |
- 11번째 줄이 아주 중요하다. JNDI 이름인데, 이 이름을 가지고 자원을 호출하게 된다.
- 12번째 줄은 접속 서버 정보이다. 호스트네임이나 IP주소, 접속 데이터베이스명을 적어주면 된다. Unicode 와 CharacterEncoding 은 옵션으로 MySQL 서버와 맞게 설정해 주어야 한다.
- 14번, 15번 줄은 접속을 위한 인증정보를 적어준다.
이걸 mysql-ds.xml 로 저장한 후에 $JBOSS_HOME/server/all/deploy/ 디렉토리에 넣으면 된다.
애플리케이션 WEB-INF/jboss-web.xml 작성
자바 애플리케이션을 작성할때에 WEB-INF 디렉토리를 만나게 된다. Deployment Descriptor 로 정의되는 web.xml 파일이 위치하는 디렉토리다. 여기에 jboss-web.xml 파일을 다음과 같이 작성한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<!DOCTYPE jboss-web PUBLIC "-//JBoss//DTD Web Application 5.0//EN" "http://www.jboss.org/j2ee/dtd/jboss-web_5_0.dtd"> <jboss-web> <!-- Uncomment the security-domain to enable security. You will need to edit the htmladaptor login configuration to setup the login modules used to authentication users. <security-domain>java:/jaas/jmx-console</security-domain> --> <resource-ref> <res-ref-name>jdbc/MySQLDS</res-ref-name> <jndi-name>java:/MySQLDS</jndi-name> </resource-ref> </jboss-web> |
- 12,13 줄이 아주 중요하다. JNDI 명을 적어주는데, 앞에 mysql-ds.xml 파일에서 설정한 이름만 적어주는게 아니라 jdbc, java: 등을 함께 적어준다. 이거 의외로 안 적어주고 안된다는 사람이 많으니 주의해서 적어주자.
애플리케이션 WEB-INF/web.xml 작성
Deployment Descriptor 파일로 불리우는 web.xml 파일에 다음과 같은 내용을 추가해준다.
1 2 3 4 5 6 7 8 9 10 |
<web-app> .... <resource-ref> <description>MySQL DataSource</description> <res-ref-name>jdbc/MySQLDS</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref> .... </web-app> |
- 5줄 에 JNDI 이름을 적어준다. jdbc/ 를 꼭 붙여준다.
여기까지가 JNDI 설정에 관한 것이다. 이 이상은 프로그래머가 사용하는 ORM 에 따라서 JNDI 호출 방법이 달라진다. 하지만 JBOSS 에서 JNDI가 잘 설정되어 있는지를 살펴볼 수있다.
root Context 설정
이제 애플리케이션에서 JNDI를 설정해 보면 다음과 같다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<!-- Root Context: defines shared resources visible to all other web components --> <tx:annotation-driven /> <!-- enable autowire --> <context:annotation-config/> <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="java:comp/env/jdbc/MySQLDS" /> <property name="resourceRef" value="true" /> </bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> |
jndiName 설정을 어떻게 하는지 주의깊게 봐야 한다.
확인하기
설정한 JNDI가 잘 설정되었는지는 맨 처음 JBoss 를 시작할때에 로그에 나온다.
1 2 3 4 5 6 7 |
00:06:33,959 INFO [ConnectionFactory] Connector bisocket://localhost:4457 has leasing enabled, lease period 10000 milliseconds 00:06:33,959 INFO [ConnectionFactory] org.jboss.jms.server.connectionfactory.ConnectionFactory@75e011d9 started 00:06:34,044 INFO [ConnectionFactoryBindingService] Bound ConnectionManager 'jboss.jca:service=ConnectionFactoryBinding,name=JmsXA' to JNDI name 'java:JmsXA' 00:06:34,066 INFO [ConnectionFactoryBindingService] Bound ConnectionManager 'jboss.jca:service=DataSourceBinding,name=MySQLDS' to JNDI name 'java:MySQLDS' 00:06:34,319 INFO [TomcatDeployment] deploy, ctxPath=/admin-console 00:06:34,427 INFO [config] Initializing Mojarra (1.2_13-b01-FCS) for context '/admin-console' 00:06:36,364 INFO [TomcatDeployment] deploy, ctxPath=/ |
이것은 JNDI 설정 파일을 읽었을 뿐 실제로 접속이 잘되는지를 나오지 않는다. 이는 JBoss Admin Console 를 통해서 가능하다.
위 그림과 같이 Test Connection 을 클릭하면 접속 테스트를 해준다.
위 그림을 보면 Status 가 성공으로 나와서 접속 성공한으로 착각하는데, 이것은 Test Connection 명령이 성공했다는 것이고 그에 대한 결과는 그 아래에 위와같이 나온다. 위 경우에 접속 실패.
이것저것 문제를 해결한 후에 다시 Test Connection 을 하고 성공하면 설정이 정상적으로 된것이다.
Ubuntu 14.04 의 JBoss EAP 5.2 init 스크립트
JBoss EAP 5.2 를 Ubuntu 14.04 에서 운영할 경우에 서비스 시작을 init 에 등록하기 위한 스크립트. Wildfly 에 내용을 가지고 와서 마이그레이션 했다.
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 |
#!/bin/bash # # /etc/init.d/jboss-SvrAPI01 -- startup script for jboss of SvrAPI01 # # NAME="systemV" DEFAULT="/opt/jboss/domains/${NAME}/jboss-env.sh" DESC="Jboss EAP 5.2 Application Server for $NAME" # clear work and tmp dirs? CLEAR_WORK_TMP="Y" HOST_NAME=`/sbin/ifconfig ens3|grep 'inet addr:'|awk '{print $2}'|awk -F : '{print $2}'` # Check privilege if [ `id -u` -ne 0 ]; then echo "You need root privileges to run this script" exit 1 fi # Make sure wildfly is started with system locale if [ -r /etc/default/locale ]; then . /etc/default/locale export LANG fi . /lib/lsb/init-functions if [ -r /etc/default/rcS ]; then . /etc/default/rcS fi # Overwrite settings from default file if [ -f "$DEFAULT" ]; then . "$DEFAULT" fi # Setup the JVM if [ -z "$JAVA" ]; then if [ -n "$JAVA_HOME" ]; then JAVA="$JAVA_HOME/bin/java" else JAVA="java" fi fi # Check if wildfly is installed if [ ! -f "$JBOSS_HOME/bin/run.jar" ]; then log_failure_msg "$NAME is not installed in \"$JBOSS_HOME\"" exit 1 fi # Run as wildfly user # Example of user creation for Debian based: # adduser --system --group --no-create-home --home $JBOSS_HOME --disabled-login wildfly if [ -z "$JBOSS_USER" ]; then JBOSS_USER=sbhyun fi # Check wildfly user id $JBOSS_USER > /dev/null 2>&1 if [ $? -ne 0 -o -z "$JBOSS_USER" ]; then log_failure_msg "User \"$JBOSS_USER\" does not exist..." exit 1 fi # Check owner of JBOSS_HOME if [ ! $(stat -L -c "%U" "$JBOSS_HOME") = $JBOSS_USER ]; then log_failure_msg "The user \"$JBOSS_USER\" is not owner of \"$JBOSS_HOME\"" exit 1 fi # The amount of time to wait for startup if [ -z "$STARTUP_WAIT" ]; then STARTUP_WAIT=120 fi # The amount of time to wait for shutdown if [ -z "$SHUTDOWN_WAIT" ]; then SHUTDOWN_WAIT=120 fi # Location to keep the console log if [ -z "$JBOSS_CONSOLE_LOG" ]; then JBOSS_CONSOLE_LOG="$SERVER_HOME/$SERVER_NAME/log/console.log" fi export JBOSS_CONSOLE_LOG touch $JBOSS_CONSOLE_LOG chown $JBOSS_USER $JBOSS_CONSOLE_LOG # Location to set the pid file JBOSS_PIDFILE="$SERVER_HOME/$SERVER_NAME/run/$SERVER_NAME.pid" export JBOSS_PIDFILE # Launch Jboss in background LAUNCH_JBOSS_IN_BACKGROUND=1 export LAUNCH_JBOSS_IN_BACKGROUND function cleanWorkTmp() { # clean tmp and work dirs echo "clean work and tmp dirs from ${SERVER_NAME}..." rm -Rf "${SERVER_HOME}/${SERVER_NAME}/work" rm -Rf "${SERVER_HOME}/${SERVER_NAME}/tmp" } function jbossPID() { # try get the JVM PID local jbossPID="x" jbossPID=$(ps -eo pid,cmd | grep "org.jboss.Main" | grep "${DOMAIN_IP}" | grep "${SERVER_NAME}" | grep -v grep | cut -c1-6) echo "$jbossPID" } # Helper function to check status of Jboss service check_status() { pidofproc -p "$JBOSS_PIDFILE" "$JAVA" >/dev/null 2>&1 } START_SCRIPT="$JBOSS_HOME/bin/run.sh" SHUTDOWN_SCRIPT="$JAVA -classpath $JBOSS_HOME/bin/shutdown.jar:$JBOSS_HOME/client/jnet.jar org.jboss.Shutdown --shutdown -s jnp://$DOMAIN_IP:$JNP_PORT -u $JBOSS_ADMIN_USER -p $JBOSS_ADMIN_PWD" case "$1" in start) log_daemon_msg "Starting $DESC" log_daemon_msg "instance $SERVER_NAME at $DOMAIN_IP ..." check_status status_start=$? if [ $status_start -eq 3 ]; then mkdir -p $(dirname "$JBOSS_PIDFILE") mkdir -p $(dirname "$JBOSS_CONSOLE_LOG") cat /dev/null > "$JBOSS_CONSOLE_LOG" su -l $JBOSS_USER -c "source $DEFAULT; $START_SCRIPT $JBOSS_OPTS --host $HOST_NAME -c $SERVER_NAME -b $DOMAIN_IP > ${JBOSS_CONSOLE_LOG} 2>&1 &" count=0 launched=0 until [ $count -gt $STARTUP_WAIT ] do grep 'Started in' "$JBOSS_CONSOLE_LOG" > /dev/null if [ $? -eq 0 ] ; then launched=1 break fi sleep 1 count=$((count + 1)); done if [ $launched -eq 1 ] ; then echo `jbossPID` > $JBOSS_PIDFILE chown $JBOSS_USER $(dirname "$JBOSS_PIDFILE") || true fi if check_status; then log_end_msg 0 else log_end_msg 1 fi if [ $launched -eq 0 ]; then log_warning_msg "$DESC hasn't started within the timeout allowed" log_warning_msg "please review file \"$JBOSS_CONSOLE_LOG\" to see the status of the service" fi elif [ $status_start -eq 1 ]; then log_failure_msg "$DESC is not running but the pid file exists" exit 1 elif [ $status_start -eq 0 ]; then log_success_msg "$DESC (already running)" fi ;; stop) check_status status_stop=$? if [ $status_stop -eq 0 ]; then read kpid < "$JBOSS_PIDFILE" log_daemon_msg "Stopping $DESC" su -l $JBOSS_USER -c "source $DEFAULT; $SHUTDOWN_SCRIPT" count=0 until [ $count -gt $SHUTDOWN_WAIT ] do if ! check_status; then break fi sleep 1 count=$((count + 1)); done if check_status; then kill -9 $kpid fi if [ "$CLEAR_WORK_TMP" = "Y" ]; then cleanWorkTmp fi rm "$JBOSS_PIDFILE" log_end_msg 0 elif [ $status_stop -eq 1 ]; then log_action_msg "$DESC is not running but the pid file exists, cleaning up" rm -f $JBOSS_PIDFILE elif [ $status_stop -eq 3 ]; then log_action_msg "$DESC is not running" fi ;; restart) check_status status_restart=$? if [ $status_restart -eq 0 ]; then $0 stop fi $0 start ;; status) check_status status=$? if [ $status -eq 0 ]; then read pid < $JBOSS_PIDFILE log_action_msg "$DESC is running with pid $pid" exit 0 elif [ $status -eq 1 ]; then log_action_msg "$DESC is not running and the pid file exists" exit 1 elif [ $status -eq 3 ]; then log_action_msg "$DESC is not running" exit 3 else log_action_msg "Unable to determine $NAME status" exit 4 fi ;; *) log_action_msg "Usage: $0 {start|stop|restart|reload|force-reload|status}" exit 2 ;; esac exit 0 |
아래는 jboss-env.sh 의 내용.
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
#!/bin/sh # jboss-env.sh - starts a new shell with instance variables set ## set jboss base env export JBOSS_HOME="/opt/jboss/jboss-as" export SERVER_HOME="/opt/jboss/domains" export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/opt/jboss/lib" export JBOSS_USER=sbhyun export SERVER_NAME=systemV export DOMAIN_IP=0.0.0.0 export JNP_PORT=1199 export JAVA_HOME=/opt/java export CLASSPATH=.:/opt/java/jre/lib export PATH=$JAVA_HOME/bin:$JBOSS_HOME/bin:$PATH # JMX Credentials JMX_CREDETIALS_FILE="$SERVER_HOME/$SERVER_NAME/conf/props/jmx-console-users.properties" JMX_USER=$(cat $JMX_CREDETIALS_FILE | grep -v '#' | cut -d '=' -f 1 | head -n 1) JMX_PWD="$(cat $JMX_CREDETIALS_FILE | grep -v '#' | cut -d '=' -f 2 | head -n 1 | tr -d '\r')" JBOSS_ADMIN_USER=${JMX_USER:-"admin"} JBOSS_ADMIN_PWD=${JMX_PWD:-"admin"} if [ "x$JBOSS_OPTS" = "x" ]; then JBOSS_OPTS="-Dserver=$SERVER_NAME" JBOSS_OPTS="$JBOSS_OPTS -Djboss.server.base.dir=$SERVER_HOME" JBOSS_OPTS="$JBOSS_OPTS -Djboss.server.base.url=file://$SERVER_HOME" JBOSS_OPTS="$JBOSS_OPTS -Djboss.server.log.dir=$SERVER_HOME/$SERVER_NAME/log" #JBOSS_OPTS="$JBOSS_OPTS -Djboss.server.log.threshold=DEBUG" JBOSS_OPTS="$JBOSS_OPTS -Djboss.messaging.ServerPeerID=2" JBOSS_OPTS="$JBOSS_OPTS -Djboss.service.binding.set=ports-01" JBOSS_OPTS="$JBOSS_OPTS -Djboss.partition.name=systemV" JBOSS_OPTS="$JBOSS_OPTS -Djboss.default.jgroups.stack=tcp" JBOSS_OPTS="$JBOSS_OPTS -Djboss.jgroups.tcp.tcpping.initial_hosts=192.168.96.30[7700],192.168.96.31[7701]" JBOSS_OPTS="$JBOSS_OPTS -Djboss.jgroups.tcp.tcp_port=7600" JBOSS_OPTS="$JBOSS_OPTS -Djboss.jgroups.bind.address=192.168.96.30" #JBOSS_OPTS="$JBOSS_OPTS -Djgroups.bind_addr=228.2.2.2" #JBOSS_OPTS="$JBOSS_OPTS -Djboss.jgroups.tcp.tcp_port=7600" #JBOSS_OPTS="$JBOSS_OPTS -Djboss.partition.udpGroup=228.2.2.2" #JBOSS_OPTS="$JBOSS_OPTS -Djboss.hapartition.mcast_port=44552" fi if [ "x$JAVA_OPTS" = "x" ]; then JAVA_OPTS="-server" JAVA_OPTS="$JAVA_OPTS -noverify" JAVA_OPTS="$JAVA_OPTS -Xms512m" JAVA_OPTS="$JAVA_OPTS -Xmx512m" JAVA_OPTS="$JAVA_OPTS -XX:PermSize=128m" JAVA_OPTS="$JAVA_OPTS -XX:MaxPermSize=128m" #JAVA_OPTS="$JAVA_OPTS -Xss128k" JAVA_OPTS="$JAVA_OPTS -verbose:gc" JAVA_OPTS="$JAVA_OPTS -Xloggc:$SERVER_HOME/$SERVER_NAME/gclog/gc.log" JAVA_OPTS="$JAVA_OPTS -XX:+PrintGCDetails" JAVA_OPTS="$JAVA_OPTS -XX:+PrintGCTimeStamps" JAVA_OPTS="$JAVA_OPTS -XX:+PrintHeapAtGC" JAVA_OPTS="$JAVA_OPTS -XX:+HeapDumpOnOutOfMemoryError" JAVA_OPTS="$JAVA_OPTS -XX:HeapDumpPath=$SERVER_HOME/$SERVER_NAME/gclog/java_pid.hprof" # JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote" # JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.port=8286" # JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.ssl=false" # JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.authenticate=false" JAVA_OPTS="$JAVA_OPTS -Djava.net.preferIPv4Stack=true" JAVA_OPTS="$JAVA_OPTS -Dsun.rmi.dgc.client.gcInterval=3600000" JAVA_OPTS="$JAVA_OPTS -Dsun.rmi.dgc.server.gcInterval=3600000" JAVA_OPTS="$JAVA_OPTS -Dsun.lang.ClassLoader.allowArraySyntax=true " fi export JBOSS_OPTS JAVA_OPTS |
TCP 기반 JBoss 5 Clustering 하기
AWS EC2 에서 JBoss EAP 5.2 를 설치하고 운영할때에 보통 클러스터링을 설정하게 된다. 문제는 JBoss EAP 5.2 에서 클러스터링은 JGroup 을 기반으로 작성되어 있다. 중요한 것은 클러스터링을 할때에 Multicast UDP 를 사용한다는 것인데, AWS EC2 에서는 Multicast 자체를 지원하지 않는다. 따라서 JBoss EAP 5.2 를 AWS EC2 에서 운영하면서 클러스터링을 기본 설정값으로 설정하고 실행시키면 클러스터링이 되지 않는다.
이럴때 TCP 를 이용하면 가능해진다. 이 포스트는 AWS EC2 에서 TCP 기반 JBoss Clustering 에 관련된 내용이다.
MPING을 TCPPING으로 바꾸기
Cluster 의 프로토콜 설정은 다음의 파일에 정의되어 있다.
- deploy/cluster/jgroups-channelfactory.sar/META-INF/jgroups-channelfactory-stacks.xml
여기에 TCP 스택 부분에 보면 MPING 설정부분을 코멘트처리하고 TCPPING부분을 언코멘트해준다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<stack name="tcp" description="TCP based stack, with flow control and message bundling. TCP stacks are usually used when IP multicasting cannot be used in a network, e.g. because it is disabled (e.g. routers discard multicast)"> <config> <!-- Alternative 1: multicast-based automatic discovery. --> <!--<MPING timeout="3000" num_initial_members="3" mcast_addr="${jboss.jgroups.tcp.mping_mcast_addr:230.11.11.11}" mcast_port="${jgroups.tcp.mping_mcast_port:45700}" ip_ttl="${jgroups.udp.ip_ttl:2}"/> --> <!-- Alternative 2: non multicast-based replacement for MPING. Requires a static configuration of *all* possible cluster members. --> <TCPPING timeout="3000" initial_hosts="${jboss.jgroups.tcp.tcpping.initial_hosts:localhost[7600],localhost[7601]}" port_range="1" num_initial_members="3"/> |
여기서 핵심이 jboss.jgroups.tcp.tcpping.initial_hosts:localhost[7600],localhost[7600] 부분이다. 이부분은 도메인을 입력해줘야 하는데, 대부분 /etc/hosts 파일에 아이피와 짧은 도메인명으로 정의를 해준다.
이렇게 주석을 해제해준 상태에서 JBOSS 옵션으로 -Djboss.jgroups.tcp.tcpping.initial_hosts=node1[7600],node2[7600] 을 주게 되면 두개의 node 가 TCPPING 으로 묶이게 된다.
Cache 매니저에서 jgroup 스택 프로토콜 바꾸기
이것은 다음의 파일에 정의 되어 있다.
- deploy/cluster/jboss-cache-manager.sar/META-INF/jboss-cache-manager-jboss-beans.xml
이 파일에서 jboss.default.jgroups.stack:udp 를 jboss.default.jgroups.stack:tcp 로 모두 교체해준다.
하지만 이 방법외에도 JBOSS 옵션으로 -Djboss.default.jgroups.stack=tcp 를 정의해주고 인스턴스를 시작해주면 적용된다.
JBoss Messaging 을 TCP 로 바꾸기
JBoss Messaging 을 TCP 로 바꾸기 위해서 다음 파일을 열어서 다음과 같이 변경해 준다.
1 2 3 4 |
- <attribute name="ControlChannelName">jbm-control</attribute> - <attribute name="DataChannelName">jbm-data</attribute> + <attribute name="ControlChannelName">tcp</attribute> + <attribute name="DataChannelName">tcp</attribute> |
이 옵션 변경은 커맨드라인으로 제공하지 않기 때문에 반드시 수동으로 이 파일을 편집해 줘야 한다.
JBOSS 시작 옵션으로 설정하기
위 파일들을 바꾸는 대신에 다음과 같이 시작과 같은 옵션만으로 TCPPING 으로 바꿀 수 있다.
1 2 3 4 5 6 7 |
JBOSS_OPTS="$JBOSS_OPTS -Djboss.messaging.ServerPeerID=2" JBOSS_OPTS="$JBOSS_OPTS -Djboss.service.binding.set=ports-01" JBOSS_OPTS="$JBOSS_OPTS -Djboss.partition.name=systemV" JBOSS_OPTS="$JBOSS_OPTS -Djboss.default.jgroups.stack=tcp" JBOSS_OPTS="$JBOSS_OPTS -Djboss.jgroups.tcp.tcpping.initial_hosts=192.168.96.30[7700],192.168.96.31[7701]" JBOSS_OPTS="$JBOSS_OPTS -Djboss.jgroups.tcp.tcp_port=7600" JBOSS_OPTS="$JBOSS_OPTS -Djboss.jgroups.bind.address=192.168.96.30" |
이 옵션 설정은 매우 중요하다.
먼저, jboss.messaging.ServerPeerID 는 반드시 Cluster 내에서 유일해야 한다. 중복되면 서버 시작시에 오류갈 발생된다.
jboss.service.binding.set 은 default 포트를 기준으로 상대적으로 포트를 할당한다. default 는 각종 서비스 포트에 기본 값으로 Cluster 의 경우에는 7600 포트, HTTP 는 8080 이다. ports-01 은 default 보다 100 을 더해서 Cluster 는 7700, HTTP 는 8180 이된다.
위 jboss.service.binding.set 은 jboss.jgroups.tcp.tcp_port 와 혼동이 될 수 있다. 예를들어 ports-01 인상태에서 tcp_port=7600 으로 했다면 100을 더해서 7700 이 된다. 하지만 ports-01 인 상태에서 tcp_port=7700 이면 실제 Cluster TCP 포트는 100을 더한 7800 이 된다. 결론적으로 tcp_port 의 실제 값은 지정한 값에 binding.set 값을 더한 값으로 된다.
jboss.jgroups.tcp.tcpping.initial_hosts 는 binding.set 과 tcp_port 값을 더한 포트 값을 적어주면 된다. 왜냐하면 이게 실제로 사용되어지는 포트가 되니까 결국에는 이곳의 포트값은 실제로 서버에서 사용되어지는 Cluster Port 값을 적으면 된다.
주의사항
이 설정을 테스트 하기위해서는 서로 다른 머신이 있어야 한다. 같은 서버상에 인스턴스를 두개를 실행시켜서하면 안된다. 반드시 서로 다른 서버에 인스턴스와 테스트를 해야지 성공한다. 이유는 아직 나도 잘 모르겠다.