Tomcat 8投掷 – org.apache.catalina.webresources.Cache.getResource无法添加资源

我刚将Tomcat从版本7.0.52升级到8.0.14。

我得到了很多静态图像文件:

org.apache.catalina.webresources.Cache.getResource无法将[/base/1325/WA6144-150×112.jpg]上的资源添加到高速caching,因为在清除过期的高速caching条目后可用空间不足 – 请考虑增加最大大小的caching

我没有指定任何特定的资源设置,我没有得到这个7.0.52。

我发现在启动时发现了一个据说已经修复的bug报告。 对我而言,这不是在启动时发生,而是在请求资源时不断发生。

其他人有这个问题?

试图至less只是禁用caching,但我找不到如何指定不使用caching的示例。 这些属性已经从Tomcat版本8中的上下文中去除了。尝试添加一个资源但是无法获得configuration权限。

<Resource name="file" cachingAllowed="false" className="org.apache.catalina.webresources.FileResourceSet" /> 

谢谢。

$CATALINA_BASE/conf/context.xml添加下面的</Context>

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

有关更多信息: http : //tomcat.apache.org/tomcat-8.0-doc/config/resources.html

从Tomcat 7升级到8时,我遇到了同样的问题:关于caching的连续的大量日志警告。

TL; DR(太长;没有阅读)

最好的解决scheme是通过添加来增加caching

 <Resources cacheMaxSize="XXXXX" /> 

$CATALINA_BASE/conf/context.xmlContext元素中,其中“XXXXX”表示增加的高速caching大小,以千字节为单位。 默认是10240(10 MB),所以设置一个比这更高的尺寸。 不要调整警告消失的最佳设置。 请注意,在高stream量的情况下,警告可能会回来。

如果您需要调整正在运行的服务器而不重新启动,请使用JMX。

最快的解决方法是完全禁用caching: <Resources cachingAllowed="false" /> ,但这不是最理想的,所以请按照我刚刚描述的那样增加它。

原因

问题是由于caching条目小于这些条目的TTL而导致Tomcat无法达到其目标caching大小。 因此,Tomcat没有足够的caching条目可能会过期,因为它们太新鲜了,所以它不能释放足够的caching并输出警告。

这个问题没有出现在Tomcat 7中,因为Tomcat 7在这种情况下根本没有输出警告。 (导致你和我使用不好的caching设置,而没有通知。)

在相对较短的时间内,与caching的大小和TTL相比,在接收到相对大量的资源HTTP请求(通常是静态的)时,会出现此问题。 如果caching达到最大值(默认为10MB),且其大小的95%以上具有新的caching条目(新鲜的意思是caching中的时间less于5秒),那么Tomcat将尝试每个web资源的警告消息加载caching。

背景信息

WebSource是Web应用程序中的文件或目录。 出于性能原因,Tomcat可以cachingWebSource。 静态资源caching (所有资源总数)的最大值默认为10240千字节(10 MB)。 当请求webResource时(例如,加载静态图像时),WebResource被加载到caching中,然后被称为caching条目。 每个caching条目都有一个TTL (生存时间),即允许caching条目留在caching中的时间。 当TTL过期时,caching条目有资格从caching中移除。 cacheTTL的默认值是5000毫秒(5秒)。

还有更多关于caching的内容,但这与问题无关。

原因

Cache类中的以下代码详细显示了caching策略:

  152 //内容不会被caching,但我们仍然需要元数据大小 
153 delta = cacheEntry。 getSize ();
154尺寸。 addAndGet (delta);
156 if (size.get()> maxSize){
157 //处理资源无序的速度。 交易caching
效率(年纪较大的作品可能会在年纪较大之前被驱逐
159 //一个)的速度,因为这是关键的道路上
160 //请求处理
161 targetSize =
162 maxSize *(100 - TARGET_FREE_PERCENT_GET)/ 100;
163 newSize = evict (
targetSize,resourceCache。 values ()。 iterator ());
165 if (newSize> maxSize){
166 //无法为此资源创build足够的空间
//将其从caching中移除
168 removeCacheEntry (path);
169日志。 警告 (sm。getString(“cache.addFail”,path));
170 }
171 }

加载webResource时,代码将计算caching的新大小。 如果计算的大小大于默认最大大小,则必须删除一个或多个高速caching的条目,否则新大小将超过最大值。 所以代码会计算一个“targetSize”,它是caching想要保留的大小(作为最优值),默认为最大值的95%。 为了达到这个targetSize,必须从caching中删除/清除条目。 这是使用以下代码完成的:

  215 私有  evict( long targetSize, Iterator < CachedResource > iter){ 
现在217 =系统。 currentTimeMillis ();
219 newSize =大小。 get ();
221 (newSize> targetSize && iter。hasNext()){
222 CachedResource资源= iter。 next ();
224 //不要过期在TTL中检查过的东西
225 if (resource。getNextCheck()> now){
226 继续 ;
227 }
229 //从caching中删除条目
230 removeCacheEntry (resource。getWebappPath());
232 newSize = size。 get ();
233 }
235 返回 newSize;
236 }

因此,当TTL过期并且targetSize尚未达到时,将删除caching条目。

在尝试通过清除caching条目释放caching之后,代码将执行:

  165 if (newSize> maxSize){ 
166 //无法为此资源创build足够的空间
//将其从caching中移除
168 removeCacheEntry (path);
169日志。 警告 (sm。getString(“cache.addFail”,path));
170 }

因此,如果试图释放caching后,大小仍超过最大值,则会显示无法释放的警告消息:

 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 

问题

正如警告信息所说,问题是

清除过期caching条目后,可用空间不足 – 请考虑增加caching的最大大小

如果您的web应用程序在短时间(5秒)内加载了大量未caching的webResources(关于最大caching,默认为10MB),那么您将得到警告。

令人困惑的是Tomcat 7没有显示警告。 这只是由这个Tomcat 7代码造成的:

  1606 //将新条目添加到caching 
1607 同步 (caching){
1608 //检查caching大小,并删除元素,如果太大
1609 if ((cache.lookup(name)== null )&& cache。allocate(entry.size)){
1610caching。 载入 (entry);
1611 }
1612 }

结合:

  231 (toFree> 0){ 
232 if (attempts == maxAllocateIterations){
233 //放弃,不改变当前的caching
234 返回 false ;
235 }

因此,当Tomcat 7无法释放caching时,根本不会输出任何警告,而Tomcat 8将输出警告。

因此,如果您使用的Tomcat 8具有与Tomcat 7相同的默认cachingconfiguration,并且Tomcat 8中有警告,那么您的(和我的)Tomcat 7的caching设置在没有任何警告的情况下性能很差。

解决scheme

有多种解决scheme:

  1. 增加caching(推荐)
  2. 降低TTL(不推荐)
  3. 取消caching日志警告(不推荐)
  4. 禁用caching

1.增加caching(推荐)

如下所述: http : //tomcat.apache.org/tomcat-8.0-doc/config/resources.html

通过在$CATALINA_BASE/conf/context.xmlContext元素中添加<Resources cacheMaxSize="XXXXX" /> ,其中“XXXXX”表示增加的高速caching大小,以千字节为单位。 默认是10240(10 MB),所以设置一个比这更高的尺寸。

你将不得不调整最佳设置。 请注意,当您突然增加stream量/资源请求时,问题可能会回来。

为了避免每次想要尝试新的caching大小时重新启动服务器,可以在不使用JMX重新启动的情况下对其进行更改。

要启用JMX ,请将其添加到Server元素中的$CATALINA_BASE/conf/server.xml中: <Listener className="org.apache.catalina.mbeans.JmxRemoteLifecycleListener" rmiRegistryPortPlatform="6767" rmiServerPortPlatform="6768" />并下载catalina-jmx-remote.jarhttps://tomcat.apache.org/download-80.cgi放到;$CATALINA_HOME/lib 。 然后使用jConsole(通过Java JDK默认提供)通过JMX连接到服务器,并查看设置的设置以在服务器运行时增加caching大小。 这些设置中的更改应立即生效。

2.降低TTL(不推荐)

cacheTtl值降低5000毫秒以下,并调整为最佳设置。

例如: <Resources cacheMaxSize="2000" />

这有效地降低了在没有使用它的情况下在RAM中填充caching。

3.取消caching日志警告(不推荐)

configuration日志logging以禁用org.apache.catalina.webresources.Cache的logging器。

有关loginTomcat的更多信息: http : //tomcat.apache.org/tomcat-8.0-doc/logging.html

4.禁用caching

您可以通过将cachingAllowed设置为false来禁用caching。 <Resources cachingAllowed="false" />

虽然我记得在Tomcat 8的testing版本中,我使用JMX来禁用caching。 (不确定为什么,但是通过server.xml禁用caching可能会有问题。)

你有更多的静态资源,caching有空间。 您可以执行以下任一操作:

  • 增加caching的大小
  • 降低caching的TTL
  • 禁用caching

有关更多详细信息,请参阅这些configuration选项的文档 。

如果它帮助其他人,我能解决这个问题的唯一方法是将以下内容添加到conf/logging.properties

 org.apache.catalina.webresources.Cache.level = SEVERE 

这将筛选出“无法添加资源”日志,其级别为WARNING。