Pinpoint Undertow 插件接入指南:配置项详解与请求追踪原理
2026/9/23 9:44:31 网站建设 项目流程

Pinpoint Undertow 插件接入指南:配置项详解与请求追踪原理

【免费下载链接】pinpointAPM, (Application Performance Management) tool for large-scale distributed systems.项目地址: https://gitcode.com/gh_mirrors/pi/pinpoint

本指南围绕 Pinpoint 官方 Undertow 插件(agent-module/plugins/undertow)展开,说明如何在 Spring Boot 内嵌 Undertow 或 WildFly 应用服务器场景下开启 Undertow 的请求追踪能力,逐项解释pinpoint.config中的全部配置参数,并结合插件源码剖析其基于Connectors.executeRootHandler入口插桩的追踪原理。读完本文,你将能够独立完成 Undertow 应用的 Pinpoint 接入、按需调优追踪参数,并理解请求参数、真实 IP、Header 过滤等功能在源码层面的实现方式。

插件概览:支持范围与适用场景

Undertow 插件是 Pinpoint 服务端(Web Server)类型插件,用于对基于 Undertow 构建的 HTTP 服务进行入口级(Entry Point)追踪。官方文档给出以下关键信息:

  • 引入版本:Since Pinpoint 1.8.0
  • 支持范围io.undertow/undertow-core [2.0.0.Final, 2.0.16.Final],即2.0.0.Final <= x <= 2.0.16.Final
  • 适用 Web Server:Spring Boot starter(内嵌 Undertow)与 WildFly Application Server

从 pom.xml 可以看到插件的依赖设计:undertow-corejavax.servlet-api均为provided作用域(由目标应用提供,插件自身不打包),pinpoint-bootstrap-core提供插桩 API,pinpoint-common-servletcompile作用域引入并在打包阶段被 maven-shade-plugin 重新定位(relocation)到com.navercorp.pinpoint.plugin.undertow.common.servlet命名空间,避免与目标应用中的 Servlet 类冲突。

插件通过UndertowConstants注册了两个服务类型:

  • UNDERTOW(ServiceType 1120,带RECORD_STATISTICS属性):用于统计与 Server Map 展示
  • UNDERTOW_METHOD(ServiceType 1121):用于方法级调用栈记录

两者由 UndertowTypeProvider.java 在 Trace 元数据初始化阶段注册。

快速启用:pinpoint.config 配置

Undertow 插件默认随 agent 分发,无需额外下载插件 jar。启用与调优均通过 agent 的pinpoint.config配置文件完成。官方文档给出的完整配置块如下:

# 总开关,默认启用 profiler.undertow.enable=true # Since pinpoint-1.8.2 # Servlet 部署模式支持(如 Spring Boot Undertow、Wildfly) # 如果是被 bootstrap 方式引导的 Undertow,请设为 false profiler.undertow.deploy.servlet=true # 是否追踪请求参数,默认值为 true profiler.undertow.tracerequestparam=true # 隐藏 Pinpoint 相关的请求头 profiler.undertow.hidepinpointheader=true # 需要排除追踪的 URL,支持 Ant 风格模式,如 /aa/*.html、/??/exclude.html profiler.undertow.excludeurl= # 需要排除追踪的 HTTP 请求方法 #profiler.undertow.excludemethod= # 原始 IP 地址请求头(如经过反向代理时获取真实客户端 IP) #profiler.undertow.realipheader=X-Forwarded-For # nginx 真实 IP 请求头 #profiler.undertow.realipheader=X-Real-IP # 可选参数:当请求头值为 ${profiler.undertow.realipemptyvalue} 指定的值时,忽略该请求头值 #profiler.undertow.realipemptyvalue=unknown

将上述内容写入pinpoint.config并重启应用后,Undertow 插件即生效。profiler.undertow.enable=false可整体关闭插件——在 UndertowPlugin.java 的setup()中,插件启动时会读取该配置,若为false则直接返回,不注册任何类转换。

配置参数详解

参数默认值说明
profiler.undertow.enabletrue插件总开关
profiler.undertow.deploy.servlettrueServlet 部署模式支持(Spring Boot Undertow / WildFly);bootstrap 引导的 Undertow 建议设为false
profiler.undertow.tracerequestparamtrue是否在调用栈中记录请求参数(query string)
profiler.undertow.hidepinpointheadertrue是否在转发请求前移除 Pinpoint 私有请求头,防止追踪上下文泄露给下游
profiler.undertow.excludeurl排除追踪的 URL,支持 Ant 风格模式,如/aa/*.html/??/exclude.html
profiler.undertow.excludemethod不记录参数的 HTTP 方法(如POST),详见下方源码说明
profiler.undertow.realipheader真实客户端 IP 请求头名称,如X-Forwarded-ForX-Real-IP
profiler.undertow.realipemptyvalue可选;当realipheader对应请求头的值等于该值时,忽略该值(不采用)

以上参数与 UndertowConfig.java 的读取逻辑一一对应。此外,源码中还暴露了两个官方文档未列出的进阶参数:

  • profiler.undertow.bootstrap.main:通过config.readList(...)读取,用于声明 bootstrap 主类列表(与deploy.servlet=false的引导场景配合);
  • profiler.undertow.http-handler.class.name:HTTP Handler 类名过滤。默认值为空时插件对所有HttpHandler生效;配置后按ExcludePathFilter语义(以.为分隔、,分隔多个类名)匹配,用于只追踪特定 Handler 实现。

值得注意的是,hidepinpointheadertracerequestparamexcludeurlexcludemethodrealipheaderrealipemptyvalue六项并非插件独有,而是通过公共的ServerConfig统一读取(见 UndertowConfig.java),因此它们的读取语义与其他 Web 容器插件(Tomcat、Jetty 等)完全一致,便于在多容器混合部署时保持配置习惯统一。

工作原理:从入口插桩到请求追踪

入口点插桩

Undertow 每次 HTTP 请求都会经由io.undertow.server.Connectors.executeRootHandler(HttpHandler, HttpServerExchange)分发到根处理器。插件在 UndertowPlugin.java 中对io.undertow.server.Connectors类执行字节码转换(transform),找到executeRootHandler方法并挂载ConnectorsExecuteRootHandlerInterceptor拦截器。选择该方法作为入口点的原因在于它同时持有HttpHandler(处理器)与HttpServerExchange(一次请求-响应交换的完整上下文),是采集请求信息的天然锚点。

请求/响应事件监听

ConnectorsExecuteRootHandlerInterceptor.java 是插件的核心逻辑,它在构造时组装了两套监听器:

  • ServletRequestListener<HttpServerExchange>:负责开启/关闭 Trace 块(TraceBlock)、记录 RPC 名称、方法、端点、远端地址、状态码、HTTP 状态码错误、请求头/ Cookie 记录等;
  • ServletResponseListener<HttpServerExchange>:负责响应侧的状态码采集与 Trace 块收尾。

before()中,先通过Validator校验参数(第一个参数必须是HttpHandler实例、第二个参数必须是HttpServerExchange,并应用http-handler.class.name过滤),随后依次触发请求监听器初始化、响应监听器初始化(注释明确说明必须在请求监听器之后,以保证 TraceBlock 先开启),最后执行UndertowHttpHeaderFilter.filter()移除 Pinpoint 私有请求头。在after()中则按相反顺序销毁响应监听器与请求监听器,并调用HttpServerExchange.getStatusCode()获取 HTTP 状态码。

请求信息采集适配

插件通过 HttpServerExchangeAdaptor.java 将 Undertow 的HttpServerExchange适配为 Pinpoint 统一的RequestAdaptor接口,映射关系如下:

Pinpoint 字段数据来源
RPC 名称HttpServerExchange.getRequestURI()
方法名HttpServerExchange.getRequestMethod()
EndPointgetDestinationAddress()(host:port)
远端地址getSourceAddress()(客户端 socket 地址)
请求头getRequestHeaders(),取peekFirst()

请求参数追踪与截断策略

profiler.undertow.tracerequestparam=true时,插件通过 ParameterRecorderFactory.java 创建参数记录器:

  • 参数提取器为HttpServerExchangeParameterExtractor,其构造参数为eachLimit=64totalLimit=512,即单个 key/value 最长截断 64 字符、整体参数字符串超过 512 字符后以...截断,避免超长 query string 撑爆 Trace 数据(见 HttpServerExchangeParameterExtractor.java);
  • 提取结果来自HttpServerExchange.getQueryParameters()(query string 解析后的 key 到多值队列的映射);
  • MethodFilterExtractor会先按excludemethod过滤 HTTP 方法,被排除的方法不记录参数;
  • tracerequestparam=false,则直接使用DisableParameterRecorder,完全不采集参数。

这套「总长限制 + 单项限制 + 方法过滤」的组合,保证了高并发生产环境下的数据体积可控。

隐藏 Pinpoint 请求头

UndertowHttpHeaderFilter.java 实现了hidepinpointheader的语义:当配置为true时,遍历HttpServerExchange.getRequestHeaders()的全部请求头名称,凡是以 Pinpoint 私有头前缀(Header.startWithPinpointHeader,如Pinpoint-*追踪上下文头)命名的,一律从HeaderMap中移除。该机制防止 Pinpoint 的追踪上下文(TraceId、SpanId 等)经 Undertow 应用透传或回传,避免下游应用误建跨系统追踪链或造成上下文污染。

Real IP 支持

当应用部署在反向代理(Nginx 等)之后时,HttpServerExchange.getSourceAddress()拿到的是代理地址而非客户端真实 IP。此时可通过:

profiler.undertow.realipheader=X-Forwarded-For

指定真实 IP 请求头;若同时设置realipemptyvalue=unknown,则当请求头值恰好为unknown(或你指定的哨兵值)时,插件会忽略该头,回退到 socket 地址。该能力由ServletRequestListenerBuilder.setRealIpSupport(config.getRealIpHeader(), config.getRealIpEmptyValue())注入(见 ConnectorsExecuteRootHandlerInterceptor.java),保证 Server Map 与调用栈中的远端地址是真实客户端。

测试与验证

仓库在 undertow-plugin-testweb 提供了配套的测试 Web 应用,其pom.xml引入undertow-coreundertow-servletundertow-websockets-jsr(版本 2.2.17.Final),启动类为 UndertowPluginTestStarter.java,可直接作为接入验证的最小样例:以带 agent 的方式启动该应用并发起 HTTP 请求,即可在 Pinpoint Web 的 Server Map 中看到UNDERTOW节点,在调用栈中看到UNDERTOW_METHOD级别的请求记录。

注意事项

  • 版本边界:官方声明支持undertow-core [2.0.0.Final, 2.0.16.Final]。测试应用使用 2.2.17.Final 仅用于集成验证;生产环境若使用超出声明范围的版本,建议先在测试环境验证字节码转换兼容性。
  • 部署模式:Spring Boot 内嵌 Undertow 与 WildFly 属于 Servlet 部署模式,保持profiler.undertow.deploy.servlet=true;若你的应用以编程方式(bootstrap)直接组装 Undertow(例如纯非 Servlet 的 HTTP 服务),应将其设为false,并结合bootstrap.mainhttp-handler.class.name做精细化控制。
  • 与 Servlet 插件的协同:由于插件 shade 了pinpoint-common-servlet,且依赖javax.servlet-api(provided),在 WildFly 等 Servlet 容器内,Undertow 插件负责入口采集,容器内的 Servlet 插件继续负责更深层 Servlet 调用链,两者互不冲突。

综上,Undertow 插件是一个典型的「入口插桩 + 统一 Request/Response 监听」型 Web 容器插件:通过Connectors.executeRootHandler单点插桩覆盖全部请求,再以可配置的开关、过滤器与截断策略平衡追踪深度与数据开销。参考本指南完成 agent-module/plugins/undertow/README.md 中的配置即可快速接入,深入 agent-module/plugins/undertow 源码可进一步理解每个参数背后的实现细节。

【免费下载链接】pinpointAPM, (Application Performance Management) tool for large-scale distributed systems.项目地址: https://gitcode.com/gh_mirrors/pi/pinpoint

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询