如何为特定Actuator URL选择性配置独立暴露端口?
Spring Boot Actuator指定部分端点暴露到独立端口实现方案
Spring Boot Actuator原生不支持直接拆分不同端点到不同端口,我们可以通过新增端口监听+访问规则校验的方式实现需求,以下是两种常用的可落地实现方案:
前置说明
假设你的业务服务默认端口为8080,需求是将/actuator/prometheus、/actuator/metrics两类端点单独暴露到9090端口,其余actuator端点仍保留在8080端口访问。
首先保留原有actuator的基础配置,不需要设置全局的management.server.port:
management.endpoints.web.exposure.include: "health, prometheus, metrics, asgHealth, slaFunc, slaAvail" management.endpoint.metrics.enabled: true management.endpoint.prometheus.enabled: true management.metrics.export.prometheus.enabled: true # 业务默认端口 server.port: 8080
方案一:新增端口监听+Spring Security规则校验(推荐)
步骤1:配置嵌入式容器新增9090端口监听
以常用的Tomcat容器为例,新增配置类让服务同时监听8080和9090两个端口:
import org.apache.catalina.connector.Connector; import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class TomcatPortConfig { @Bean public WebServerFactoryCustomizer<TomcatServletWebServerFactory> addManagementPort() { return factory -> { Connector managementConnector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL); managementConnector.setPort(9090); factory.addAdditionalTomcatConnectors(managementConnector); }; } }
步骤2:配置Security端口访问规则
限制不同端点允许访问的端口:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.web.SecurityFilterChain; @Configuration public class ActuatorAccessConfig { @Bean public SecurityFilterChain actuatorSecurityRule(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth // prometheus、metrics仅允许9090端口访问 .requestMatchers("/actuator/prometheus", "/actuator/metrics/**") .access((authentication, context) -> () -> context.getRequest().getServerPort() == 9090 ) // 其余actuator端点仅允许业务端口8080访问 .requestMatchers("/actuator/**") .access((authentication, context) -> () -> context.getRequest().getServerPort() == 8080 ) // 业务接口按需配置权限,这里默认放行 .anyRequest().permitAll() ) // 无特殊需求可关闭actuator路径的csrf防护 .csrf(csrf -> csrf.ignoringRequestMatchers("/actuator/**")); return http.build(); } }
方案二:新增端口监听+自定义过滤器校验(无Spring Security依赖场景)
如果项目没有引入Spring Security,可以用自定义过滤器实现端口校验逻辑:
步骤1:同方案一步骤1,新增9090端口监听
步骤2:自定义端口校验过滤器
import jakarta.servlet.*; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; public class ActuatorPortCheckFilter implements Filter { // 管理端口 private static final int MANAGE_PORT = 9090; // 业务端口 private static final int BUSINESS_PORT = 8080; // 需要限制只能从管理端口访问的端点前缀 private static final String[] MANAGE_ONLY_ENDPOINTS = {"/actuator/prometheus", "/actuator/metrics"}; @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse resp = (HttpServletResponse) response; String requestUri = req.getRequestURI(); int currentPort = req.getServerPort(); // 校验管理端口专属端点 for (String endpoint : MANAGE_ONLY_ENDPOINTS) { if (requestUri.startsWith(endpoint)) { if (currentPort != MANAGE_PORT) { resp.sendError(HttpServletResponse.SC_FORBIDDEN, "该端点仅允许从管理端口访问"); return; } chain.doFilter(request, response); return; } } // 校验其余actuator端点仅允许业务端口访问 if (requestUri.startsWith("/actuator/") && currentPort != BUSINESS_PORT) { resp.sendError(HttpServletResponse.SC_FORBIDDEN, "该端点仅允许从业务端口访问"); return; } chain.doFilter(request, response); } }
步骤3:注册过滤器到容器
import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class FilterRegisterConfig { @Bean public FilterRegistrationBean<ActuatorPortCheckFilter> actuatorPortFilter() { FilterRegistrationBean<ActuatorPortCheckFilter> registration = new FilterRegistrationBean<>(); registration.setFilter(new ActuatorPortCheckFilter()); // 过滤器只拦截actuator路径 registration.addUrlPatterns("/actuator/*"); // 设置最高优先级 registration.setOrder(Integer.MIN_VALUE); return registration; } }
最终效果验证
http://你的服务地址:8080/actuator/health:正常返回http://你的服务地址:8080/actuator/prometheus:返回403禁止访问http://你的服务地址:9090/actuator/prometheus:正常返回http://你的服务地址:9090/actuator/health:返回403禁止访问
内容的提问来源于stack exchange,提问作者kingkong
相关产品推荐
相关产品推荐

