☰
SkyWalking中间件支持清单:Spring Cloud、Dubbo、RocketMQ与ShardingSphere链路追踪实践
2026/10/10 3:18:48 网站建设 项目流程

做微服务排查的人,应该都有过这种经历:接到一个“订单提交特别慢”的工单,打开监控平台想顺着链路找瓶颈,结果发现调用链在某个环节突然断了——前面还能看到 HTTP 入口、Feign 调用、Redis 查询,可一到消息发送或者分库分表的数据访问,就只剩孤零零的一截。这时候十有八九不是业务代码的问题,而是 APM 对那个中间件“不认识”。SkyWalking 作为目前使用率很高的开源应用性能监控系统,解决这个问题的核心,就是它那张“支持的中间件清单”。这篇文章我就围绕 Spring Cloud、Dubbo、RocketMQ、ShardingSphere 这几个高频组件,把 SkyWalking 的中间件支持范围、背后原理、接入验证和排坑经验一次性讲清楚。

选择 SkyWalking 的团队,绝大多数不是冲着 UI 有多炫,而是看中它的 Agent 能在一大堆中间件上自动埋点。这也就意味着,搞清楚“支持清单”比搞清楚告警规则更优先——清单决定了一条调用链能画多完整,也决定了你后续做拓扑分析、慢 SQL 定位、异常追踪时会不会出现盲区。下面我按“为什么需要重视清单—清单到底长什么样—重点中间件逐个拆解—原理实现—实操验证—问题排查”的顺序来写,新手可以照着跑一遍验证流程,老手也可以直接跳到第三、第六节看重点。

1. 为什么“支持哪些中间件”是选型的第一道门槛

1.1 链路中断是分布式监控里最常发生的事故

我见过不止一个团队在引入 APM 时踩同一个坑:光看官网首页截图觉得功能很全,装完 Agent 后才发现,自己项目里最关键的调用链“断”了。比如服务之间的调用走的是自研 RPC,或者消息队列用的是某个不太主流的客户端版本,这些场景往往没有对应插件。链路一旦断在半路,调用链图上就会出现断层:前半段的时间瀑布图是完整的,后半段只有一个黑盒 Span,耗时压在里面根本定位不到具体方法。

这里的关键点在于:一个 APM 能不能用,不是由 UI 功能决定的,而是由插件生态决定的。SkyWalking 的 Java Agent 之所以在这个问题上口碑不错,正是因为它把支持的中间件以“插件”的方式组织起来,形成了覆盖 HTTP、RPC、MQ、数据库、缓存、注册中心、网关等几大类别的长清单。链路追踪其实很像拼积木,每个插件负责在特定框架或客户端上“搭”一个 Span 出来,而你不希望调用链拼到一半突然缺了一块积木。

1.2 SkyWalking 的插件机制让支持清单具备可扩展性

讲支持清单之前,先有必要知道 SkyWalking 的插件是怎么工作的。Java Agent 本身不直接写死“每种中间件怎么埋点”,而是在启动时扫描 plugins 和 optional-plugins 目录下的所有插件 jar。每个插件通过字节码增强技术,在目标中间件客户端的关键方法(比如发请求、收响应、执行 SQL、发送消息)前后插入探针代码,自动创建和结束 Span,再透传 Trace ID。

这种机制带来两个直接影响:第一,业务代码可以保持零侵入,不用手动在方法上加注解或者埋点;第二,供给清单是动态的,你可以通过加插件 jar 的方式扩展支持范围,不一定要升级整个 Agent。哪怕某个中间件没有官方插件,理论上也能通过自定义插件、手动埋点、OpenTelemetry 接入等方式补上。所以,网络上经常有人截图贴“SkyWalking 支持中间件清单表”来讨论,其实那张表代表的只是一个“快照”,真正重要的是你理解这张表为什么长这样、每个格子背后对应哪个插件。

2. 最新支持清单总览:哪些中间件可以直接“插上就用”

2.1 一份可对照的中间件支持总表

先放一份按使用场景分类的总表。这张表不是从某个版本说明书里完整抄出来的,而是我把平时部署中验证过的组件归纳在一起,标注了插件归属(默认 plugins 直接生效,还是 optional-plugins 需要手动启用),方便你对照自己项目的技术栈。

分类常见中间件 / 框架插件归属使用备注
Web 与 HTTPTomcat、Jetty、Undertow、Servlet、Spring MVC、Spring Boot默认启用的插件绝大多数 Java Web 服务开箱即用
服务间调用Spring Cloud(Feign、RestTemplate)、Spring Cloud Gateway、Zuul默认启用 / OptionalGateway 的插件在某些版本需要单独拷贝
RPCDubbo、gRPC、Motan、SOFARPC默认启用Dubbo 3.x 与 2.x 的插件包不同
消息队列RocketMQ、Kafka、RabbitMQ、ActiveMQ默认启用 / OptionalRocketMQ 支持 4.x 与 5.x,注意版本匹配
数据库访问MySQL、PostgreSQL、Oracle、SQLServer、H2、SQLite、MariaDB默认启用通过 JDBC 层拦截 SQL 执行
分库分表ShardingSphere 以及 ShardingSphere-JDBC / Proxy默认启用 / OptionalJDBC 模式和 Proxy 模式的接入方式不一样
缓存Redis(Jedis、Lettuce、Redisson)、Memcached默认启用关注命令耗时与缓存穿透场景
搜索引擎Elasticsearch(TransportClient / RestClient)、OpenSearch默认启用 / Optional版本跨度大,插件需按客户端版本选
注册与配置Nacos、Zookeeper、Consul、Eureka、Apollo默认启用 / Optional主要用于服务发现阶段的 Span 显示
异步与并发CompletableFuture、线程池、Java 并发工具、TimerTask、Spring @AsyncOptional 居多跨线程链路传递建议重点检查
响应式Spring WebFlux、WebClient、Reactor 相关Optional / 较晚加入需要复制插件并关注响应式上下文传播

这张表的价值在于,你一眼就能发现自己技术栈里哪些组件是“不需要动手的”,哪些是“需要去 optional-plugins 里翻一翻的”。我自己的习惯是,每次新项目定技术选型时,先把表里列出的组件和版本对照一遍,再决定要不要为“灰区”组件准备替代方案。

2.2 如何快速判断手头的中间件是否被覆盖

遇到表里没写的组件,不用急着焦虑,可以按下面三步走。

第一步,看 Agent 解压后的 plugins 目录。目录下有大量命名规整的 jar,比如 apm-dubbo-xx.jar、apm-rocketmq-xx.jar、apm-shardingsphere-xx.jar,直接搜索关键词最快。第二步,看 optional-plugins 目录。有些插件因为可能影响性能或者依赖特殊版本,不会默认激活,而是放在 optional 下,需要手动复制到 plugins 目录。第三步,看官方文档。SkyWalking 的官方文档会按插件列出支持的版本范围,版本匹配度比“有没有插件”更重要。

这里有一个特别值得说的细节:判断“支持”不能只看插件包存在,还要看 Agent 版本和后端版本。插件一般跟着 Agent 大版本走,比如你用 9.x 的 Agent,就需要匹配同大版本的后端服务,否则上报数据可能因为协议版本不同而解析异常。实际项目里我见过不少“插件明明加载成功,UI 里却看不到链路”的案例,最后发现都是 Agent 与后端版本错配。

2.3 关于 WebFlux 与响应式场景的特别提醒

Spring Cloud 技术栈现在已经普遍迈向 Spring Boot 3.x 和 Spring WebFlux,监控在响应式场景下的支持相对敏感。SkyWalking 对 WebFlux、WebClient、Reactor 的支持是有的,但插件通常放在 optional-plugins 目录,需要根据版本手动启用。而且在响应式链路里,上下文传播方式与传统 ThreadLocal 模型差异很大,很多链路断层发生在订阅线程切换时,并不是插件不支持,而是 Agent 默认的传播机制在响应式调用链上需要配合额外配置。

这个点我建议使用 WebFlux 的团队做接入验证时单独测一条分钟级的全链路请求:从前端网关打到 WebFlux 服务,再通过 WebClient 调用下游,最后看链路图上是否完整。如果中途断掉,先确认 optional 插件是否已复制,再去官方文档核对 reactor 相关支持的版本要求。

3. 重点中间件逐个拆解:Spring Cloud、Dubbo、RocketMQ、ShardingSphere

3.1 Spring Cloud:从 Feign 到 Gateway 的完整调用链

Spring Cloud 之所以排在标题第一位,因为它是微服务落地时最主流的技术栈,也是 SkyWalking 插件支持最“饱满”的一块。在 Spring Cloud 体系里,调用链上的每一段几乎都有对应插件:服务接收方有 Spring MVC / Servlet 插件,服务调用方有 OpenFeign、RestTemplate、OkHttp、Apache HttpClient 插件,网关层有 Spring Cloud Gateway 和 Zuul 插件。这意味着从一个入口请求进来,经过网关、Feign 调用、下游服务处理,再到数据库访问,Span 都能被自动串联起来。

实际接入时要注意两点。第一,Feign 调用是否真的能形成跨服务链路,不仅取决于 Feign 插件,还取决于下游服务是否也挂了 SkyWalking Agent。只要有一端没挂,链路就会断在下游入口,现象是“上游能看到调用出口,下游看不到调用入口”。第二,Spring Cloud Gateway 的插件往往不在默认加载列表里。我遇到过网关链路在图谱上只有孤零零一个节点的情况,后来查日志发现是 gateway 插件没有被激活。把 optional-plugins 里的对应 jar 复制到 plugins 目录并重启服务后,拓扑图立刻恢复了完整的网关上下游关系。

3.2 Dubbo:跨进程与跨线程的链路上下文传递

Dubbo 是 RPC 场景里很典型的代表。SkyWalking 对 Dubbo 的支持分两个方向:消费端发出调用时,会把 TraceId 和 ParentSpanId 放进 Dubbo 的隐式传参里;提供端收到请求后,从隐式传参中取回上下文并创建新的 Span。所以只要两端都挂了 Agent,一次 Dubbo 调用的上下游关系是自动关联的,不需要改任何业务代码。

需要留神的细节是 Dubbo 版本差异。老项目常用 Dubbo 2.6/2.7,新项目可能直接用 3.x,不同版本在上下文传递机制上有变化,SkyWalking 针对不同大版本的插件命名不一样,使用前最好核对插件支持的版本范围。另外一个常见坑是异步泛化调用:很多团队用 Dubbo 的泛化调用做网关路由,但异步线程里如果不显式绑定上下文,Trace 会在异步边界断掉。解决思路有两个,一是确认线程池相关的可选插件已经被启用,二是在业务侧通过 ContextManager 手动把上下文传递到异步任务中。

3.3 RocketMQ:异步消息场景怎么保住一条链路

很多微服务到了中后期,都会把部分同步调用改成 RocketMQ 异步消息。这是业务上常见的改造,但对 APM 来说却是一次真正的考验:消息发送方给完 MQ 就返回了,消费者在另一个服务、另一个线程池里拉取消息继续处理,两段业务之间没有直接的 HTTP 或 RPC 调用,链路怎么连起来?

SkyWalking 的做法是在生产者发送消息时,把链路上下文写入消息的 properties;消费者消费消息时,从消息属性里取出上下文并重建 Span。所以只要生产者、消费者两端都接入 Agent,并且 RocketMQ 插件正常加载,“发送消息”和“消费处理”会出现在同一条 Trace 里。我在一个订单项目里实测过:用户下单后,订单服务发一条“创建订单成功”的消息给积分服务,积分服务消费后更新积分,整条链路在拓扑图上能从用户请求一路画到 Redis 写入,消息中间的那一段也能清楚看到耗时在哪。

操作上要注意两点:第一,如果消费者端的消费线程是自定义线程池,需要检查线程池相关插件是否启用,否则上下文在 submit 到 worker 线程时容易丢;第二,RocketMQ 客户端版本跨度较大,4.x 和 5.x 的 API 有差异,插件版本要与客户端版本适配,升级客户端时最好同步检查 Agent 插件版本。

3.4 ShardingSphere:分库分表下的 SQL 追踪

ShardingSphere 在标题里的出现,说明很多人已经开始关心“分库分表之后,监控能不能看到真实执行 SQL”这个问题。分库分表中间件会改写 SQL,比如一张订单表被拆到 8 个分片里,直接看数据库的慢查询日志只能看到物理库上的分片 SQL,很难对上业务侧的原始逻辑 SQL。SkyWalking 对 ShardingSphere 的插件正好解决了这个痛点:它能在 ShardingSphere 的路由改写层抓取逻辑 SQL 和实际路由后的物理 SQL,帮助你在监控图上看到 SQL 是从哪个服务发起、改写成哪些分片语句、每个分片的执行耗时。

ShardingSphere 有 JDBC 模式和 Proxy 模式,接入方式不太一样。JDBC 模式下,应用直接依赖 ShardingSphere-JDBC,SkyWalking 的 JDBC 相关插件可以通过拦截数据源操作拿到对 ShardingSphere 的执行链路;Proxy 模式下,应用先连到一个独立部署的数据库代理层,再转发到底层数据库,链路追踪要看这一跳在 SkyWalking 网关/数据库之间的呈现是否清晰。实际使用中,我建议同时看服务和数据库两端的 Span,才能判断“慢”到底是分片路由耗时,还是底层数据库耗时。

3.5 其他高频组件:MySQL、Redis、Kafka、ES、MongoDB

除了标题点名的四个组件,日常技术栈里还有几个出镜率极高的中间件,值得顺带说。

MySQL 属于最基础、也最让人放心的支持项。SkyWalking 通过 JDBC 层统一拦截,无论是 Spring Data、MyBatis 还是原生 JDBC,SQL 执行过程和耗时都能上链路。Redis 的 Jedis、Lettuce、Redisson 都有插件,连 Lua 脚本执行也能被追踪到。Kafka 的插件模式和 RocketMQ 类似,生产消费两端都传递上下文。Elasticsearch 的情况稍微特殊一点:它同时是数据库和搜索引擎,插件要跟客户端版本(TransportClient、RestClient 还是新客户端)匹配,用错了版本会出现“ES 调用不在链路里”的现象。MongoDB 的插件相对中规中矩,如果你用的驱动版本比较老,建议在测试环境先用一条真实查询验证一次。

4. “支持”背后是怎么实现的:从 Agent 到字节码增强

4.1 一个请求进来,插件到底做了什么

理解了清单,再往里走一层,我们要搞清楚“支持”这件事到底是谁在干活。以一次 MySQL 查询为例:应用代码调用 MyBatis 的 mapper 方法,最终会走 JDBC 驱动。SkyWalking 的 mysql 插件通过字节码增强,在 JDBC 的 Connection 创建、Statement 执行、ResultSet 获取等关键方法上做了拦截,把这些位置变成链路上的 Span。Span 记录的信息包括 SQL 语句、数据库实例、执行耗时、异常堆栈,UI 里看到的就是一条慢 SQL 明细。

这套机制的优点很明显:业务代码完全没有侵入,不需要在每个 Mapper 上面加工具方法,也不需要改 SQL。缺点是需要做字节码增强,对 Java 版本和框架版本比较敏感。字节码增强本身也是动态的,Agent 在应用启动时把增强逻辑注入到目标类的字节码中,如果你的框架升级后方法签名变了,旧插件就会失效。很多“升级完 Spring Boot 之后链路突然少了”的诡异现象,根因其实就在这。

4.2 上下文传播机制:ThreadLocal 与跨线程传递

链路上下文在单线程里传递比较简单,本质上是一个 ThreadLocal 变量,Span 开始、结束都围绕同一个线程。但现实业务里异步无处不在:线程池、消息队列、CompletableFuture、Spring @Async。每当执行线程从 A 切到 B,ThreadLocal 里的上下文就断了。SkyWalking 针对这个问题专门做了跨线程传递插件,原理是拦截线程池的提交方法,在创建新任务时把上下文快照传进去,在新线程中恢复。

这就是为什么前面反复强调 Optional 插件要检查:线程池插件、异步工具插件都属于可选加载项。如果你在自己的异步代码里发现 Trace 断成两截,先不要怀疑中间件没被支持,重点检查“异步插件是否已启用”和“是否用官方插件支持的线程池实现方式”。从实际操作角度讲,接入了 Agent 之后跑一个包含异步调用的测试用例,是验证这块最直接的手段。

4.3 关键配置项与目录结构

Java Agent 的目录结构虽然不算复杂,但有些配置项容易忽略。解压 Agent 压缩包后会看到 skywalking-agent.jar、config 目录、plugins 目录、optional-plugins 目录。启动应用时用 -javaagent 指定 skywalking-agent.jar 的路径即可,常见配置一般集中在 config/agent.config 文件或者启动参数里的 -Dskywalking.xxx=xxx。我个人最常用的几个配置项是 agent.service_name(服务名)、collector.backend_service(后端地址)、agent.namespace(用来区分多环境命名空间,比如测试环境与生产环境共用一套后端时避免串数据)。

另一个容易被忽略的是插件开关:并不是 plugins 目录里有多余 jar 就必须全部启用。对于不需要监控的某些中间件,保留插件反而会带来额外的增强开销和日志噪音。如果项目里没有用到某个组件,可以放心把对应插件 jar 移走,或者通过插件相关配置控制加载范围。这是一项非常实用的优化手段,尤其在高并发、对启动速度敏感的生产应用中,精简插件列表比无脑全量开启更合理。

5. 实操验证:让中间件清单在你的环境里真正生效

5.1 环境准备与 Agent 接入

接入 SkyWalking 的第一步是拿到 Java Agent 压缩包,把它放到统一目录,比如 /opt/skywalking,方便多应用复用。接着在应用的启动参数里加上 -javaagent,典型命令长这样:

java \ -javaagent:/opt/skywalking/skywalking-agent.jar \ -Dskywalking.agent.service_name=order-service \ -Dskywalking.collector.backend_service=10.0.0.8:11800 \ -jar order-service.jar

注意 -javaagent 必须放在主类或 jar 参数之前,如果顺序不对,应用可能不会加载 Agent。这里我用了一个示例内网地址 10.0.0.8:11800,实际部署时替换成你的后端 OAP 地址即可。端口 11800 是后端 gRPC 上报端口,如果你用了 HTTP 上报或者其他自定义端口,相应调整即可。

5.2 验证插件加载:用日志确认

Agent 接入成功后,应用启动日志里会出现 SkyWalking 相关的 banner 和插件加载信息。想快速确认某个中间件插件是否生效,可以直接在启动日志里搜索插件名。我自己通常会用类似下面的命令把日志过滤一下:

nohup java -javaagent:/opt/skywalking/skywalking-agent.jar \ -Dskywalking.agent.service_name=order-service \ -jar order-service.jar > app.log 2>&1 & grep -i "plugin" app.log | head -n 30

正常情况下你能看到 Dubbo、RocketMQ、ShardingSphere、MySQL 等插件被加载的日志条目。如果发现某个中间件插件不在加载列表里,先检查它是否在 optional-plugins 目录而没有复制到 plugins 目录。这是一个很常见、也很容易在代码 review 时被忽略的动作。

5.3 用一条 Spring Cloud + RocketMQ 链路做端到端验证

工具装好以后,最有说服力的验证是跑一条完整链路。我以一个简化版微服务场景举例:入口服务通过 Feign 调用订单服务,订单服务发一条 RocketMQ 消息,消费者服务(比如积分服务)收到消息后查询一次 MySQL。所有服务都接同一个 Agent 和同一个后端,然后在后端 UI 里查看拓扑图和 Trace 明细。

验证时有几个可观察的点:拓扑图应该显示入口服务、订单服务、RocketMQ、积分服务、MySQL 几个节点,节点之间连线清晰;点进任意一条 Trace,应该能看到 HTTP 入口、Feign 调用、消息发送、消息消费、SQL 执行等完整 Span 序列;如果一个节点缺失,基本可以断定是对应服务的插件没生效,或者服务没有正常上报数据。这套验证流程花费时间不长,但能把“支持清单”从纸面变成实打实的可用能力。

6. 常见问题与排查技巧实录

6.1 高频问题速查表

把我在实际使用中遇到的典型问题整理成一张速查表,方便你在出问题时按图索骥:

问题现象可能原因排查方法
服务在 UI 上只有一个节点,没有任何依赖边服务间调用关系没识别到,多半是某个中间件插件没生效检查该服务启动日志里的插件加载情况
Trace 在消息消费端断掉RocketMQ / Kafka 插件未加载,或消费端线程池插件未启用确认 MQ 插件在 plugins 目录,检查消费线程模型
Feign 调用的下游服务没有入口 Span下游服务没有接入 Agent,或者 Agent 与服务端版本不匹配确认下游服务启动参数和后端版本
网关链路缺失Spring Cloud Gateway / Zuul 插件在 optional-plugins 中未启用复制对应插件到 plugins 目录后重启
SQL 执行耗时看不到明细JDBC 插件未加载,或数据库用了非 JDBC 连接池检查插件与连接池版本,确认使用的访问方式
异步调用链路断裂线程池、CompletableFuture 等异步插件未启用启用 Optional 插件,重新验证异步场景
升级框架版本后链路消失插件版本与客户端版本不兼容回归测试,并核对官方文档中的版本兼容区间

这张表不一定覆盖所有怪问题,但能覆盖绝大多数“刚接入 APM 时最容易遇到”的情况。排查的大方向其实是一致的:先确认插件加载,再确认版本匹配,最后才怀疑后端解析问题。

6.2 真没有插件时怎么办:兼容手段清单

如果经过所有检查,某个自研框架、内部客户端或小众中间件确实没有现成插件,也别慌,有几条可行的路线可以尝试。

第一条路线是用 SkyWalking 提供的自定义增强插件(apm-customize-enhance-plugin),通过配置描述目标类和方法,实现轻量级埋点。这种方式不需要写 Java 代码,适合快速补点。第二条路线是在业务代码里调用 SkyWalking 的 OpenTracing 兼容 API 手动创建 Span,代码稍有侵入,但能在关键业务方法上保留精确的耗时和上下文。第三条路线是接入 OpenTelemetry 数据,较新版本的 SkyWalking 后端支持通过 OTLP 协议接收 OpenTelemetry 产生的 Trace 数据,这样可以借助 OTel 生态的丰富组件覆盖官方插件未覆盖的中间件。第四条路线是自己基于官方插件框架写一个自定义插件,适合有技术能力、愿意长期维护的团队。

这几条路线没有绝对的好坏,取决于你对“零侵入”的要求有多高,以及这个中间件在你的系统里有多关键。如果只是为了“图上不断链”,OpenTelemetry 接入是最省事的路径之一。

6.3 版本兼容性:最容易被忽略的坑

最后专门再说说版本兼容性。这是我在实际项目里踩过最多坑的地方,也是最容易在最终交付时被忽略的地方。SkyWalking 的 Java Agent、后端 OAP、前端 UI 之间通常保持同大版本组合才最稳。混用大版本可能表现为“Agent 显示上报成功,但 UI 没有数据”或“采样数据周期性地丢失”。

中间件客户端版本与插件版本的匹配同样敏感。比如 RocketMQ 客户端如果从 4.x 升到 5.x,你依然要验证消息消费端是否还能正确传递上下文;ShardingSphere 如果从旧版本往新版本升级,路由 SQL 的结构可能变化,插件拦截到的字段也可能变化。我的建议很简单:给每个中间件的“客户端版本—Agent 插件版本”组合做一次回归测试,并把验证结果记录在项目维护文档里,避免每次升级都靠猜。顺手提一个不算技巧的技巧:升级 Agent 或中间件客户端时,把升级前的链路截图留一份,升级后对比同一场景的 Trace 结构,哪里断了立刻就能看出来。

我在实际项目里最大的体会是,SkyWalking 的“支持清单”不是一份躺在官网上的静态表格,而是一套工程能力:选型前对照清单决定监控盲区,接入后通过日志和 UI 验证清单真实生效,升级前回归验证清单覆盖的中间件可用性。你把这三个环节都用起来,中间件支持这个问题才不会反复成为告警排查时的暗坑。希望这篇内容能帮你少走一些弯路。

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

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

立即咨询