From e465368f546fc50f7ab841dd1392f35dd6bfb8fb Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Mon, 22 Aug 2016 22:36:28 +0100 Subject: [PATCH] Ensure that access log is flushed periodically MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, Tomcat’s background processing was only enabled on the context but access logging was configured on the engine. This means that the access log valve’s background processing method was never called and, therefore, that it wasn’t flushed periodically. This commit moves the enablement of background processing up to the engine, thereby ensuring that the access log is flushed periodically. Background processing cascades down the container hierarchy so, after this change, background processing will still be performed on the context as well. Closes gh-6646 --- .../autoconfigure/web/ServerProperties.java | 15 +---------- .../web/ServerPropertiesTests.java | 26 +++++++++++++++++++ ...TomcatEmbeddedServletContainerFactory.java | 13 +++++++++- 3 files changed, 39 insertions(+), 15 deletions(-) diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java index 13b17dee4f..902fdb7ddf 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java @@ -777,7 +777,7 @@ public class ServerProperties if (getBasedir() != null) { factory.setBaseDirectory(getBasedir()); } - customizeBackgroundProcessorDelay(factory); + factory.setBackgroundProcessorDelay(Tomcat.this.backgroundProcessorDelay); customizeRemoteIpValve(serverProperties, factory); if (this.maxThreads > 0) { customizeMaxThreads(factory); @@ -819,19 +819,6 @@ public class ServerProperties } } - private void customizeBackgroundProcessorDelay( - TomcatEmbeddedServletContainerFactory factory) { - factory.addContextCustomizers(new TomcatContextCustomizer() { - - @Override - public void customize(Context context) { - context.setBackgroundProcessorDelay( - Tomcat.this.backgroundProcessorDelay); - } - - }); - } - private void customizeRemoteIpValve(ServerProperties properties, TomcatEmbeddedServletContainerFactory factory) { String protocolHeader = getProtocolHeader(); diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java index 0db14c7cf9..177c5f2dda 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java @@ -43,6 +43,7 @@ import org.springframework.boot.bind.RelaxedDataBinder; import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer; import org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory; import org.springframework.boot.context.embedded.tomcat.TomcatContextCustomizer; +import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer; import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory; import org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainerFactory; import org.springframework.boot.web.servlet.ServletContextInitializer; @@ -140,6 +141,7 @@ public class ServerPropertiesTests { map.put("server.tomcat.protocol_header", "X-Forwarded-Protocol"); map.put("server.tomcat.remote_ip_header", "Remote-Ip"); map.put("server.tomcat.internal_proxies", "10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"); + map.put("server.tomcat.background_processor_delay", "10"); bindProperties(map); ServerProperties.Tomcat tomcat = this.properties.getTomcat(); assertThat(tomcat.getAccesslog().getPattern()).isEqualTo("%h %t '%r' %s %b"); @@ -150,6 +152,7 @@ public class ServerPropertiesTests { assertThat(tomcat.getProtocolHeader()).isEqualTo("X-Forwarded-Protocol"); assertThat(tomcat.getInternalProxies()) .isEqualTo("10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"); + assertThat(tomcat.getBackgroundProcessorDelay()).isEqualTo(10); } @Test @@ -352,6 +355,29 @@ public class ServerPropertiesTests { testRemoteIpValveConfigured(); } + @Test + public void defaultTomcatBackgroundProcessorDelay() throws Exception { + TomcatEmbeddedServletContainerFactory container = new TomcatEmbeddedServletContainerFactory(); + this.properties.customize(container); + assertThat( + ((TomcatEmbeddedServletContainer) container.getEmbeddedServletContainer()) + .getTomcat().getEngine().getBackgroundProcessorDelay()) + .isEqualTo(30); + } + + @Test + public void customTomcatBackgroundProcessorDelay() throws Exception { + Map map = new HashMap(); + map.put("server.tomcat.background-processor-delay", "5"); + bindProperties(map); + TomcatEmbeddedServletContainerFactory container = new TomcatEmbeddedServletContainerFactory(); + this.properties.customize(container); + assertThat( + ((TomcatEmbeddedServletContainer) container.getEmbeddedServletContainer()) + .getTomcat().getEngine().getBackgroundProcessorDelay()) + .isEqualTo(5); + } + @Test public void setUseForwardHeadersTomcat() throws Exception { // Since 1.3.0 no need to explicitly set header names if use-forward-header=true diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java index 5e2015a335..8aaa3a3b94 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java @@ -129,6 +129,8 @@ public class TomcatEmbeddedServletContainerFactory private Charset uriEncoding = DEFAULT_CHARSET; + private int backgroundProcessorDelay; + /** * Create a new {@link TomcatEmbeddedServletContainerFactory} instance. */ @@ -176,7 +178,7 @@ public class TomcatEmbeddedServletContainerFactory } private void configureEngine(Engine engine) { - engine.setBackgroundProcessorDelay(-1); + engine.setBackgroundProcessorDelay(this.backgroundProcessorDelay); for (Valve valve : this.engineValves) { engine.getPipeline().addValve(valve); } @@ -765,6 +767,15 @@ public class TomcatEmbeddedServletContainerFactory return this.uriEncoding; } + /** + * Sets the background processor delay in seconds. + * @param delay the delay in seconds + * @since 1.4.1 + */ + public void setBackgroundProcessorDelay(int delay) { + this.backgroundProcessorDelay = delay; + } + /** * {@link LifecycleListener} that stores an empty merged web.xml. This is critical for * Jasper on Tomcat 7 to prevent warnings about missing web.xml files and to enable