Disable Tomcat's MBean Registry by default

Closes gh-16498
This commit is contained in:
Andy Wilkinson 2019-05-21 17:00:53 +01:00
parent 080a2f5c3b
commit b603cd5d4b
9 changed files with 119 additions and 16 deletions

View File

@ -27,6 +27,7 @@ import org.springframework.boot.autoconfigure.web.embedded.NettyWebServerFactory
import org.springframework.boot.autoconfigure.web.embedded.TomcatWebServerFactoryCustomizer;
import org.springframework.boot.autoconfigure.web.embedded.UndertowWebServerFactoryCustomizer;
import org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryCustomizer;
import org.springframework.boot.autoconfigure.web.reactive.TomcatReactiveWebServerFactoryCustomizer;
import org.springframework.boot.web.reactive.server.ConfigurableReactiveWebServerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
@ -65,6 +66,7 @@ public class ReactiveManagementChildContextConfiguration {
ReactiveManagementWebServerFactoryCustomizer(ListableBeanFactory beanFactory) {
super(beanFactory, ReactiveWebServerFactoryCustomizer.class,
TomcatWebServerFactoryCustomizer.class,
TomcatReactiveWebServerFactoryCustomizer.class,
JettyWebServerFactoryCustomizer.class,
UndertowWebServerFactoryCustomizer.class,
NettyWebServerFactoryCustomizer.class);

View File

@ -17,10 +17,12 @@
package org.springframework.boot.actuate.autoconfigure.metrics.web.tomcat;
import java.util.Collections;
import java.util.concurrent.atomic.AtomicInteger;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.binder.tomcat.TomcatMetrics;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import org.apache.tomcat.util.modeler.Registry;
import org.junit.jupiter.api.Test;
import org.springframework.boot.SpringApplication;
@ -33,11 +35,13 @@ import org.springframework.boot.test.context.runner.ReactiveWebApplicationContex
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
import org.springframework.boot.web.embedded.tomcat.TomcatReactiveWebServerFactory;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.embedded.tomcat.TomcatWebServer;
import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.server.reactive.HttpHandler;
import org.springframework.test.util.ReflectionTestUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
@ -51,6 +55,7 @@ public class TomcatMetricsAutoConfigurationTests {
@Test
public void autoConfiguresTomcatMetricsWithEmbeddedServletTomcat() {
resetTomcatState();
new WebApplicationContextRunner(
AnnotationConfigServletWebServerApplicationContext::new)
.withConfiguration(AutoConfigurations.of(
@ -58,6 +63,7 @@ public class TomcatMetricsAutoConfigurationTests {
ServletWebServerFactoryAutoConfiguration.class))
.withUserConfiguration(ServletWebServerConfiguration.class,
MeterRegistryConfiguration.class)
.withPropertyValues("server.tomcat.mbeanregistry.enabled=true")
.run((context) -> {
context.publishEvent(
new ApplicationStartedEvent(new SpringApplication(),
@ -75,6 +81,7 @@ public class TomcatMetricsAutoConfigurationTests {
@Test
public void autoConfiguresTomcatMetricsWithEmbeddedReactiveTomcat() {
resetTomcatState();
new ReactiveWebApplicationContextRunner(
AnnotationConfigReactiveWebServerApplicationContext::new)
.withConfiguration(AutoConfigurations.of(
@ -82,6 +89,7 @@ public class TomcatMetricsAutoConfigurationTests {
ReactiveWebServerFactoryAutoConfiguration.class))
.withUserConfiguration(ReactiveWebServerConfiguration.class,
MeterRegistryConfiguration.class)
.withPropertyValues("server.tomcat.mbeanregistry.enabled=true")
.run((context) -> {
context.publishEvent(
new ApplicationStartedEvent(new SpringApplication(),
@ -130,6 +138,13 @@ public class TomcatMetricsAutoConfigurationTests {
.hasBean("customTomcatMetrics"));
}
private void resetTomcatState() {
ReflectionTestUtils.setField(Registry.class, "registry", null);
AtomicInteger containerCounter = (AtomicInteger) ReflectionTestUtils
.getField(TomcatWebServer.class, "containerCounter");
containerCounter.set(-1);
}
@Configuration(proxyBeanMethods = false)
static class MeterRegistryConfiguration {

View File

@ -23,8 +23,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
import javax.validation.Configuration;
import javax.validation.Validation;
import org.apache.catalina.mbeans.MBeanFactory;
import org.springframework.boot.context.event.ApplicationFailedEvent;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.boot.context.event.ApplicationStartingEvent;
@ -99,7 +97,6 @@ public class BackgroundPreinitializer
runSafely(new ConversionServiceInitializer());
runSafely(new ValidationInitializer());
runSafely(new MessageConverterInitializer());
runSafely(new MBeanFactoryInitializer());
runSafely(new JacksonInitializer());
runSafely(new CharsetInitializer());
preinitializationComplete.countDown();
@ -137,18 +134,6 @@ public class BackgroundPreinitializer
}
/**
* Early initializer to load Tomcat MBean XML.
*/
private static class MBeanFactoryInitializer implements Runnable {
@Override
public void run() {
new MBeanFactory();
}
}
/**
* Early initializer for javax.validation.
*/

View File

@ -400,6 +400,11 @@ public class ServerProperties {
*/
private final Resource resource = new Resource();
/**
* Modeler MBean Registry configuration.
*/
private final Mbeanregistry mbeanregistry = new Mbeanregistry();
public int getMaxThreads() {
return this.maxThreads;
}
@ -552,6 +557,10 @@ public class ServerProperties {
return this.resource;
}
public Mbeanregistry getMbeanregistry() {
return this.mbeanregistry;
}
/**
* Tomcat access log properties.
*/
@ -821,6 +830,23 @@ public class ServerProperties {
}
public static class Mbeanregistry {
/**
* Whether Tomcat's MBean Registry should be enabled.
*/
private boolean enabled;
public boolean isEnabled() {
return this.enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}
}
/**

View File

@ -24,6 +24,7 @@ import reactor.netty.http.server.HttpServer;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.web.embedded.jetty.JettyReactiveWebServerFactory;
import org.springframework.boot.web.embedded.jetty.JettyServerCustomizer;
import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory;
@ -98,6 +99,12 @@ abstract class ReactiveWebServerFactoryConfiguration {
return factory;
}
@Bean
public TomcatReactiveWebServerFactoryCustomizer tomcatReactiveWebServerFactoryCustomizer(
ServerProperties serverProperties) {
return new TomcatReactiveWebServerFactoryCustomizer(serverProperties);
}
}
@Configuration(proxyBeanMethods = false)

View File

@ -0,0 +1,48 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.web.reactive;
import org.apache.tomcat.util.modeler.Registry;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.web.embedded.tomcat.TomcatReactiveWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
/**
* {@link WebServerFactoryCustomizer} to apply {@link ServerProperties} to Tomcat reactive
* web servers.
*
* @author Andy Wilkinson
* @since 2.2.0
*/
public class TomcatReactiveWebServerFactoryCustomizer
implements WebServerFactoryCustomizer<TomcatReactiveWebServerFactory> {
private final ServerProperties serverProperties;
public TomcatReactiveWebServerFactoryCustomizer(ServerProperties serverProperties) {
this.serverProperties = serverProperties;
}
@Override
public void customize(TomcatReactiveWebServerFactory factory) {
if (!this.serverProperties.getTomcat().getMbeanregistry().isEnabled()) {
Registry.disableRegistry();
}
}
}

View File

@ -16,6 +16,8 @@
package org.springframework.boot.autoconfigure.web.servlet;
import org.apache.tomcat.util.modeler.Registry;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.web.embedded.tomcat.ConfigurableTomcatWebServerFactory;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
@ -60,6 +62,9 @@ public class TomcatServletWebServerFactoryCustomizer
customizeUseRelativeRedirects(factory,
tomcatProperties.getUseRelativeRedirects());
}
if (!tomcatProperties.getMbeanregistry().isEnabled()) {
Registry.disableRegistry();
}
}
private void customizeRedirectContextRoot(ConfigurableTomcatWebServerFactory factory,

View File

@ -1075,6 +1075,20 @@ include::{code-examples}/context/embedded/TomcatLegacyCookieProcessorExample.jav
[[howto-enable-tomcat-mbean-registry]]
=== Enable Tomcat's MBean Registry
Embedded Tomcat's MBean registry is disabled by default. This minimizes Tomcat's memory
footprint. If you want to use Tomcat's MBeans, for example so that they can be used to
expose metrics via Micrometer, you must use the `server.tomcat.mbeanregistry.enabled`
property to do so, as shown in the following example:
[source,properties,indent=0]
----
server.tomcat.mbeanregistry.enabled=true
----
[[howto-enable-multiple-listeners-in-undertow]]
=== Enable Multiple Listeners with Undertow
Add an `UndertowBuilderCustomizer` to the `UndertowServletWebServerFactory` and

View File

@ -1793,7 +1793,8 @@ Spring Boot registers the following core metrics when applicable:
* Logback metrics: record the number of events logged to Logback at each level
* Uptime metrics: report a gauge for uptime and a fixed gauge representing the
application's absolute start time
* Tomcat metrics
* Tomcat metrics (`server.tomcat.mbeanregistry.enabled` must be set to `true` for all
Tomcat metrics to be registered)
* https://docs.spring.io/spring-integration/docs/current/reference/html/system-management-chapter.html#micrometer-integration[Spring Integration] metrics