Spring Boot 如何控制 Tomcat 缓存?
Posted
技术标签:
【中文标题】Spring Boot 如何控制 Tomcat 缓存?【英文标题】:How does Spring Boot control Tomcat cache? 【发布时间】:2017-01-01 22:57:15 【问题描述】:我正在将 5 年前的带有 JSP 的 Spring MVC 应用程序移植到 Spring Boot。因此,根据http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-jsp-limitations中的示例,我使用的是“战争”包装。
嵌入式 tomcat 启动。但是日志中充满了缓存警告,如下例所示
2016-08-25 14:59:01.442 INFO 28884 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer:Tomcat 使用端口初始化:8080 (http) 2016-08-25 14:59:01.456 INFO 28884 --- [main] o.apache.catalina.core.StandardService:启动服务 Tomcat 2016-08-25 14:59:01.458 信息 28884 --- [主要] org.apache.catalina.core.StandardEngine:启动 Servlet 引擎:Apache Tomcat/8.5.4 2016-08-25 14:59:01.531 WARN 28884 --- [ost-startStop-1] org.apache.catalina.webresources.Cache:无法在 [/WEB-INF/lib/displaytag-1.2. jar] 到缓存,因为在驱逐过期缓存条目后没有足够的可用空间 - 考虑增加缓存的最大大小 2016-08-25 14:59:01.531 WARN 28884 --- [ost-startStop-1] org.apache.catalina.webresources.Cache:无法在 [/WEB-INF/lib/decrex-maven- 添加资源0.1.10-SNAPSHOT.jar] 到缓存,因为在驱逐过期缓存条目后可用空间不足 - 考虑增加缓存的最大大小 2016-08-25 14:59:01.531 WARN 28884 --- [ost-startStop-1] org.apache.catalina.webresources.Cache:无法在 [/WEB-INF/lib/spring-boot- 添加资源actuator-1.4.0.RELEASE.jar] 到缓存,因为在驱逐过期缓存条目后没有足够的可用空间 - 考虑增加缓存的最大大小 2016-08-25 14:59:01.531 WARN 28884 --- [ost-startStop-1] org.apache.catalina.webresources.Cache:无法在 [/WEB-INF/lib/validation-api- 添加资源1.1.0.Final.jar] 到缓存,因为在驱逐过期缓存条目后可用空间不足 - 考虑增加缓存的最大大小 2016-08-25 14:59:01.532 WARN 28884 --- [ost-startStop-1] org.apache.catalina.webresources.Cache:无法在 [/WEB-INF/lib/lucene-backward- 添加资源codecs-5.3.1.jar] 到缓存,因为在驱逐过期缓存条目后没有足够的可用空间 - 考虑增加缓存的最大大小 2016-08-25 14:59:01.532 WARN 28884 --- [ost-startStop-1] org.apache.catalina.webresources.Cache:无法在 [/WEB-INF/lib/lucene-queries- 添加资源5.3.1.jar] 到缓存,因为在驱逐过期的缓存条目后没有足够的可用空间 - 考虑增加缓存的最大大小 ...... 2016-08-25 14:59:05.121 WARN 28884 --- [ost-startStop-1] org.apache.catalina.webresources.Cache:无法在 [/WEB-INF/lib/jstl-1.2. jar] 到缓存,因为在驱逐过期缓存条目后没有足够的可用空间 - 考虑增加缓存的最大大小 2016-08-25 14:59:05.139 WARN 28884 --- [ost-startStop-1] org.apache.catalina.webresources.Cache:无法在 [/WEB-INF/classes/commons-logging. properties] 到缓存,因为在驱逐过期的缓存条目后没有足够的可用空间 - 考虑增加缓存的最大大小 2016-08-25 14:59:05.139 INFO 28884 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]:初始化 Spring 嵌入式 WebApplicationContext 2016-08-25 14:59:05.139 INFO 28884 --- [ost-startStop-1] os.web.context.ContextLoader:根 WebApplicationContext:初始化在 7117 毫秒内完成 ...... 2016-08-25 15:02:03.960 INFO 28884 --- [ndardContext[]]] org.apache.catalina.webresources.Cache:后台缓存驱逐进程无法释放 [10]% 的 Context [ ] - 考虑增加缓存的最大大小。驱逐后大约 [9,251] KB 的数据保留在缓存中。我很乐意增加 tomcat 缓存,但我找不到在 Spring Boot 中控制它的方法。请建议!!!
我在下面尝试了安迪威尔金森的建议。还尝试在
EmbeddedServletContainerCustomizer
中使用它
@零件
公共类 ServletContainerCustomizer 实现 EmbeddedServletContainerCustomizer
私有静态最终日志日志 = LogFactory.getLog(ServletContainerCustomizer.class);
@覆盖
公共无效定制(ConfigurableEmbeddedServletContainer 容器)
if (TomcatEmbeddedServletContainerFactory.class.isAssignableFrom(container.getClass()))
int 缓存大小 = 256 * 1024;
log.info("自定义tomcat工厂。新缓存大小(KB)为" + cacheSize);
TomcatEmbeddedServletContainerFactory tomcatFactory = (TomcatEmbeddedServletContainerFactory) 容器;
tomcatFactory.addContextCustomizers((上下文)->
StandardRoot standardRoot = new StandardRoot(context);
standardRoot.setCacheMaxSize(cacheSize);
);
关于更改缓存大小的消息在日志中,但上面的代码对警告没有影响
【问题讨论】:
有一些关于此错误的信息:***.com/questions/26893297/… 据我所知,要增加缓存大小,您必须定义EmbeddedServletContainerCustomizer
感谢您的想法。我可以访问TomcatEmbeddedServletContainerFactory 的实例。但是没有方法可以帮助控制缓存
【参考方案1】:
我遇到同样的问题已经有一段时间了,但安迪威尔金森的提示让我走上了正确的道路。 对我有用的是像 Andy 一样设置缓存,然后在上下文中显式设置资源。
@Bean
public EmbeddedServletContainerFactory servletContainer()
TomcatEmbeddedServletContainerFactory tomcatFactory = new TomcatEmbeddedServletContainerFactory()
@Override
protected void postProcessContext(Context context)
final int cacheSize = 40 * 1024;
StandardRoot standardRoot = new StandardRoot(context);
standardRoot.setCacheMaxSize(cacheSize);
context.setResources(standardRoot); // This is what made it work in my case.
logger.info(String.format("New cache size (KB): %d", context.getResources().getCacheMaxSize()));
;
return tomcatFactory;
希望这会有所帮助!
【讨论】:
太好了,谢谢!我看到创建的standardRoot
没有在任何地方传递,但我说服自己没关系,因为它在构造函数中得到了context
。
谢谢,可以确认它与 spring boot 1.4.2 一起工作。【参考方案2】:
您可以使用上下文定制器配置缓存大小,以使用定制的StandardRoot
配置上下文:
Java 7:
@Bean
public TomcatEmbeddedServletContainerFactory tomcatFactory()
TomcatEmbeddedServletContainerFactory tomcatFactory = new TomcatEmbeddedServletContainerFactory();
tomcatFactory.addContextCustomizers(new TomcatContextCustomizer()
@Override
public void customize(Context context)
StandardRoot standardRoot = new StandardRoot(context);
standardRoot.setCacheMaxSize(40 * 1024);
);
return tomcatFactory;
Java 8:
@Bean
public TomcatEmbeddedServletContainerFactory tomcatFactory()
TomcatEmbeddedServletContainerFactory tomcatFactory = new TomcatEmbeddedServletContainerFactory();
tomcatFactory.addContextCustomizers((context) ->
StandardRoot standardRoot = new StandardRoot(context);
standardRoot.setCacheMaxSize(40 * 1024);
);
return tomcatFactory;
【讨论】:
非常感谢!我尝试了您的建议(使用 1024*1024)两种方式:创建工厂并稍后在 EmbeddedServletContainerCustomizer 中对其进行自定义(代码已添加到我的问题中)。然而,两者都对结果没有任何影响 - 警告仍然存在standardRoot.setCachingAllowed(false);
也不禁用缓存。似乎StandardRoot
不会影响任何事情
听起来您的定制器没有被使用。您确定它在组件扫描涵盖的包中吗?
是的。为了确保这一点,我在定制器中添加了log.info("...")
语句,我在日志中看到了这个语句
嗯,它对我有用。如果没有显示它不起作用的 complete 示例,我很难过。【参考方案3】:
参考那里的答案here,我创建了 src/main/webapp/META-INF/context.xml 并添加了以下内容。
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Resources cachingAllowed="true" cacheMaxSize="204800" />
</Context>
【讨论】:
我使用外部tomcat,只有这个答案对我有用。以上是关于Spring Boot 如何控制 Tomcat 缓存?的主要内容,如果未能解决你的问题,请参考以下文章
尝试在外部在tomcat 9上运行带有rest控制器的spring boot war文件
spring boot 2 内嵌Tomcat Stopping service [Tomcat]
如何解决tomcat的问题? Spring-Boot“扫描失败”