SSH框架如何对接Webfunny Apm后端监控

一只会飞的鱼儿 1小时前 ⋅ 6 阅读
ad
前言:为什么需要全链路监控?
在分布式系统中,一个用户请求可能穿越 Struts2 控制器、Spring 服务、Hibernate 数据访问等多个层级,传统日志排查方式面临三大痛点:
  1. 故障定位难:无法快速追踪请求流经路径,问题排查耗时久(某银行案例显示,未接入 APM 时异常定位需 45 分钟);
  1. 性能瓶颈隐蔽:缺乏各组件耗时统计,难以识别慢 SQL、低效方法等瓶颈;
  1. 系统行为不透明:微服务调用链路复杂,无法直观掌握系统运行状态。
而 Webfunny APM 结合 OpenTelemetry 可完美解决这些问题 —— 无需大规模改造 SSH 老项目,即可实现零侵入 / 低侵入的全链路追踪。本文将详细拆解对接过程,从环境配置到验证落地,带你快速上手。

一、项目技术栈与对接核心方案

1. 基础技术栈(SSH 框架适配版)
层级
 
 
 
 
技术选型
 
 
 
 
版本
 
 
 
 
核心作用
 
 
 
 
Web 框架
 
 
 
 
Apache Struts2
 
 
 
 
6.3.0.2
 
 
 
 
MVC 控制器,接收 HTTP 请求
 
 
 
 
容器层
 
 
 
 
Spring Framework
 
 
 
 
5.3.27
 
 
 
 
依赖注入、事务管理
 
 
 
 
ORM 层
 
 
 
 
Hibernate
 
 
 
 
5.6.15.Final
 
 
 
 
数据持久化,生成 SQL 执行
 
 
 
 
数据库
 
 
 
 
H2 Database
 
 
 
 
2.2.224
 
 
 
 
开发 / 测试环境内存数据库(生产可替换为 MySQL)
 
 
 
 
构建工具
 
 
 
 
Maven
 
 
 
 
3.8+
 
 
 
 
依赖管理与项目构建
 
 
 
 
运行环境
 
 
 
 
Java
 
 
 
 
11
 
 
 
 
兼容 SSH 框架与 OpenTelemetry Agent
 
 
 
 
链路探针
 
 
 
 
OpenTelemetry Java Agent
 
 
 
 
2.22.0
 
 
 
 
自动采集链路数据,无需修改业务代码
 
 
 
 
 
 
 
 
 
2. 核心集成架构
采用「Agent 自动注入 + OTLP 协议上报」方案,整体链路如下:
用户请求 → OpenTelemetry Java Agent(自动采集)→ SSH 各层级(Struts2→Spring→Hibernate)→ 
OTLP Exporter → OpenTelemetry Collector → Webfunny APM 平台
关键优势
  • 零侵入:Agent 方式无需修改 SSH 业务代码,老项目快速适配;
  • 全覆盖:自动采集 HTTP 请求、SQL 执行、方法调用等核心数据;
  • 标准化:基于 OpenTelemetry 协议,支持后续对接其他 APM 平台(如 Elastic、Datadog)。

二、详细对接步骤(直接抄作业)

1. 第一步:添加 Maven 依赖
pom.xml 中引入 OpenTelemetry 核心依赖(用于注解增强和 API 调用):
<dependencies>
    <!-- OpenTelemetry API -->
    <dependency>
        <groupId>io.opentelemetry</groupId>
        <artifactId>opentelemetry-api</artifactId>
        <version>1.24.0</version>
    </dependency>
    
    <!-- OpenTelemetry 注解支持 -->
    <dependency>
        <groupId>io.opentelemetry.instrumentation</groupId>
        <artifactId>opentelemetry-instrumentation-annotations</artifactId>
        <version>1.24.0</version>
    </dependency>
</dependencies>
2. 第二步:配置 OpenTelemetry Java Agent
2.1 下载 Agent 包
OpenTelemetry 官网 下载 opentelemetry-javaagent.jar(版本 2.22.0),放置在服务器目录(如 /opt/otel/)。
2.2 编写启动脚本(关键配置)
创建 start-with-otel.sh 启动脚本,整合 Agent 配置与应用启动命令(适配 Jetty/Tomcat 容器):
#!/bin/bash

# ====================== OpenTelemetry 核心配置 ======================
# 服务名称(Webfunny 平台显示用)
OTEL_SERVICE_NAME="Pro-sshDemo"
# 资源属性(环境标识、实例ID,便于多环境区分)
OTEL_RESOURCE_ATTRIBUTES="deployment.environment=production,service.instance.id=ssh-app-01,service.version=2.0"
# Webfunny OTLP 上报端点(注意:原文档中 http://staging.webfunny.cn:9013 若解析失败,需检查网络连通性)
OTEL_EXPORTER_OTLP_ENDPOINT="http://staging.webfunny.cn:9013"
# 传输协议(GRPC 性能更优,若报错可改为 http/protobuf)
OTEL_EXPORTER_OTLP_PROTOCOL="grpc"
# 超时时间
OTEL_EXPORTER_OTLP_TIMEOUT="10s"
# 仅开启 Trace 采集(Metrics/Logs 按需启用)
OTEL_TRACES_EXPORTER="otlp"
OTEL_METRICS_EXPORTER="none"
OTEL_LOGS_EXPORTER="none"
# 全局方法扫描(无需注解,自动采集指定包下所有方法)
OTEL_INSTRUMENTATION_METHODS_INCLUDE="com.yourapp.service.*,com.yourapp.action.*,com.yourapp.dao.*"
# 排除工具类/配置类(减少冗余 Span)
OTEL_INSTRUMENTATION_METHODS_EXCLUDE="com.yourapp.util.*,com.yourapp.config.*"

# ====================== 应用启动配置 ======================
# Agent 路径(替换为你的实际路径)
OTEL_AGENT_JAR="/opt/otel/opentelemetry-javaagent.jar"
# 端口配置(避免冲突)
JETTY_PORT=8080

# 整合启动参数
export MAVEN_OPTS="\
-javaagent:$OTEL_AGENT_JAR \
-Dotel.service.name=$OTEL_SERVICE_NAME \
-Dotel.resource.attributes=$OTEL_RESOURCE_ATTRIBUTES \
-Dotel.exporter.otlp.endpoint=$OTEL_EXPORTER_OTLP_ENDPOINT \
-Dotel.exporter.otlp.protocol=$OTEL_EXPORTER_OTLP_PROTOCOL \
-Dotel.exporter.otlp.timeout=$OTEL_EXPORTER_OTLP_TIMEOUT \
-Dotel.traces.exporter=$OTEL_TRACES_EXPORTER \
-Dotel.metrics.exporter=$OTEL_METRICS_EXPORTER \
-Dotel.logs.exporter=$OTEL_LOGS_EXPORTER \
-Dotel.instrumentation.methods.include=$OTEL_INSTRUMENTATION_METHODS_INCLUDE \
-Dotel.instrumentation.methods.exclude=$OTEL_INSTRUMENTATION_METHODS_EXCLUDE"

# 启动 Jetty 容器(若用 Tomcat,替换为 catalina.sh start)
mvn jetty:run -Djetty.http.port=$JETTY_PORT

 

3. 第三步:链路增强(注解 / 全局扫描二选一)
方案 A:@WithSpan 注解(精准控制,生产推荐)
在关键业务方法上添加注解,自定义 Span 名称和类型,适用于核心链路监控:
// Struts2 Action 层(Controller)
@Action("/userList")
public class UserAction {
    @WithSpan(value = "UserAction.listUsers", kind = SpanKind.SERVER)
    public String list() {
        // 业务逻辑...
        userService.getAllUsers();
        return SUCCESS;
    }
}

// Spring Service 层
@Service
public class UserServiceImpl implements UserService {
    @WithSpan(value = "UserService.queryAllUsers", kind = SpanKind.INTERNAL)
    @Override
    public List() {
        return userDao.findAll();
    }
}

// Hibernate DAO 层
@Repository
public class UserDaoImpl implements UserDao {
    @WithSpan(value = "UserDao.findUserList", kind = SpanKind.INTERNAL)
    @Override
    public List findAll() {
        return sessionFactory.getCurrentSession().createQuery("from User").list();
    }
}

 

方案 B:全局方法扫描(零代码,测试 / 快速验证)
通过启动脚本中的 OTEL_INSTRUMENTATION_METHODS_INCLUDE 配置,自动采集指定包下所有方法,无需添加注解,适合快速验证全链路。
两种方案对比
方式
 
 
 
 
适用场景
 
 
 
 
优点
 
 
 
 
缺点
 
 
 
 
@WithSpan 注解
 
 
 
 
生产环境、核心链路
 
 
 
 
性能优、Span 命名清晰
 
 
 
 
需少量代码修改
 
 
 
 
全局方法扫描
 
 
 
 
开发 / 测试、快速验证
 
 
 
 
零代码、覆盖全面
 
 
 
 
可能产生冗余 Span
 
 
 
 
 
 
 
 
 

三、验证与问题排查

1. 本地验证三步法
① 启动应用
# 赋予脚本执行权限
chmod +x start-with-otel.sh
# 启动应用
./start-with-otel.sh

 

② 发送测试请求
curl http://localhost:8080/userList

③ 验证结果
  • 查看应用日志,若输出以下内容说明采集成功:
[otel.javaagent] LoggingSpanExporter - 'GET /userList' : traceId=xxx spanId=xxx SERVER
[otel.javaagent] LoggingSpanExporter - 'UserAction.listUsers' : traceId=xxx spanId=xxx INTERNAL
[otel.javaagent] LoggingSpanExporter - 'UserService.queryAllUsers' : traceId=xxx spanId=xxx INTERNAL
[otel.javaagent] LoggingSpanExporter - 'SELECT * FROM user' : traceId=xxx spanId=xxx CLIENT

 

  • 登录 Webfunny APM 平台,在「链路追踪」模块查看完整调用链。

2. 常见问题排查(避坑指南)
问题现象
 
 
 
 
高频原因
 
 
 
 
解决方案
 
 
 
 
无 Trace 日志输出
 
 
 
 
Agent 未加载成功
 
 
 
 
1. 检查 -javaagent 路径是否正确;2. 确保 JDK 版本 ≥ 8;3. 避免多个 Agent 冲突(如 SkyWalking、Arthas)
 
 
 
 
有日志但 Webfunny 无数据
 
 
 
 
OTLP 端点不通
 
 
 
 
1. 用 nc -zv staging.webfunny.cn 9013 测试网络连通性;2. 若 GRPC 协议报错,改为 OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
 
 
 
 
方法扫描未生效
 
 
 
 
包名配置错误
 
 
 
 
1. 包名不要加 java. 前缀;2. 多包用逗号分隔,如 com.yourapp.service.*,com.yourapp.action.*
 
 
 
 
SQL 语句未采集
 
 
 
 
Hibernate 版本不兼容
 
 
 
 
确保 Hibernate 版本 ≥ 3.3,Agent 2.22.0 原生支持 3.3+ 版本
 
 
 
 
性能下降明显
 
 
 
 
采样率过高
 
 
 
 
添加采样率配置:-Dotel.traces.sampler=parentbased_traceidratio -Dotel.traces.sampler.arg=0.3(30% 采样率)
 
 
 
 
 
 
 

四、最佳实践与性能优化

1. 采样策略优化
链路追踪会产生一定数据量,合理配置采样率平衡监控效果与性能:
  • 开发 / 测试环境:全采样(-Dotel.traces.sampler=always_on);
  • 生产环境:概率采样(如 30% 采样率)或自适应采样,避免高并发场景下的性能开销。
2. 链路粒度控制
  • 核心链路(支付、下单):用 @WithSpan 注解精准采集,保留完整细节;
  • 非核心链路(查询、统计):通过全局扫描排除,或降低采样率;
  • 排除工具类、循环调用方法,减少冗余 Span。
3. 资源属性规范
务必配置 deployment.environment(环境)和 service.instance.id(实例 ID),便于在 Webfunny 中区分生产 / 测试环境、不同服务器实例,快速定位问题节点。
4. 冷数据处理
Webfunny 支持链路数据归档,可在平台配置 TTL 策略(如 30 天),避免存储资源浪费,降低运维成本。

五、总结

SSH 框架集成 Webfunny APM 的核心优势在于「低侵入、高覆盖」—— 通过 OpenTelemetry Java Agent 实现零代码全链路采集,配合 @WithSpan 注解精准控制粒度,完美适配老项目改造需求。对接后可实现:
  1. 故障定位效率提升 80%:从 45 分钟缩短至分钟级;
  1. 全链路可视化:直观查看 HTTP→Action→Service→DAO→DB 的完整调用链;
  1. 性能瓶颈量化:精准识别慢 SQL、低效方法,为优化提供数据支撑。
如果你的项目是 SSH 架构,且面临故障排查难、性能优化无方向的问题,不妨按照本文步骤对接 Webfunny APM,让分布式系统的运行状态一目了然。

关于Webfunny

Webfunny专注于前端监控系统,前端埋点系统的研发。 致力于帮助开发者快速定位问题,帮助企业用数据驱动业务,实现业务数据的快速增长。支持H5/Web/PC前端、微信小程序、支付宝小程序、UniApp和Taro等跨平台框架。实时监控前端网页、前端数据分析、错误统计分析监控和BUG预警,第一时间报警,快速修复BUG!支持私有化部署,Docker容器化部署,可支持千万级PV的日活量!

  点赞 0   收藏 0
  • 一只会飞的鱼儿
    共发布70篇文章 获得8个收藏
全部评论: 0