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“扫描失败”

如何知道spring boot中嵌入了哪个tomcat版本

spring boot 2 内嵌Tomcat 抛出异常 “Stopping service [Tomcat]”

spring boot 2 内嵌Tomcat 抛出异常 “Stopping service [Tomcat]”