从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
(10 MB),因此请设置更大的大小。调整一下警告消失的最佳设置。请注意,在交通流量较高的情况下,警告可能会再次出现。
1.1原因(简短说明)
此问题是由于由于缓存条目小于那些条目的TTL而导致Tomcat无法达到其目标缓存大小而引起的。因此,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是在Web应用程序中的文件或目录。出于性能原因,Tomcat可以缓存WebSource。默认情况下,静态资源缓存的最大值(所有资源总计)为10240 KB(10 MB)。当请求webResource时(例如,加载静态图像时),会将webResource加载到缓存中,然后将其称为缓存条目。每个缓存条目都有一个TTL(生存时间),TTL是允许缓存条目保留在缓存中的时间。TTL过期后,可以从缓存中删除缓存条目。cacheTTL的默认值为5000毫秒(5秒)。
关于缓存,还有更多要说的,但这与问题无关。
2.2原因
Cache类中的以下代码详细显示了缓存策略:
152 //内容将不会被缓存,但是我们仍然需要元数据大小
153 long delta = cacheEntry。getSize();
154 尺寸。addAndGet(delta);
156 如果(大小。得到()> MAXSIZE){
157个 //处理资源无序速度。交易缓存
158 //效率(年轻的条目可以之前旧的逐出
159级 //的)速度,因为这是在关键路径上
160 //请求处理
161 长的targetSize =
162 maxSize *(100-TARGET_FREE_PERCENT_GET)/ 100;
163 长新尺寸= 逐出(
164 的targetSize,resourceCache。值()。迭代器());
165 if(newSize> maxSize){
166 //无法为此资源创建足够的空间
167 //从缓存中删除它
168 removeCacheEntry(path);
169个 日志。警告(SM。的getString( “cache.addFail”路径));
170 }
171 }
加载webResource时,代码将计算缓存的新大小。如果计算的大小大于默认的最大大小,则必须删除一个或多个缓存条目,否则新大小将超过最大大小。因此,代码将计算“ targetSize”,即缓存要保留的大小(最佳),默认为最大值的95%。为了达到此targetSize,必须从缓存中删除/删除条目。使用以下代码完成此操作:
215 私人 long evct (long targetSize,Iterator < CachedResource > iter){
217 long now =系统。currentTimeMillis();
219 long newSize =大小。得到();
221 而(新尺寸>的targetSize && ITER。hasNext()){
222 CachedResource资源= ITER。next();
224 //不会过期已在TTL内检查什么
225 ,如果(资源。getNextCheck()>现在){
226 继续 ;
227 }
229 //从缓存中删除该条目
230 removeCacheEntry(资源。getWebappPath());
232 newSize =大小。得到();
233 }
235 返回 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问题
因此,如警告消息所示,问题是
收回过期的缓存条目后可用空间不足-请考虑增加缓存的最大大小
如果您的Web应用程序在短时间内(5秒)内加载了许多未缓存的webResources(大约为最大缓存,默认为10mb),那么您将收到警告。
令人困惑的是,Tomcat 7没有显示警告。这仅仅是由Tomcat 7代码引起的:
1606 //添加新条目缓存
1607 同步(缓存){
1608 //检查缓存大小,和删除元素,如果过大
1609 ,如果((缓存。查找(名称)== 空)&&缓存。分配(entry.size) ){
1610 缓存。加载(输入);
1611 }
1612 }
结合:
231 while(toFree> 0){
232 if(attempts == maxAllocateIterations){
233 //放弃,对当前缓存不做任何更改
234 return false ;
235 }
因此,当Tomcat 7无法释放缓存时,它根本不会输出任何警告,而Tomcat 8则会输出警告。
因此,如果您使用的Tomcat 8具有与Tomcat 7相同的默认缓存配置,并且在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”代表增加的高速缓存大小,在千字节指定。默认值为10240(10 MB),因此请设置更大的大小。
您必须调整以获得最佳设置。请注意,当您的流量/资源请求突然增加时,问题可能会再次出现。
为了避免每次要尝试新的缓存大小时都必须重新启动服务器,可以更改它而无需使用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" />
这实际上归结为在不使用ram的情况下拥有并填充了缓存。
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的Beta版中,但我使用的是JMX来禁用缓存。(不确定为什么会这样,但是通过server.xml禁用缓存可能会出现问题。)