Java로 만들어진 데몬 또는 Tomcat와 같이 Java로 구동되는 WAS를 운영환경에서 사용하다보면

사용자수의 증가 등의 부하로 인해 설정된 메모리를 초과하여 Application이 뒤지거나 처리속도가 늦어지는 경우가 있다.

 

자바8에 대한 오라클 문서에 의하면 

https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/ergonomics.html

 

JVM 옵션에 메모리 설정을 별도로 해주지 않고 default로 실행할 경우 

  • Initial heap size of 1/64 of physical memory up to 1 GB
  • Maximum heap size of 1/4 of physical memory up to 1 GB

기본 Heap size는 물리적 메모리의 1/64, 최대 Heap size는 물리적 메모리의 1/4로 설정 된다.

 

아래 명령어로 현재 JVM의 기본 Heap, Perm Size를 확인할 수 있다.

 

[Linux]

(jdk1.7 이하)
java -XX:+PrintFlagsFinal -version 2>&1 | grep -i -E 'heapsize|permsize|version'

 

(jdk1.8 이상)

java -XX:+PrintFlagsFinal -version 2>&1 | grep -i -E 'heapsize|metaspacesize|version'

 
[Windows]

(jdk1.7 이하)
java -XX:+PrintFlagsFinal -version 2>&1 | findstr /I "heapsize permsize version"

 

(jdk1.8 이상)

java -XX:+PrintFlagsFinal -version 2>&1 | findstr /I "heapsize metaspacesize version"

 

$ top

 

$ java -XX:+PrintFlagsFinal -version 2>&1 | grep -i -E 'heapsize|metaspacesize|version'

필자의 경우 메모리는 약 12G이고 1/64인 약 192MB와 InitialHeapSize와 1/4인 약 3G인 MaxHeapSize가 기본값으로 잡혀있는 것을 확인할 수 있다.

 

SpringFramework가 적용된 어플리케이션을 배포하다보면 

org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException 에러를 마주할 때가 있다.

예를 들면 다음과 같은 예외가 발생한다.

 


[ERROR][servlet.FrameworkServlet.initServletBean:457] - Context initialization failed
org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 31 in XML document from ServletContext resource [/WEB-INF/spring/appServlet/servlet-context.xml] is invalid; nested exception is org.xml.sax.SAXParseException; lineNumber: 31; columnNumber: 77; cvc-complex-type.2.4.c: 일치하는 와일드 카드 문자가 엄격하게 적용되지만 'util:properties' 요소에 대한 선언을 찾을 수 없습니다.
        at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:396)
        at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:334)
        at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:302)
        at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:174)
        at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:209)
        at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:180)
        at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:125)
        at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:94)
        at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:131)
        at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:522)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:436)
        at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:631)
        at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:588)
        at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:645)
        at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:508)
        at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:449)
        at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:133)
        at javax.servlet.GenericServlet.init(GenericServlet.java:158)
        at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1284)
        at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1197)
        at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1087)
        at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5266)
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5554)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
        at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
        at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
        at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:652)
        at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1263)
        at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1948)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
        at java.util.concurrent.FutureTask.run(FutureTask.java:262)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:745)
Caused by: org.xml.sax.SAXParseException; lineNumber: 31; columnNumber: 77; cvc-complex-type.2.4.c: 일치하는 와일드 카드 문자가 엄격하게  적용되지만 'util:properties' 요소에 대한 선언을 찾을 수 없습니다.


 

이유는?

대부분은 개발환경은 인터넷이 되는 환경일 것이다.

배포환경이 방화벽이나 망분리로 인해 아웃바운드가 막혀있을 경우 스프링 설정파일에

정의되어 있는 xsd 정의를 불러오지 못해서 발생한다.

 

필자의 에러를 살펴보면

 

[/WEB-INF/spring/appServlet/servlet-context.xml] is invalid; nested exception is org.xml.sax.SAXParseException; lineNumber: 31; columnNumber: 77; cvc-complex-type.2.4.c: 일치하는 와일드 카드 문자가 엄격하게 적용되지만 'util:properties' 요소에 대한 선언을 찾을 수 없습니다.

 

즉, servlet-context.xml 에서 util의 properties 요소를 찾을 수 없어서 발생하였다.

 

해당 파일의 상단을 보면 아래와 같이 정의가 되어 있는데

 

http://www.springframework.org/schema/util/spring-util-3.1.xsd 에 접근을 하지 못했기 때문이다.

 

 

해결방법

모든 xsd는 spring관련 jar에 포함되어 있고, beans에 관련된 파일은 spring-beans-${springframework.version}.jar에 있다.

 

 

그러므로 xsd를 인터넷에서 받아오는 것이 아닌 프로젝트의 jar 안에 있는 파일을 참조하게 하면 된다.

 

http://www.springframework.org/schema/util/spring-util-${springframework.version}.xsd 

=> classpath:org/springframework/beans/factory/xml/spring-util-${springframework.version}.xsd 변경

 

 

 

rc.local

위치 : /etc/rc.d/rc.local

 

이곳에 실행하고자 하는 스크립트 실행을 작성해주면 시스템이 부팅될 때 해당 명령을 수행

 

필자는 서비스에 등록되지 않은 데몬이나 어플리케이션을 시스템 부팅 시 자동으로 실행하기 위한 용도로 사용한다.

 

기본값은 root 권한으로 스크립트 실행

 

사용법

- /home에 실행시키고자 하는 test.sh 스크립트가 있다 가정

$ /home/test.sh

 

특정 계정으로 실행해야 하는 경우

$ su - 계정 -c "실행할 스크립트의 절대경로"

 

  ex) $ su - test -c "/home/test.sh"

    -> test 계정으로 /home 에 존재하는 test.sh 실행

 

간혹 절대경로로 기입했을 경우 인식이 안되는 O/S가 있다. 이 경우 cd 명령어를 이용하여 스크립트 파일이 있는 경로로

이동후 해당 스크립트를 실행하게 작성하면 된다.

 

  ex) $  su - test -c "cd /home; ./test.sh"

 

Centos7 버전부터는 /etc/rc.d/rc.local 파일의 실행권한이 644(-rw-r--r--)로 설정 되어있다.

Please note that you must run 'chmod +x /etc/rc.d/rc.local' to ensure

 

 

즉, 해당 기능을 사용하기 위해서는 실행권한(x)를 추가해줘야 한다.

CentOS6 는 EOS로 인해 yum repository가 사용이 안된다.

따라서 다른 repository로 변경해줘야 한다.

 

경로 : /etc/yum.repos.d/[OS 종류].repo

 

아래로 변경 

 

[base]
name=CentOS-$releasever - Base
# mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os&infra=$infra
# baseurl=http://mirror.centos.org/centos/$releasever/os/$basearch/
baseurl=https://vault.centos.org/6.10/os/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6

# released updates
[updates]
name=CentOS-$releasever - Updates
# mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=updates&infra=$infra
# baseurl=http://mirror.centos.org/centos/$releasever/updates/$basearch/
baseurl=https://vault.centos.org/6.10/updates/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6

# additional packages that may be useful
[extras]
name=CentOS-$releasever - Extras
# mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extras&infra=$infra
# baseurl=http://mirror.centos.org/centos/$releasever/extras/$basearch/
baseurl=https://vault.centos.org/6.10/extras/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6

 

변경 후 yum clean

+ Recent posts