SpringBoot应用当中,默认情况下Actuator与应用程序在相同的端口号启动。但是可能会存在一些场景(比如主程序可能是需要对外暴露的,但是Actuator只是内网暴露的),需要将Actuator与应用程序的主端口隔离开。

可以参考如下的配置,其中server.port配置的是主程序的端口号,management.server.port则配置的是Actuator的端口号。

server.port=8080
management.server.port=8891

配置后,Actuator就无法在8080端口访问,需要在8891端口进行访问。

Actuator与应用程序端口隔离的代码位置如下:

// org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration

@AutoConfiguration
@AutoConfigureOrder(Ordered.LOWEST_PRECEDENCE)
@EnableConfigurationProperties({ WebEndpointProperties.class, ManagementServerProperties.class })
public class ManagementContextAutoConfiguration {

    @Configuration(proxyBeanMethods = false)
    @ConditionalOnManagementPort(ManagementPortType.SAME)
    static class SameManagementContextConfiguration implements SmartInitializingSingleton {

        private final Environment environment;

        SameManagementContextConfiguration(Environment environment) {
            this.environment = environment;
        }

        @Override
        public void afterSingletonsInstantiated() {
            verifySslConfiguration();
            verifyAddressConfiguration();
            if (this.environment instanceof ConfigurableEnvironment configurableEnvironment) {
                addLocalManagementPortPropertyAlias(configurableEnvironment);
            }
        }

        private void verifySslConfiguration() {
            Boolean enabled = this.environment.getProperty("management.server.ssl.enabled", Boolean.class, false);
            Assert.state(!enabled, "Management-specific SSL cannot be configured as the management "
                    + "server is not listening on a separate port");
        }

        private void verifyAddressConfiguration() {
            Object address = this.environment.getProperty("management.server.address");
            Assert.state(address == null, "Management-specific server address cannot be configured as the management "
                    + "server is not listening on a separate port");
        }

        /**
         * Add an alias for 'local.management.port' that actually resolves using
         * 'local.server.port'.
         * @param environment the environment
         */
        private void addLocalManagementPortPropertyAlias(ConfigurableEnvironment environment) {
            environment.getPropertySources().addLast(new PropertySource<>("Management Server") {

                @Override
                public Object getProperty(String name) {
                    if ("local.management.port".equals(name)) {
                        return environment.getProperty("local.server.port");
                    }
                    return null;
                }

            });
        }

        @Configuration(proxyBeanMethods = false)
        @EnableManagementContext(ManagementContextType.SAME)
        static class EnableSameManagementContextConfiguration {

        }

    }

    @Configuration(proxyBeanMethods = false)
    @ConditionalOnManagementPort(ManagementPortType.DIFFERENT)
    static class DifferentManagementContextConfiguration {

        @Bean
        static ChildManagementContextInitializer childManagementContextInitializer(
                ManagementContextFactory managementContextFactory, ApplicationContext parentContext) {
            return new ChildManagementContextInitializer(managementContextFactory, parentContext);
        }

    }

}

其中会去识别management.server.portserver.port不一致(ManagementPortType=DIFFERENT)的话,那么将会使用ChildManagementContextInitializer去创建一个子ApplicationContext,专门用来处理Actuator相关的接口。