Actuator与应用程序端口隔离

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

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相关的接口。

Comment