如何让 Javamelody 使用不同的端口(Spring Boot+暴露的两个 HTTP 端口)
How to make Javamelody use different port (Spring Boot+two HTTP ports exposed)
我有 Spring 引导 Web 应用程序。它在端口 8080 上公开 REST API。它还通过 Spring 引导管理端点 (http://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-monitoring.html) 公开管理端口 8081。
我没有任何自定义 Tomcat 配置来实现这一点。我的 application.properties
文件中只有 属性 management.port=8081
。
我按照中所述配置了 JavaMelody
https://github.com/javamelody/javamelody/wiki/UserGuideAdvanced#spring-boot-app
(我有我的自定义 JavaMelodyConfiguration
class,org.springframework.boot.web.servlet.FilterRegistrationBean
注册 net.bull.javamelody.MonitoringFilter
)。
@Bean
public FilterRegistrationBean javaMelody() {
final FilterRegistrationBean javaMelody = new FilterRegistrationBean();
javaMelody.setFilter(new MonitoringFilter());
javaMelody.setAsyncSupported(true);
javaMelody.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ASYNC);
javaMelody.addUrlPatterns("/*");
return javaMelody;
}
通过此配置,Javamelody 暴露在端口 8080(业务端口)上。我想把它移到 8081(管理端口)。如何改变?
我使用Spring Boot 1.4.2.RELEASE, javamelody 1.62.0
编辑:此答案仍然正确,但请参阅已接受的答案以获得更简单的解决方案。
EmbeddedTomcatConfiguration.java
package ...
import java.util.ArrayList;
import java.util.List;
import org.apache.catalina.connector.Connector;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class EmbeddedTomcatConfiguration {
@Value("${server.additionalPorts}")
private String additionalPorts;
@Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
Connector[] additionalConnectors = this.additionalConnector();
if (additionalConnectors != null && additionalConnectors.length > 0) {
tomcat.addAdditionalTomcatConnectors(additionalConnectors);
}
return tomcat;
}
private Connector[] additionalConnector() {
if (StringUtils.isBlank(this.additionalPorts)) {
return null;
}
String[] ports = this.additionalPorts.split(",");
List<Connector> result = new ArrayList<>();
for (String port : ports) {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setScheme("http");
connector.setPort(Integer.valueOf(port));
result.add(connector);
}
return result.toArray(new Connector[] {});
}
}
application.yml
server:
port: ${appPort:8800}
additionalPorts: 8880,8881
Application.java
@SpringBootApplication
@ComponentScan(...)
@Import(EmbeddedTomcatConfiguration.class)
public Application {
public static void main(String[] args) {
SpringApplication.run(Application .class, args);
}
}
我关于限制从特定端口访问 javamelody 的建议是扩展 javamelody 过滤器,如果请求来自特定端口则将请求链接起来,否则发回 404。
来自日志:
INFO TomcatEmbeddedServletContainer:185 - Tomcat started on port(s): 8800 (http) 8880 (http) 8881 (http)
顺便说一下,这种方法会暴露这些端口上的其他端点。
要解决此问题并将 javamelody 过滤器(/monitoring)限制到特定端口,您需要编写一个过滤器来验证从允许的端口请求的路径(servlet 和过滤器路径),请记住这些过滤器的顺序很重要。
基于这个答案和我在回答这个问题时已经可用的部分源代码,我在 http://tech.asimio.net/2016/12/15/Configuring-Tomcat-to-Listen-on-Multiple-ports-using-Spring-Boot.html
上发布了一篇关于这个主题的博客 post
您可以通过 MvcEndpoint 使用 ReportServlet。像这样:
import net.bull.javamelody.MonitoringFilter;
import net.bull.javamelody.ReportServlet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.Endpoint;
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.GetMapping;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* We configure the Java Melody {@link MonitoringFilter} normally, but disables all access to the UI. Instead,
* we create a {@link ReportServlet}, and expose it through a {@link MvcEndpoint} in {@link #javaMelodyReportEndpoint()}.
*/
@Configuration
public class JavaMelodyConfiguration {
private final ServletConfig servletConfig;
@Autowired
public JavaMelodyConfiguration(ServletConfig servletConfig) {
this.servletConfig = servletConfig;
}
@Bean
MvcEndpoint javaMelodyReportEndpoint() {
ReportServlet reportServlet = new ReportServlet();
// We initialize the servlet with the servlet configuration from the server that runs on server.port, as
// it currently only uses it to access the Collector instance, and some system information.
reportServlet.init(servletConfig);
return new MvcEndpoint() {
@Override
public String getPath() {
return "/monitoring";
}
@Override
public boolean isSensitive() {
return false;
}
@Override
public Class<? extends Endpoint> getEndpointType() {
return null;
}
@GetMapping
public void report(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws ServletException, IOException {
reportServlet.service(httpRequest, httpResponse);
}
};
}
@Bean
FilterRegistrationBean javaMelodyFilterRegistration() {
FilterRegistrationBean javaMelody = new FilterRegistrationBean();
javaMelody.setFilter(monitoringFilter());
javaMelody.setName("javamelody");
return javaMelody;
}
@Bean
MonitoringFilter monitoringFilter() {
return new MonitoringFilter() {
@Override
protected boolean isAllowed(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException {
// We allow no access to the report (/monitoring) from this filter, access is done through the
// MvcEndpoint above, using the management port.
return false;
}
};
}
}
(我也张贴在这里:https://github.com/javamelody/javamelody/issues/601)
如果目标是从java开始在管理端口上公开监控,melody 1.76版本现在就简单多了。
您需要 Spring 引导 2.x、执行器并在 yml 或属性文件中:
- management.server.port: {您的自定义端口}
- management.endpoints.web.exposure.include:{你平时想要什么},监控
- javamelody.management-启用端点监控:true
在此处查看更多详细信息:
https://github.com/javamelody/javamelody/wiki/SpringBootStarter#configuration-in-case-of-management-port
我有 Spring 引导 Web 应用程序。它在端口 8080 上公开 REST API。它还通过 Spring 引导管理端点 (http://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-monitoring.html) 公开管理端口 8081。
我没有任何自定义 Tomcat 配置来实现这一点。我的 application.properties
文件中只有 属性 management.port=8081
。
我按照中所述配置了 JavaMelody
https://github.com/javamelody/javamelody/wiki/UserGuideAdvanced#spring-boot-app
(我有我的自定义 JavaMelodyConfiguration
class,org.springframework.boot.web.servlet.FilterRegistrationBean
注册 net.bull.javamelody.MonitoringFilter
)。
@Bean
public FilterRegistrationBean javaMelody() {
final FilterRegistrationBean javaMelody = new FilterRegistrationBean();
javaMelody.setFilter(new MonitoringFilter());
javaMelody.setAsyncSupported(true);
javaMelody.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ASYNC);
javaMelody.addUrlPatterns("/*");
return javaMelody;
}
通过此配置,Javamelody 暴露在端口 8080(业务端口)上。我想把它移到 8081(管理端口)。如何改变?
我使用Spring Boot 1.4.2.RELEASE, javamelody 1.62.0
编辑:此答案仍然正确,但请参阅已接受的答案以获得更简单的解决方案。
EmbeddedTomcatConfiguration.java
package ...
import java.util.ArrayList;
import java.util.List;
import org.apache.catalina.connector.Connector;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class EmbeddedTomcatConfiguration {
@Value("${server.additionalPorts}")
private String additionalPorts;
@Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
Connector[] additionalConnectors = this.additionalConnector();
if (additionalConnectors != null && additionalConnectors.length > 0) {
tomcat.addAdditionalTomcatConnectors(additionalConnectors);
}
return tomcat;
}
private Connector[] additionalConnector() {
if (StringUtils.isBlank(this.additionalPorts)) {
return null;
}
String[] ports = this.additionalPorts.split(",");
List<Connector> result = new ArrayList<>();
for (String port : ports) {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setScheme("http");
connector.setPort(Integer.valueOf(port));
result.add(connector);
}
return result.toArray(new Connector[] {});
}
}
application.yml
server:
port: ${appPort:8800}
additionalPorts: 8880,8881
Application.java
@SpringBootApplication
@ComponentScan(...)
@Import(EmbeddedTomcatConfiguration.class)
public Application {
public static void main(String[] args) {
SpringApplication.run(Application .class, args);
}
}
我关于限制从特定端口访问 javamelody 的建议是扩展 javamelody 过滤器,如果请求来自特定端口则将请求链接起来,否则发回 404。
来自日志:
INFO TomcatEmbeddedServletContainer:185 - Tomcat started on port(s): 8800 (http) 8880 (http) 8881 (http)
顺便说一下,这种方法会暴露这些端口上的其他端点。 要解决此问题并将 javamelody 过滤器(/monitoring)限制到特定端口,您需要编写一个过滤器来验证从允许的端口请求的路径(servlet 和过滤器路径),请记住这些过滤器的顺序很重要。
基于这个答案和我在回答这个问题时已经可用的部分源代码,我在 http://tech.asimio.net/2016/12/15/Configuring-Tomcat-to-Listen-on-Multiple-ports-using-Spring-Boot.html
上发布了一篇关于这个主题的博客 post您可以通过 MvcEndpoint 使用 ReportServlet。像这样:
import net.bull.javamelody.MonitoringFilter;
import net.bull.javamelody.ReportServlet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.Endpoint;
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.GetMapping;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* We configure the Java Melody {@link MonitoringFilter} normally, but disables all access to the UI. Instead,
* we create a {@link ReportServlet}, and expose it through a {@link MvcEndpoint} in {@link #javaMelodyReportEndpoint()}.
*/
@Configuration
public class JavaMelodyConfiguration {
private final ServletConfig servletConfig;
@Autowired
public JavaMelodyConfiguration(ServletConfig servletConfig) {
this.servletConfig = servletConfig;
}
@Bean
MvcEndpoint javaMelodyReportEndpoint() {
ReportServlet reportServlet = new ReportServlet();
// We initialize the servlet with the servlet configuration from the server that runs on server.port, as
// it currently only uses it to access the Collector instance, and some system information.
reportServlet.init(servletConfig);
return new MvcEndpoint() {
@Override
public String getPath() {
return "/monitoring";
}
@Override
public boolean isSensitive() {
return false;
}
@Override
public Class<? extends Endpoint> getEndpointType() {
return null;
}
@GetMapping
public void report(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws ServletException, IOException {
reportServlet.service(httpRequest, httpResponse);
}
};
}
@Bean
FilterRegistrationBean javaMelodyFilterRegistration() {
FilterRegistrationBean javaMelody = new FilterRegistrationBean();
javaMelody.setFilter(monitoringFilter());
javaMelody.setName("javamelody");
return javaMelody;
}
@Bean
MonitoringFilter monitoringFilter() {
return new MonitoringFilter() {
@Override
protected boolean isAllowed(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException {
// We allow no access to the report (/monitoring) from this filter, access is done through the
// MvcEndpoint above, using the management port.
return false;
}
};
}
}
(我也张贴在这里:https://github.com/javamelody/javamelody/issues/601)
如果目标是从java开始在管理端口上公开监控,melody 1.76版本现在就简单多了。
您需要 Spring 引导 2.x、执行器并在 yml 或属性文件中:
- management.server.port: {您的自定义端口}
- management.endpoints.web.exposure.include:{你平时想要什么},监控
- javamelody.management-启用端点监控:true
在此处查看更多详细信息: https://github.com/javamelody/javamelody/wiki/SpringBootStarter#configuration-in-case-of-management-port