본문 바로가기
IT-개발/JAVA

springboot - Embedded Tomcat Cache 조정하기

by 로데안 2024. 5. 28.

prologue
페이지가 자꾸 이상하게 뜨는데 왜 이럴까요?
> 로그를 보니 Tomcat 로그에 cache관련 WARN이 많네요.. (이것 때문일까?)
Tomcat Cache 크기 늘리는 건 금방 하죠?
> 아니 누가 이걸 springboot 내장 톰캣으로 개발한 걸 그대로 올려놨어..(@*$&*#&%)

 

내장 톰캣을 거둬낼까..?

 
 

일반적인 Tomcat에서 Cache 설정하기


일반적인 Tomcat의 환경에서는 어떻게 설정했을까? Tomcat 경로 내 conf/context.xml 파일 내부에

<Resources cachingAllowed="true" cacheMaxSize="102400"/>

 
cachingAllowed true와 cacheMaxSize를 100MB 정도(cacheMaxSize는 KB 단위)만 넣어줘도 충분할 것 같았습니다.
하지만 Embedded에서는 넣을 곳이 어디일까요..?
 

내장된 Tomcat 사용하기

 
SpringBoot에서 Embedded Tomcat을 사용하는 건 아주 간단합니다.
maven 기준으로는 아래처럼 작성하면 되는데요. Tomcat 말고 다른 Application Server를 쓰려고 한다면
exclusions에 걸린 주석을 해제하면 되겠습니다.

<properties>
	....생략
	<servlet-api.version>3.1.0</servlet-api.version>
</properties>
....생략
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <!-- For Excluding the Tomcat dependency, eleminate comment below codes -->
        <!-- <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
            </exclusion>
        </exclusions> -->
    </dependency>
</dependencies>

 
그리고 application.properties 에 server.port 같은 값에 열릴 port만 입력(server.port=0은 랜덤 포트) 해도 Tomcat을 손쉽게 쓸 수 있습니다만..
톰캣의 세부 사항을 모두 application.properties에서 세팅할 수는 없었습니다. 저런 Cache 설정이 모든 application server의 내용은 아닐 수 있겠지요..
 

Embedded Tomcat은  어떻게 수정을..

 
내장된 Tomcat은 properties에서 지정된 설정만으로 세세한 설정은 불가하기 때문에 코드로 구현해 주어야 합니다.
좀 더 파보면 context.xml을 따로 resouce에 파일을 넣고 연결할 수 도 있겠지만,
소스상에서 처리할 수 있도록 수정해보려고 합니다.
 
Spring Docs 상에서는
WebServerFactoryCustomizer<TomcatServletWebServerFactory> 에 대한 구현 하면
cutomize 메서드를 실행하게 되는 걸로 보입니다.
tomcat context를 불러와서 cache부분을 수정해 주면 되겠네요.
 
또한 TomcatServletWebServerFactory에 addContextCustomizers로 추가해 준다면 제대로 작동합니다.(누락 시 추가 안됨)

@Component
public class TomcatEmbeddedConfig implements WebServerFactoryCustomizer<TomcatServletWebServerFactory>{
	
	@Override
	public void customize(TomcatServletWebServerFactory factory) {
        /* 아래 람다식과 동일 코드
        TomcatContextCustomizer tomcatContextCustomizer = new TomcatContextCustomizer() {
			@Override
			public void customize(Context context) {
				StandardRoot standardRoot = new StandardRoot(context);
				standardRoot.setCachingAllowed(true);
				standardRoot.setCacheMaxSize(100*1024*1024);
				context.setResources(standardRoot);
			}
		};*/
    
		TomcatContextCustomizer tomcatContextCustomizer = context -> {
			StandardRoot standardRoot = new StandardRoot(context);
			standardRoot.setCachingAllowed(true);
			standardRoot.setCacheMaxSize(100*1024*1024); //100MB
			context.setResources(standardRoot);
		};
		
		factory.addContextCustomizers(tomcatContextCustomizer); //add해야 적용
	}
}

 
Cache 크기에 대해서 좀 써보자면 context.xml 에서는 cacheMaxSize가 KB 단위라고 해서 100*1024로 하려 했으나
StandardRoot 내부의 Cache 클래스의 maxSize는 10*1024*1024로 입력한 것을 보아 KB단위가 아닌 Byte 단위일 테니
콘텐츠가 많은 앱이다 보니 100MB로 늘리는 코드를 추가하였습니다.
 
(참고사항 : Cache)

//org.apache.catalina.webresources.Cache.class
public class Cache {

    private static final Log log = LogFactory.getLog(Cache.class);
    protected static final StringManager sm = StringManager.getManager(Cache.class);

    private static final long TARGET_FREE_PERCENT_GET = 5;
    private static final long TARGET_FREE_PERCENT_BACKGROUND = 10;

    // objectMaxSize must be < maxSize/20
    private static final int OBJECT_MAX_SIZE_FACTOR = 20;

    private final StandardRoot root;
    private final AtomicLong size = new AtomicLong(0);

    private long ttl = 5000;
    private long maxSize = 10 * 1024 * 1024;
    .... 생략

 
 

Epilogue

 
재밌네..
(역시 페이지가 안나오는 이유는 아니였음)

반응형