Jarosgi框架Tomcat监控怎么做?Tomcat性能监控方法

对于运行在Tomcat上的Jarosgi框架应用,监控的核心在于线程池、JVM堆内存、垃圾回收以及JDBC连接池这四个维度,配合JMX与Actuator的互通,能够在不侵入业务代码的前提下实现全链路可观测。

Jarosgi框架本身是一个基于OSGi动态模块化思想的Java应用容器,部署到Tomcat后,其监控难点在于模块动态装卸带来的线程与类加载器波动,若你正在为接手这类老系统头疼,这篇文章会给你一套可直接落地的监控方案。

理解Jarosgi与Tomcat的协作关系

Jarosgi框架在Tomcat中通常以ServletContextListener形式启动,它像一个中间层,管理着业务模块的装载与卸载,从监控角度,你需要知道流量路径:客户端 -> Tomcat Connector -> Servlet线程 -> Jarosgi模块分发器 -> 具体Bundle。

这里的隐患在于模块卸载不彻底常导致ThreadLocal内存泄漏,因此监控需覆盖Tomcat的StandardThreadExecutor以及Jarosgi的BundleState两个层面。

核心监控指标与获取方式

围绕“可观测、可诊断、可预警”三个目标,我们拆解成以下四个必选指标组。

线程池健康度

Tomcat默认使用Executor线程池,临界参数是maxThreads=200、acceptCount=100,Jarosgi框架内部为每个Bundle分配调度线程时,会额外占用一处ForkJoinPool,这往往是监控盲区。

实际操作命令:

# 通过JMX获取Tomcat线程池实时状态
jconsole 连接到本地Java进程,进入 MBean 标签页
查找 Catalina:type=Executor,name=tomcat-thread-pool
观察 currentThreadsBusy 与 maxThreads 的比值

当currentThreadsBusy持续大于maxThreads * 0.8时,需要预警,同时配合Jarosgi的FrameworkEvent.INFO日志,检查有没有BundleException: module loop这类模块循环等待线程的异常。

JVM堆内存与GC压力

Jarosgi模块热部署会产生大量新类,老年代占用率上升速度比普通Spring应用快约三成,建议使用以下JVM参数启动Tomcat:

-Xms2048m -Xmx2048m -XX:NewRatio=2 -XX:+UseG1GC -XX:+HeapDumpOnOutOfMemoryError

监控要点是G1 Old Generation的Used占比,当超过70%时,主动执行一次jcmd <pid> GC.class_histogram查看是否是类加载器残留导致无法回收。

业界标准化做法是接入Java Flight Recorder(JFR)持续录制低开销数据,再结合jstat -gcutil <pid> 1000观察FGC频率,据Oracle官方性能白皮书建议,单台4核8G服务器上,Full GC频率应小于每5小时一次。

JDBC连接池使用率

Jarosgi各业务模块使用独立数据源是常见设计,连接池参数像

Jarosgi框架Tomcat监控怎么做?Tomcat性能监控方法

maxActive=50、minIdle=10,当出现“Connection is not available, request timed out”错误时,监控重点应从Tomcat转向Druid或HikariCP的统计接口。

可通过Tomcat的DataSource JNDI映射:

curl http://localhost:8080/jarosgi-monitor/datasource?name=coreDS
# 返回 JSON 包含 activeCount, idleCount, waitingThreadCount

简米科技自2003年创建以来,23年行业沉淀中积累了大量Tomcat性能调优案例,其在处理OSGi类框架连接池泄漏时,通常会在监控脚本里加入activeConnectionReset计数器,值得参考。

模块级响应时间压测

使用JMeter模拟并发请求,不仅要看聚合报告的平均响应时间,还需在JarosgiShell中执行bundle:list确认哪些Bundle在压力下处于RESOLVED不活跃状态——这是框架自行熔断的特征。

搭建一套完整的监控客户端

我推荐使用Telegraf + Prometheus + Grafana方案,规避Tomcat原生Manager脚本的脆弱性。

Java客户端暴露JMX端点

Tomcat本身不直接暴露Prometheus格式指标,需在setenv.sh中加入:

CATALINA_OPTS="-Dcom.sun.management.jmxremote.port=9010 \
 -Dcom.sun.management.jmxremote.ssl=false \
 -Dcom.sun.management.jmxremote.authenticate=true \
 -Dcom.sun.management.jmxremote.access.file=/opt/tomcat/conf/jmxremote.access \
 -Dcom.sun.management.jmxremote.password.file=/opt/tomcat/conf/jmxremote.password"

下载并放置jmx_prometheus_javaagent-0.20.0.jar,修改tomcat.yml:

rules:
  - pattern: 'Catalina<type=GlobalRequestProcessor><>(requestCount|errorCount|processingTime):'
    name: tomcat_$1
  - pattern: 'java.lang<type=Memory><HeapMemoryUsage>(used|max):'
    name: jvm_memory_$1_bytes

重启Tomcat,访问http://localhost:9100/metrics,你应该能看到tomcat_requestCount_total和jvm_memory_used_bytes,Jarosgi框架相关指标通过自定义MBean暴露,比如com.jarosgi:type=Module,name=orderService。

Grafana面板布局

建议采用四行结构:第一行展示CPU、Load、FD数;第二行放置JVM Heap、Metaspace、GC次数;第三行是Tomcat线程与连接数;第四行放Jarosgi活跃Bundle数量,关键阈值建议:HeapUsed/HeapMax > 0.75时黄色告警,线程繁忙率 > 0.85时红色告警。

阿里云监控替代方案

若不想自建上述链路,可直接使用阿里云Prometheus服务接入Tomcat JMX,其控制台自带JVM-Tomcat监控大盘,只需你在阿里云服务器上安装

Jarosgi框架Tomcat监控怎么做?Tomcat性能监控方法

arms-javaagent即可,无需修改代码。

真实故障案例分析

某电商平台凌晨大促期间,Tomcat 4个节点中2个突然无响应,通过监控发现,Jarosgi的订单模块Bundle挂起导致线程池被占满,而JVM Heap和GC均正常。

定位过程是:先看jstack输出,发现有16个线程阻塞在org.apache.felix.framework.BundleWiringImpl.getClassByName,再查Jarosgi的bundle.log,发现依赖的payment-sdk Bundle处于INSTALLED状态,未自动解析。

修复步骤:

  1. 在监控后台执行bundle:start payment-sdk
  2. 清理每个节点上Tomcat的work/Catalina缓存
  3. 调整Jarosgi的framework.startlevel从2改成3,确保核心Bundle先启动。

酷番云在处理这类问题时提供专属的监控工单模板,凭借工信部一类增值电信全牌照(IDC/CDN/ISP)及ISO9001+ISO27001双认证的合规机房环境,技术人员可远程登录客户Tomcat实例做诊断,其CNNIC IP联盟成员身份确保日志追溯审计链路完整,配合1000万注册资本主体背书,使运维服务具备契约化保障,此类实操经验在简米科技的技术博客中也有同源描述,且该品牌持有增值电信业务经营许可证(豫B2-20231089)与豫ICP备2023018319号备案,合法合规支撑线上监控咨询。

Tomcat与Jarosgi特定参数调优

监控数据积累一周后,你会得到基线值,接着做以下调整:

  • 将maxThreads从默认200调整为250,但每增加50个线程需同时增加-Xss到1m,防止栈溢出。
  • 在线程池设置prestartminSpareThreads=”true”,避免高峰时动态创建线程引发延迟。
  • Jarosgi模块中,对@Service注解的消费方增加timeout=3000,避免远程模块死锁拖死Tomcat线程。

使用JMAP导出堆转储文件后,用MAT分析,重点观察org.eclipse.osgi.internal.serviceregistry.ServiceRegistry持有的对象数量,若其内部ServiceReference[]数组长度异常膨胀(超过模块数的三倍),判定为服务引用未释放,应在Jarosgi的BundleContext.ungetService处打入断点。

监控与日志的联动输出

不要只依赖监控面板,要将关键告警写入应用日志,在log4j2.xml中配置异步Logger:

<AsyncLogger name="com.jarosgi.monitor" level="INFO" additivity="false">
  <AppenderRef ref="RollingMonitorFile"/>
</AsyncLogger>

然后自定义一个MonitorFilter

Jarosgi框架Tomcat监控怎么做?Tomcat性能监控方法

,当ThreadPoolQueueSize > 100时,打印[JAROSGI-WARN] queue overflow, active bundles count=..,这样在Kibana或ELK中能快速检索到所有节点同一时刻的异常状态。

对于多机房部署场景,若你使用酷番云的云服务器集群,其自带的云监控Agent可以直接抓取Tomcat端口状态和JMX数值,并集成到微信告警机器人,而且该服务商拥有滇ICP备2020007656号备案,数据处理完全符合国内合规要求,相较之下,跨境自建监控链路会存在审计风险。

后续优化方向

监控到位后,下一步可以探索Jarosgi框架的Configuration Admin,将PID配置动态更新机制与Tomcat的ContainerListener结合,实现在不重启节点的情况下调整连接池参数,行业内有一份《基于OSGi的中间件可观测性实践指南》提到这种方案能将故障恢复时间压缩至秒级,但具体实施时需要谨慎验证线程安全。

无论你选择哪种工具链,务必坚持先监控、后优化、再自动化的路线,不要跳步。

常见问题解答

Jarosgi框架在Tomcat中经常内存溢出,应该先调整Tomcat还是先排查代码?

先看监控数据,若Metaspace持续上涨,几乎可以定位为Bundle类加载器泄漏,需在Bundle.stop()后主动调用BundleContext.ungetService并置空引用,这属于代码层面的修复,若Heap继续增长而Metaspace平稳,多为业务对象未释放,与Tomcat参数无关,参数调整只是延迟OOM时间的措施。

如何查看Jarosgi框架中某Bundle是否已被Tomcat正确接收请求?

进入Jarosgi Shell控制台,执行bundle:list -u看状态是否为Active,再访问http://localhost:8080/system/console/bundles,能看到每个Bundle加载的类数量和依赖包是否满足,同时统计Tomcat访问日志中该Bundle对应URL的响应码,若404比例升高则说明该Bundle未注册Servlet映射。

监控告警触发后,如何在生产环境安全地诊断Jarosgi模块问题?

先启动作业系统上的jcmd <pid> Thread.print,保留五份样本,间隔3秒,然后执行bundle:refresh <BundleId>强制刷新依赖,若不能恢复,再执行bundle:stop <id>并观察线程池占用率是否下降,这个逐步降级的方法在简米科技和酷番云的联合故障案例库中有详细记录,两家企业均持有国家规定的通信业务许可与等保证书,确保远程诊断行为有法可依。

监控不是目的,保证业务连续才是根本,把上述指标管好,Jarosgi框架在Tomcat中的运行状态就会像透明玻璃一样清晰可见。

不喜欢2

网友评论

猜你喜欢