如何在Spring Boot中过滤Tomcat访问日志中的TCP请求?
过滤Tomcat访问日志中的非HTTP请求(如HAProxy健康检查)
你的Servlet Filter仅对合法HTTP请求生效,而HAProxy那种返回400的健康检查请求属于不符合HTTP规范的TCP请求——这类请求在Tomcat走到Servlet Filter阶段前就被处理了,因此需要从Tomcat的访问日志核心组件层面解决。
以下是两种可行方案:
方案一:自定义AccessLogValve拦截日志记录
Tomcat的AccessLogValve是生成访问日志的核心组件,我们可以通过继承它并重写日志逻辑,实现特定请求的过滤。
1. 自定义AccessLogValve
import org.apache.catalina.valves.AccessLogValve; import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; public class FilteredAccessLogValve extends AccessLogValve { @Override protected void log(Request request, Response response, long time) { // 过滤掉请求URI为"-"且状态码为400的请求(对应HAProxy健康检查日志) String requestUri = request.getRequestURI(); int statusCode = response.getStatus(); if ("-".equals(requestUri) && statusCode == 400) { return; // 跳过记录该日志 } // 正常请求继续执行原有日志逻辑 super.log(request, response, time); } }
2. 在Spring Boot中替换默认Valve
通过WebServerFactoryCustomizer配置Tomcat,替换默认的AccessLogValve为自定义实现:
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; import org.springframework.stereotype.Component; import org.apache.catalina.valves.AccessLogValve; @Component public class TomcatAccessLogCustomizer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> { @Override public void customize(TomcatServletWebServerFactory factory) { // 移除默认的AccessLogValve factory.getEngineValves().removeIf(valve -> valve instanceof AccessLogValve); // 添加自定义Valve并配置原有日志参数 FilteredAccessLogValve customValve = new FilteredAccessLogValve(); customValve.setDirectory("logs"); customValve.setPrefix("localhost_access_log"); customValve.setSuffix(".txt"); customValve.setPattern("%h %l %u %t \"%r\" %s %b"); // 保持原有日志格式 factory.addEngineValves(customValve); } }
方案二:利用Tomcat AccessLogValve的条件过滤
如果不想自定义类,可直接通过配置condition属性,基于请求属性过滤日志。在Spring Boot配置文件中添加:
application.properties
server.tomcat.accesslog.enabled=true server.tomcat.accesslog.directory=logs server.tomcat.accesslog.prefix=localhost_access_log server.tomcat.accesslog.suffix=.txt server.tomcat.accesslog.pattern=%h %l %u %t \"%r\" %s %b # 排除状态码400且请求URI为"-"的请求 server.tomcat.accesslog.condition=not (statusCode == 400 and requestURI == '-')
说明
- 该方式依赖Tomcat的EL表达式支持,
condition属性允许通过表达式判断是否记录日志。 - HAProxy健康检查请求会被Tomcat标记为请求URI="-"、状态码400,正好匹配上述过滤条件。
注意:两种方案均适配Tomcat 10.1.18版本,方案一中
AccessLogValve.log方法为protected权限,可直接重写。
内容的提问来源于stack exchange,提问作者rmf
相关产品推荐
相关产品推荐

