Tomcat 7에서 8로 업그레이드 할 때 동일한 문제가 발생했습니다. 캐시에 대한 로그 경고가 계속해서 많이 발생했습니다.
1. 짧은 답변
다음을 Context
xml 요소에 추가 하십시오 $CATALINA_BASE/conf/context.xml
.
<!-- The default value is 10240 kbytes, even when not added to context.xml.
So increase it high enough, until the problem disappears, for example set it to
a value 5 times as high: 51200. -->
<Resources cacheMaxSize="51200" />
따라서 기본값은 10240
(10mbyte)이므로 이보다 큰 크기를 설정하십시오. 경고가 사라지는 최적의 설정을 위해 조정하십시오. 교통량이 많은 상황에서는 경고가 다시 표시 될 수 있습니다.
1.1 원인 (간단한 설명)
이 문제는 Tomcat이 해당 항목의 TTL보다 작은 캐시 항목으로 인해 대상 캐시 크기에 도달 할 수 없기 때문에 발생합니다. 따라서 Tomcat에는 만료 될 수있는 캐시 항목이 충분하지 않았습니다. 너무 신선했기 때문에 캐시를 충분히 확보 할 수 없어서 경고를 출력했습니다.
Tomcat 7은이 상황에서 경고를 출력하지 않았기 때문에 Tomcat 7에서는 문제가 나타나지 않았습니다. (귀하와 나에게 알리지 않고 잘못된 캐시 설정을 사용하게됩니다.)
이 문제는 캐시의 크기 및 TTL에 비해 상대적으로 짧은 시간에 리소스에 대한 상대적으로 많은 양의 HTTP 요청 (일반적으로 정적)을 수신 할 때 나타납니다. 캐시가 최대 크기 (기본적으로 10MB)에 도달하고 새 캐시 항목이있는 크기의 95 % 이상 (새로 고침은 캐시에서 5 초 미만을 의미 함)에 도달하면 Tomcat이 시도하는 각 webResource에 대해 경고 메시지가 표시됩니다. 캐시에로드합니다.
1.2 선택적 정보
재부팅하지 않고 실행중인 서버에서 cacheMaxSize를 조정해야하는 경우 JMX를 사용하십시오.
가장 빠른 해결 방법은 cache :를 완전히 비활성화하는 <Resources cachingAllowed="false" />
것이지만 이는 차선책이므로 방금 설명한대로 cacheMaxSize를 늘리십시오.
2. 긴 답변
2.1 배경 정보
WebSource는 웹 응용 프로그램에서 파일이나 디렉토리입니다. 성능상의 이유로 Tomcat은 WebSource를 캐시 할 수 있습니다. 정적 리소스 캐시 (전체 리소스) 의 최대 값은 기본적으로 10240KB (10MB)입니다. webResource가 요청되면 (예 : 정적 이미지를로드 할 때) 캐시에 webResource가로드되고이를 캐시 항목이라고합니다. 모든 캐시 항목에는 캐시 항목이 캐시에 머무를 수있는 시간 인 TTL (Time to Live)이 있습니다. TTL이 만료되면 캐시 항목을 캐시에서 제거 할 수 있습니다. cacheTTL의 기본값은 5000 밀리 초 (5 초)입니다.
캐싱에 대해 더 많은 정보가 있지만 이는 문제와 관련이 없습니다.
2.2 원인
Cache 클래스 의 다음 코드 는 캐싱 정책을 자세히 보여줍니다.
152 // 콘텐츠는 캐시되지 않지만 메타 데이터 크기
153 long delta = cacheEntry가 필요합니다. getSize ();
154 사이즈. addAndGet (델타);
156 if (size. get ()> maxSize) {
157 // 속도를 위해 정렬되지 않은 리소스를 처리합니다. 거래 캐시
(158) // 효율 (이하 항목 전에 이전 퇴거 될 수있다
(159 명) 이 대 임계 경로가 이후 속도 //들)
(160) 의 처리 요구 //
161 긴 targetSize가 =
162 이 maxSize * (100 - TARGET_FREE_PERCENT_GET) / 100;
163 long newSize = evict (
164 targetSize, resourceCache. values (). iterator ());
165 if (newSize> maxSize) {
166 //이 리소스를위한 충분한 공간을 만들 수 없습니다.
167 // 캐시에서 제거합니다.
168 removeCacheEntry (path);
169 로그. 경고 (sm. getString ( "cache.addFail", 경로));
170 }
171 }
webResource를로드 할 때 코드는 캐시의 새 크기를 계산합니다. 계산 된 크기가 기본 최대 크기보다 크면 하나 이상의 캐시 된 항목을 제거해야합니다. 그렇지 않으면 새 크기가 최대 크기를 초과합니다. 따라서 코드는 "targetSize"를 계산합니다. 이는 캐시가 (최적 값으로) 유지하려는 크기이며 기본적으로 최대 값의 95 %입니다. 이 targetSize에 도달하려면 항목을 캐시에서 제거 / 제거해야합니다. 이것은 다음 코드를 사용하여 수행됩니다.
215 private long evict ( long targetSize, Iterator < CachedResource > iter) {
217 long now = 시스템. currentTimeMillis ();
219 long newSize = 크기. get ();
221 while (newSize> targetSize && iter. hasNext ()) {
222 CachedResource resource = iter. 다음 ();
224 // TTL 내에서 확인 된 항목을 만료하지 않음
225 if (resource. getNextCheck ()> now) {
226 계속 ;
227 }
229 // 캐시에서 항목 제거
230 removeCacheEntry (resource. getWebappPath ());
232 newSize = 크기. get ();
233 }
235 return newSize;
236 }
따라서 TTL이 만료되고 targetSize에 아직 도달하지 않은 경우 캐시 항목이 제거됩니다.
캐시 항목을 제거하여 캐시를 해제하려고 시도한 후 코드는 다음을 수행합니다.
165 if (newSize> maxSize) {
166 //이 리소스에 대해 충분한 공간을 만들 수 없습니다.
167 // 캐시에서 제거합니다.
168 removeCacheEntry (path);
169 로그. 경고 (sm. getString ( "cache.addFail", 경로));
170 }
따라서 캐시를 해제하려는 시도 후에도 크기가 여전히 최대 값을 초과하면 해제 할 수 없다는 경고 메시지가 표시됩니다.
cache.addFail=Unable to add the resource at [{0}] to the cache for web application [{1}] because there was insufficient free space available after evicting expired cache entries - consider increasing the maximum size of the cache
2.3 문제
따라서 경고 메시지에서 알 수 있듯이 문제는
만료 된 캐시 항목을 제거한 후 사용 가능한 여유 공간이 부족합니다. 캐시의 최대 크기를 늘리는 것이 좋습니다.
웹 애플리케이션이 짧은 시간 (5 초) 내에 캐시되지 않은 많은 webResources (대략 최대 캐시, 기본적으로 10MB)를로드하면 경고가 표시됩니다.
혼란스러운 부분은 Tomcat 7이 경고를 표시하지 않았다는 것입니다. 이것은 단순히 다음 Tomcat 7 코드로 인해 발생합니다.
1606 // 캐시에 새 항목 추가
1607 동기화 됨 (캐시) {
1608 // 캐시 크기를 확인하고 너무 크면 요소 제거
1609 if ((cache. lookup (name) == null ) && cache. allocate (entry.size) ) {
1610 캐시. 로드 (항목);
1611 }
1612 }
다음과 결합 :
231 while (toFree> 0) {
232 if (attempts == maxAllocateIterations) {
233 // 포기, 현재 캐시가 변경되지 않음
234 return false ;
235 }
따라서 Tomcat 7은 캐시를 해제 할 수 없을 때 경고를 전혀 출력하지 않는 반면 Tomcat 8은 경고를 출력합니다.
따라서 Tomcat 7과 동일한 기본 캐싱 구성으로 Tomcat 8을 사용하고 Tomcat 8에서 경고가 표시되면 Tomcat 7의 캐싱 설정이 경고없이 제대로 수행되지 않은 것입니다.
2.4 솔루션
여러 솔루션이 있습니다.
- 캐시 늘리기 (권장)
- TTL 낮추기 (권장하지 않음)
- 캐시 로그 경고 표시 안 함 (권장하지 않음)
- 캐시 비활성화
2.4.1. 캐시 늘리기 (권장)
여기에 설명 된대로 : http://tomcat.apache.org/tomcat-8.0-doc/config/resources.html
<Resources cacheMaxSize="XXXXX" />
의 Context
요소 내에 추가 합니다 $CATALINA_BASE/conf/context.xml
. 여기서 "XXXXX"는 증가 된 캐시 크기를 나타내며 KB 단위로 지정됩니다. 기본값은 10240 (10mbyte)이므로 이보다 큰 크기를 설정하십시오.
최적의 설정을 위해 조정해야합니다. 트래픽 / 리소스 요청이 갑자기 증가하면 문제가 다시 발생할 수 있습니다.
새 캐시 크기를 시도 할 때마다 서버를 다시 시작할 필요가 없도록 JMX를 사용하여 다시 시작하지 않고 변경할 수 있습니다.
하기 위해 JMX를 사용 ,이 추가 $CATALINA_BASE/conf/server.xml
내 Server
요소 :
<Listener className="org.apache.catalina.mbeans.JmxRemoteLifecycleListener" rmiRegistryPortPlatform="6767" rmiServerPortPlatform="6768" />
다운로드 catalina-jmx-remote.jar
에서 https://tomcat.apache.org/download-80.cgi 과에 넣어 $CATALINA_HOME/lib
. 그런 다음 jConsole (기본적으로 Java JDK와 함께 제공됨)을 사용하여 JMX를 통해 서버에 연결하고 설정을 살펴보고 서버가 실행되는 동안 캐시 크기를 늘립니다. 이러한 설정의 변경 사항은 즉시 적용됩니다.
2.4.2. TTL 낮추기 (권장하지 않음)
낮은 cacheTtl
최적의 설정에 대한 낮은 5000 밀리 초보다 뭔가에 의해 값과 조정.
예를 들면 : <Resources cacheTtl="2000" />
이것은 효과적으로 캐시를 사용하지 않고 램에 캐시를 채우는 것으로 귀결됩니다.
2.4.3. 캐시 로그 경고 표시 안 함 (권장하지 않음)
에 대한 로거를 비활성화하도록 로깅을 구성합니다 org.apache.catalina.webresources.Cache
.
Tomcat 로그인에 대한 자세한 정보 : http://tomcat.apache.org/tomcat-8.0-doc/logging.html
2.4.4. 캐시 비활성화
당신은 설정하여 캐시를 비활성화 할 수 있습니다 cachingAllowed
로 false
.
<Resources cachingAllowed="false" />
Tomcat 8의 베타 버전에서는 JMX를 사용하여 캐시를 비활성화 한 것을 기억할 수 있습니다. (정확한 이유는 모르지만 server.xml을 통해 캐시를 비활성화하는 데 문제가있을 수 있습니다.)