[spring-projects/spring-boot]默认情况下禁用 Tomcat 的 MBean 注册表并提供一个属性来启用它

2024-04-10 644 views

回答

7

我不久前尝试过这个。我想出的最好的办法是提供一个已删除的org.apache.tomcat.util.modeler.Registry实现。我找不到在不使用反射的情况下插入它的方法,因为实例Registry是通过私有字段支持的静态方法检索的,所以我放弃了它。我想知道 Meecroweave 是否想出了更聪明的办法。

6

Meecroweave使用反射来交换registry上静态字段的值org.apache.tomcat.util.modeler.Registry

我将衡量收益,然后我们可以决定性能改进是否值得进行反思性黑客攻击。

4

对于大多数人来说,启动时间方面的好处可以忽略不计。我相信这是因为后台预初始化程序导致昂贵的描述符解析在单独的线程上并行完成。在可能禁用预初始化器的 CPU 受限环境中,优势将更加明显。

在内存使用方面的好处更加明显。以前需要 -Xmx13M 的应用程序就位后NoOpRegistry将以 -Xmx11M 开头。这是使用 Tomcat 9.0.17 进行测试的。

7

在 Tomcat 9.0.19 中,相同的应用程序默认以 -Xmx9M 开头(感谢https://github.com/apache/tomcat/pull/146),并以 -Xmx7M 开头NoOpRegistry。当考虑所需堆的百分比时,大约 2MB 的减少变得越来越有吸引力。

2

@markt-asf 您是否会考虑 Tomcat 增强功能,允许以更简单的方式关闭 JMX?节省 2MB 的堆空间非常有吸引力,如果我们不必借助反射来做到这一点,那就更有吸引力了。

4

这并不完全是我的决定,但我不反对这样做的增强请求。如果您在 Bugzilla 中打开增强请求,我会将其添加到当前相当长的 TODO 列表中。

5

感谢 @markt-asf,Tomcat 9.0.20 有了一个新Registry.disableRegistry()方法,我们可以调用它来禁用 Tomcat 的 MBean 注册。我认为我们应该默认禁用它并提供一种机制将其重新打开。我们也许可以使用spring.jmx.enabled或者我们可能想要一个 Tomcat 特定的属性。

3

我们认为 Tomcat 特定的属性会更好。如果我们依赖它,那么当设置为spring.jmx.enabled时,就不可能让事情恢复到 2.1.x 中的状态。就像是。spring.jmx.enabledfalseserver.tomcat.registry.enabled

6

禁用注册表的副作用是一些 Tomcat 指标会因为基于 MBean 而丢失。 HTTP 会话指标会保留,但线程池、缓存、servlet 和全局请求指标都会丢失。可以以不同的方式绑定其中一些指标,以避免使用 MBean 作为源。

4

我认为这破坏了目前的构建。 Tomcat EE 测试没有可用的方法,因为它们似乎引入了旧版本的 tomcat。以下是可行的解决方案吗?

    Method disableMethod = ReflectionUtils.findMethod(Registry.class, "disableRegistry");
    if (disableMethod != null) {
        ReflectionUtils.invokeMethod(disableMethod, null);
    }

最后这涉及到反射,我猜你想避免@wilkinsona

5

该代码根本不应该在 TomEE 上运行,因为它是特定于嵌入式 Tomcat 的。我会看一看。谢谢,@dreis2211。

0
    if (disableMethod != null) {
        ReflectionUtils.invokeMethod(disableMethod, null);
    }

这段代码不会也“打破”多个测试调用的情况TomcatServletWebServerFactory.getWebServer吗?我有一个项目,其中有一个@SpringBootTest和一个测试,通过启动应用程序SpringApplication.run,第二次调用第二次getWebServer调用 Tomcat 中的以下代码Registry,因此registry已经保存了一个实例NoDescriptorRegistry,从而记录了警告。

    public static synchronized void disableRegistry() {
        if (registry == null) {
            registry = new NoDescriptorRegistry();
        } else {
            log.warn(sm.getString("registry.noDisable"));
        }

    }

我将“break”(上面)放在引号中,但由于我们因日志中的意外警告而导致测试失败,所以我现在有一个损坏的测试。这是一个不幸的警告。 (我知道我可以使用 修复它server.tomcat.mbeanregistry.enabled=true,但它不太漂亮。)

2

感谢您向 Tomcat 团队解决该问题。我偶然发现了这个误报警告 ( The MBean registry cannot be disabled because it has already been initialised),因为我们在应用程序中为管理服务器使用了不同的端口(management.server.port已设置)。

3

默认情况下,Tomcat 启用为“false”,我们应该这样做:

server.tomcat.mbeanregistry.enabled=true

0

我发现自己现在正在寻找方法来强制这个标志无条件地为真。我们需要它对于 dynatrace 集成来说是正确的,但我天真的认为,只需在开发人员的说明中说明这一点就足够了。我们控制启动脚本,因此我只需添加“-Dserver.tomcat.mbeanregistry.enabled=true”即可。必须这样做似乎很奇怪。