
先交代一句这套组合我现在已经稳定跑了半年多Tongweb实例从2台加到8台全部靠PrometheusGrafana这一套统一纳管省了太多“登录到服务器看一眼JVM状态”的机械操作。标题里的Tongweb 8090说的就是Tongweb中间件暴露出来用于JMX监控的端口有的版本里也叫管理端口和业务端口是两回事这点一定要先分清楚不然下面所有配置都容易对不上。我写这篇的目的很简单把从零搭建Tongweb监控的完整过程、踩过的坑、以及最终沉淀下来的配置模板一次性整理出来。适合刚接手Tongweb维护、或者想把公司里分散的Java中间件监控统一到同一套开源体系里的同学参考。内容不依赖任何商业监控产品一台普通的Linux服务器就能跑完所有组件。1. 监控方案的整体设计与思路拆解1.1 为什么选PrometheusGrafana而不是传统监控先说结论Tongweb本身是Java应用服务器基于JVM运行所以最需要监控的不是服务器层面的CPU内存而是JVM的堆内存、GC、线程池、连接数这些应用层指标。传统做法是登录Tongweb自带的管理控制台或者ssh上去敲jstat、jstack但这些都是“点一下看一秒”的模式没有历史曲线也没法在半夜出问题时自动通知人。Zabbix也不是不行但Zabbix的强项是网络和主机层面的指标采集对Java应用层指标要么需要自己写脚本模板要么依赖agent插件维护成本偏高。Prometheus的核心优势在于“拉取模型”加“指标即数据”用exporter把Tongweb的JMX指标暴露成HTTP接口Prometheus定时拉取存成时序数据Grafana从Prometheus查询渲染。整个过程配置透明哪里出问题一眼就能看到。还有一个很现实的理由PrometheusGrafana这套组合在社区里太成熟了遇到问题随便一搜就有答案。Tongweb虽然相对小众但它跑在JVM上所以所有关于JVM监控的资料、面板、告警规则都能直接复用这是选型时最省心的地方。1.2 核心数据链路Tongweb → Prometheus → Grafana整套链路看起来长实际拆开就四段第一段是Tongweb暴露JMX指标。Tongweb启动时通过JVM参数开启JMX服务监听在8090端口。第二段是jmx_exporter把JMX里的MBean数据转换成Prometheus能识别的/metrics格式。第三段是Prometheus按固定时间间隔默认15秒拉取这些指标并存储。第四段是Grafana连接Prometheus数据源把指标画成面板并基于规则触发告警。很多人第一次接触会被“端口”搞晕Tongweb业务端口可能是8080、8090或者其他自定义端口而这里说的监控端口是JMX RMI端口。如果业务端口恰好也是8090那就更需要确认清楚——JMX端口和业务端口在配置上完全独立但共用同一个IP肉眼很容易看错。1.3 部署拓扑与组件分工我的实际部署方式是这样的组件作用部署位置Tongweb被监控的应用服务器开启JMX监听8090业务服务器jmx_exporterJava agent方式运行把JMX指标转成HTTP格式与Tongweb同机监听9100Prometheus抓取指标存储时序数据计算告警规则独立监控服务器监听9090Grafana可视化面板与告警展示独立监控服务器或与Prometheus同机监听3000这里有个细节值得说一下jmx_exporter有两种运行方式一种是独立进程连远端JMX端口另一种是作为Java agent打进Tongweb启动参数里。我强烈建议用agent方式。原因很简单JVM的JMX指标里有大量进程内部数据agent方式相当于在进程里直接读取不需要额外维护一个netty http服务去转发RMI连接配置更少出问题的环节更少。2. 基础组件安装与环境准备2.1 Prometheus安装与基础配置Prometheus安装没什么技术含量但有几个版本选择和权限上的小坑值得注意。先去官网下载Linux amd64版本压缩包解压后直接就是可执行文件。顺序上建议先配好prometheus.yml再启动因为如果先启动再改配置虽然Prometheus支持热加载但第一次启动时经常会因为文件语法问题反复看日志。我的prometheus.yml最简配置如下global: scrape_interval: 15s evaluation_interval: 15s scrape_configs: - job_name: prometheus static_configs: - targets: [localhost:9090]这里有两个参数要解释一下。scrape_interval是抓取频率默认15秒对Tongweb这种中间件监控完全够用没必要改成5秒指标多了反而会增加JMX请求压力和磁盘占用。evaluation_interval是告警规则计算频率会和下面要写的告警规则配合。启动时用systemd托管比较好别用nohup挂在后台。我吃过一次亏服务器重启后Prometheus没自启监控面板全灰业务那边也没人发现直到凌晨告警打过来才知道是监控端先挂了。systemd配置很简单核心就三条ExecStart指向prometheus二进制、WorkingDirectory指向数据目录、Restartalways。[Unit] DescriptionPrometheus Afternetwork.target [Service] Userprometheus ExecStart/opt/prometheus/prometheus --config.file/opt/prometheus/prometheus.yml --storage.tsdb.path/opt/prometheus/data Restartalways [Install] WantedBymulti-user.target启动完别急着往下走先验证一步curl http://localhost:9090/targets能看到Prometheus自带job的UP状态是绿色再继续。2.2 Grafana安装与数据源接入Grafana安装也不复杂Debian系直接用apt仓库装或者下载tar包解压跑。装完访问http://server-ip:3000默认账号admin/admin第一次登录会强制改密码改成强密码并记住后面别再用默认密码不然扫描工具扫出来就是裸奔。进入Grafana后的第一个操作是添加Prometheus数据源。路径是Configuration - Data Sources - Add data source选PrometheusURL填http://prometheus-ip:9090点击Save Test显示“Successfully queried the Prometheus API”就通了。这里有个容易踩的坑如果Prometheus和Grafana不在同一台机器URL千万不要填localhost:9090要填Prometheus服务器的实际内网IP。别问我为什么强调很多新手第一次配完发现面板上全是不带数据的空图表排查半天才发现数据源连错了地址。Grafana侧还有一个可选优化提前配好组织、用户和权限给不同团队开只读账号。Tongweb运维面板给DBA和研发看的时候只读权限能避免有人手滑改掉面板配置。2.3 Tongweb被监控端的准备Tongweb这边的准备工作主要围绕三件事确认8090端口没有被占用、确认JMX服务能正常监听、确认防火墙放行了监控端口。用这个命令检查端口netstat -tlnp | grep 8090如果端口已经被其他进程占用要么换一个端口要么先停掉冲突进程。Tongweb启动的时候如果提示JMX端口绑定失败通常不会影响业务启动但你会发现自己怎么连都连不上日志里却什么都没有。防火墙检查也要提前做。很多机房有云安全组和服务器iptables两层规则Prometheus所在机器和Tongweb所在机器之间至少要放行两段流量Tongweb的8090端口给jmx_exporter如果是agent方式实际是jmx_exporter和Prometheus之间通信但JMX端口同样需要有监听地址以及jmx_exporter的9100端口给Prometheus。3. 关键环节Tongweb 8090 JMX暴露与对接3.1 JMX采集原理简析为什么用JMX就能监控Tongweb因为Tongweb是Java程序而JVM自带的JMX机制把运行时状态都封装成了MBeanManaged Bean。这些MBean包括内存池、GC、线程、类加载、操作系统等标准命名空间从java.lang开始。jmx_exporter的原理就是通过JMX RMI协议连上MBeanServer按配置的规则把指定MBean的属性值转成Prometheus指标格式。打个比方JMX里java.lang:typeMemory这个MBean的HeapMemoryUsage属性经过jmx_exporter转换后就变成了jvm_memory_bytes_used{areaheap}这样的指标后面可以直接在Prometheus里查询。理解这个转换过程很重要因为后续写面板和告警规则时你操作的对象不是JMX属性名而是Prometheus指标名。如果哪天Grafana上查不到某个指标第一反应应该是回到jmx_exporter暴露的/metrics接口里看这个指标到底叫什么、有没有触发过滤规则。3.2 Tongweb 8090的JMX配置实操Tongweb的JMX配置入口是它的启动脚本。不同版本位置略有区别但本质都是在JVM启动参数里加上一套-Dcom.sun.management.jmxremote配置。以下是我在Tongweb 7上验证过的配置JAVA_OPTS$JAVA_OPTS -Dcom.sun.management.jmxremotetrue JAVA_OPTS$JAVA_OPTS -Dcom.sun.management.jmxremote.port8090 JAVA_OPTS$JAVA_OPTS -Dcom.sun.management.jmxremote.rmi.port8090 JAVA_OPTS$JAVA_OPTS -Dcom.sun.management.jmxremote.authenticatefalse JAVA_OPTS$JAVA_OPTS -Dcom.sun.management.jmxremote.sslfalse JAVA_OPTS$JAVA_OPTS -Dcom.sun.management.jmxremote.local.onlyfalse JAVA_OPTS$JAVA_OPTS -Djava.rmi.server.hostname192.168.10.20逐条解释一下。authenticatefalse和sslfalse是测试环境的选择意思是JMX连接不需要用户名密码、不加密。但到了生产环境我强烈不建议这样裸奔后面第5章会单独讲怎么加固。local.onlyfalse表示允许非本机连接这行很多人会漏漏了之后你在另一台机器上访问JMX端口就会直接超时。java.rmi.server.hostname这行几乎必填。因为JMX RMI通信时服务端会把自己认为的IP地址告诉客户端在有多网卡的服务器上这个地址经常是内网固定IP或主机名如果Prometheus那边解析不了就会一直报Connection refused。手动指定成业务网卡的IP是最省事的做法。接下来是jmx_exporter的接入。下载jmx_prometheus_javaagent-xxx.jar后放到Tongweb服务器上在原来的启动命令里加一行java -javaagent:/opt/jmx_exporter/jmx_prometheus_javaagent.jar9100:/opt/jmx_exporter/config.yaml \ $JAVA_OPTS \ -jar tongweb.jar这里的9100是jmx_exporter自己暴露HTTP指标用的端口config.yaml是抓取规则。因为Tongweb已经开启了JMX 8090jmx_exporter会直接通过JMX协议读取本机JVM的MBean不需要再去配置remote connection。一个比较关键的配置文件config.yaml我的基础版长这样rules: - pattern: java.langtypeMemory(HeapMemoryUsage|NonHeapMemoryUsage)(committed|init|max|used) name: jvm_memory_$1_$2 - pattern: java.langtypeThreadingThreadCount name: jvm_threads_current - pattern: java.langtypeGarbageCollectorname(.*)CollectionCount name: jvm_gc_collection_count - pattern: java.langtypeGarbageCollectorname(.*)CollectionTime name: jvm_gc_collection_time如果不想自己写规则也可以随手抄一个简单的rules配置先让数据跑起来再说。等确认通了再逐步调整过滤规则减少不必要的指标膨胀。3.3 Prometheus采集规则配置Tongweb装好jmx_exporter后Prometheus这边要增加一个job来拉数据。在prometheus.yml的scrape_configs下加这一段- job_name: tongweb static_configs: - targets: [192.168.10.20:9100] relabel_configs: - source_labels: [__address__] regex: (.*):.* target_label: instance replacement: tongweb-01标签这里值得多写一句。默认情况下Prometheus会使用targets里的地址作为instance标签也就是说指标里的instance192.168.10.20:9100。如果后续有多台Tongweb你会看到每个实例都是IP面板上根本分不清是哪台。我习惯用relabel_configs把instance改成tongweb-01这种可读性强的别名后续面板和告警里引用起来一目了然。配完执行Prometheus热加载curl -X POST http://localhost:9090/-/reload然后到Prometheus的Status - Targets页面确认tongweb这个job的Endpoint是UP状态。如果你不放心也可以直接到Prometheus的查询页面输入up{jobtongweb}返回1就说明抓取成功。4. Grafana可视化与告警联动4.1 数据源与Dashboard导入数据源在第2章已经配好了。这里讲讲怎么高效做出一个可用的Tongweb监控面板。最快的方式是导入现成的JVM监控Dashboard。Grafana社区有大量通用JVM面板官方编号8561、4701之类都可以用导入方式是Deashboard - Import输入编号即可。但这些面板大部分针对Spring Boot应用里面用了很多Spring Boot才有的指标比如http_server_requests_seconds_countTongweb上没有这些数据所以导入完通常会有一堆空图。我的做法是导入一个基础JVM面板作为底子然后删掉空图再加上Tongweb特色的连接数、活跃线程、请求处理时间等指标。这样比从零手搓面板快得多也能保证图表风格统一。4.2 常用监控面板设计设计面板的原则很简单先回答“应用活着吗”再回答“性能健康吗”最后看“趋势往哪走”。我实际保留的监控指标如下面板名称PromQL作用实例存活up{jobtongweb}第一时间发现进程挂了堆内存使用量jvm_memory_bytes_used{areaheap}看堆内存水位堆内存使用率jvm_memory_bytes_used{areaheap}/jvm_memory_bytes_max{areaheap}触发优化和告警的关键GC暂停次数jvm_gc_collection_count看Full GC频率GC暂停耗时jvm_gc_collection_time看停顿影响活跃线程数jvm_threads_current排查线程泄漏类加载数jvm_classes_loaded排查动态类加载问题这里说一个经验面板不要堆太多图。我见过有人把几十个指标全堆在一个Dashboard上看着很专业但实际运维时根本不知道先看哪个。我自己的Dashboard只留下6到7张图按“故障排查路径”从上往下排最先看到存活状态然后看内存和GC最后看线程和连接数。用Grafana的Time Series类型画堆内存时我习惯同时画committed和max两条曲线因为只看used看不出问题——堆用完不一定异常要看是否接近max以及committed是否频繁扩容。这些细节才是有价值的信息。4.3 告警规则配置告警这里有两种实现。一种是在Prometheus里写rules规则由Alertmanager发到钉钉、邮件、企业微信另一种是直接用Grafana的Alerting。我建议把核心告警放在Prometheus这一层因为它不依赖Grafana存活监控系统的告警自身不能挂在监控界面上。我的告警规则文件tongweb-rules.yml长这样groups: - name: tongweb-alerts rules: - alert: TongwebInstanceDown expr: up{jobtongweb} 0 for: 1m labels: severity: critical annotations: summary: Tongweb实例{{ $labels.instance }} 已停止 - alert: TongwebHeapUsageHigh expr: (jvm_memory_bytes_used{areaheap} / jvm_memory_bytes_max{areaheap}) 0.85 for: 10m labels: severity: warning annotations: summary: {{ $labels.instance }} 堆内存使用率超过85%for: 10m的意思不是简单的“持续10分钟都超阈值”而是“这个条件要连续满足10分钟才触发告警”这样可以有效过滤掉偶发的内存尖峰。经验上堆内存使用率阈值设为85%持续10分钟比较合适如果设成90%很多吞吐量大的Tongweb还没到阈值就先被Full GC打挂了。Grafana侧也可以配告警适合一些视图级的自定义阈值比如某个接口的耗时超过特定值。两条链路不冲突Prometheus负责可靠触达Grafana负责灵活补充。5. 常见问题排查与避坑实录5.1 经典故障8090连不上、指标为空这套方案搭好后我收到的求助里超过一半是同一个问题Prometheus能看到tongwebjob是UP的但查询jvm_memory_bytes_used却没有任何数据。先说排查顺序。第一步去jmx_exporter的9100端口直接看指标有没有暴露curl http://192.168.10.20:9100/metrics | grep jvm_memory如果这里没有输出说明jmx_exporter没有抓到JMX数据问题多半在Tongweb的JMX配置上。常见原因有三个一是忘了加-Dcom.sun.management.jmxremote.port8090导致JMX根本没监听二是端口被防火墙挡了三是java.rmi.server.hostname没配RMI回调地址不对。如果9100能看到指标但Prometheus查不到问题就在采集配置上。检查Targets页面的Target Labels看job标签是不是tongwebinstance标签是不是被relabel搞错了。有一次我就是把正则写错所有指标都被drop了Targets页面还显示UP但数据为空。再说一个隐蔽的坑Tongweb某些版本启动时会用独立ClassLoader加载它自己的MBean导致java.lang标准指标正常但Tongweb特有指标比如连接数、session数在jmx_exporter默认配置下抓不到。这种情况需要去Tongweb的管理控制台确认MBean的ObjectName然后手动加到config.yaml的pattern里。5.2 JMX认证与安全加固前面配置里我用了authenticatefalse这在测试环境没问题但生产环境真的不建议。JMX RMI协议本身不加密如果监控端口暴露到了公网等于把堆内存、GC、线程等内部信息全裸给别人看严重一点的甚至可以通过JMX的DiagnosticCommand执行一些JVM管理操作。推荐的做法是两层加固。第一层JMX配置改成密码认证JAVA_OPTS$JAVA_OPTS -Dcom.sun.management.jmxremote.authenticatetrue JAVA_OPTS$JAVA_OPTS -Dcom.sun.management.jmxremote.access.file/opt/tongweb/conf/jmxremote.access JAVA_OPTS$JAVA_OPTS -Dcom.sun.management.jmxremote.password.file/opt/tongweb/conf/jmxremote.passwordjmxremote.access文件里写monitorRole readonly controlRole readwritejmxremote.password文件里写用户名和密码注意这个文件权限必须改成600否则JVM会直接拒绝启用JMX。然后在jmx_exporter启动参数里通过-Dcom.sun.management.jmxremote.registry之类的方式带上凭据或者使用jmx_prometheus_httpserver的配置指定用户名密码。第二层网络层面的最小化暴露。Tongweb的JMX端口只监听内网IP不要监听0.0.0.0同时用安全组或iptables限定只有监控服务器IP能访问8090和9100。这个比JMX密码认证优先级更高因为即便认证被绕过网络隔离还能兜底。5.3 性能开销与优化建议很多人担心加了一个jmx_exporter会不会拖垮Tongweb性能。从我实测的数据看jmx_exporter的CPU开销通常在1%以内内存占用在几十MB级别对生产环境几乎可以忽略。真正需要关注的是高频抓取和大量规则带来的JMX压力。优化点有三个。第一scrape_interval不要设太短。15秒完全够用如果Tongweb实例特别多甚至可以放宽到30秒或60秒Prometheus这边是全局的但同一套指标保留时间也不会因此失真多少。第二config.yaml里一定要加过滤规则。很多网上模板会直接抓全部java.lang.*的指标那会产生几百个时间序列存到Prometheus里全是垃圾。我只保留java.lang:typeMemory、Threading、GarbageCollector、OperatingSystem里真正关心的属性指标数量能少一半以上。第三Grafana面板上不要放太多高基数的标签组合。比如别在图表里用instance作为唯一分组维度去叠加几十个实例Grafana渲染会很慢。我一般用$instance变量下拉框让面板默认显示一台实例需要对比时再手动加。写在最后的一点心得体会这套Tongweb监控方案前前后后调了两周最大的感悟是监控系统的价值不在于把多少指标放到大屏上而在于故障发生时能不能“少走弯路”。我现在每天上班先扫一眼Grafana里的Tongweb面板堆内存曲线、GC次数、活跃线程数正常就不用再挨个登录服务器看日志。最后分享一个实用小技巧给Prometheus数据加一个保存时长的配置项我的做法是--storage.tsdb.retention.time180d保留半年的历史数据。这样到了做容量规划的时候可以直接从Grafana看过去几个月的内存和连接数趋势比拍脑袋估算准得多。如果你们团队还没把Tongweb纳入Prometheus监控我建议从今天就开始动手先抓基础JVM指标跑通后再逐步加Tongweb特有指标整个链路并不复杂但越早接入未来的维护成本越低。