强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Minecraft PaperMC 服务器部署指南 / 13 - 监控与诊断

13 - 监控与诊断

13.1 监控体系概述

13.1.1 监控层次

┌─────────────────────────────────────┐
│         应用层监控                   │
│   TPS / MSPT / 实体数 / 玩家数      │
├─────────────────────────────────────┤
│         JVM 层监控                   │
│   GC 频率 / 堆内存 / 线程数         │
├─────────────────────────────────────┤
│         系统层监控                   │
│   CPU / 内存 / 磁盘 IO / 网络       │
└─────────────────────────────────────┘

13.1.2 监控工具矩阵

工具层次类型说明
Spark应用 + JVM插件PaperMC 最强分析工具
Timings应用内置Paper 内置(旧版)
/tps应用内置基本 TPS 查看
Prometheus + Grafana系统 + JVM外部完整监控面板
htop / glances系统CLI服务器资源监控
VisualVMJVMGUI内存和线程分析

13.2 Spark 性能分析

Spark 是 PaperMC 生态中最强大的性能分析插件。

13.2.1 安装 Spark

# 从 Hangar 下载
# https://hangar.papermc.io/lucko/Spark

# 或使用 Paper plugin.yml 自动下载
# 将 spark-paper.jar 放入 plugins/ 目录
wget -O /opt/minecraft/paper/plugins/spark-paper.jar \
  "https://hangar.papermc.io/api/v1/projects/spark/versions/latest/PAPER/download"

13.2.2 TPS 和 MSPT 监控

# 查看 TPS
/spark tps

# 输出示例:
# TPS from last 1m, 5m, 15m: 20.0, 19.8, 19.5
# MSPT from last 1m, 5m, 15m: 12.5, 15.2, 18.1

# 查看详细性能信息
/spark health

# 查看实体统计
/spark healthentities

13.2.3 CPU 分析器(Profiler)

# 启动 CPU 分析(采样 60 秒)
/spark profiler --timeout 60

# 查看分析结果
/spark profiler --timeout 60 --order total

# 分析特定类型的性能
/spark profiler --timeout 300 --interval 1

分析输出示例:

--- Thread: Server Thread ---
  45.2% - MinecraftServer.tick()
    ├── 23.1% - WorldServer.tick()
    │   ├── 12.3% - Entity ticking
    │   │   ├── 8.1% - Zombie.aiStep()
    │   │   └── 4.2% - Creeper.aiStep()
    │   └── 10.8% - Block ticking
    ├── 15.4% - ChunkSource ticking
    └── 6.7% - Connection ticking
  28.5% - idle

13.2.4 内存分析

# 查看内存使用
/spark healthmemory

# 输出示例:
# Heap Memory: 3.2 GB / 4.0 GB (80%)
# Eden Space: 1.5 GB
# Survivor Space: 128 MB
# Old Gen: 1.6 GB

# 查看对象分布
/spark gc

# 查看详细 GC 日志
/spark gcinfo

13.2.5 线程分析

# 查看线程信息
/spark threads

# 查看特定线程
/spark threadinfo "Server Thread"

13.2.6 实体和区块分析

# 实体统计
/spark healthentities

# 输出示例:
# Zombies: 245
# Skeletons: 189
# Creepers: 67
# Items: 432
# Total: 1,233

# 区块统计
/spark healthchunks

# 输出示例:
# Loaded Chunks: 3,456
# Entity Chunks: 890
# Ticket Chunks: 2,100

13.2.7 Spark Web 界面

# 启动 Spark Web 界面
/spark web

# 输出链接: https://spark.lucko.me/xxxxx
# 可以在浏览器中查看详细的性能报告

13.2.8 Spark 配置

# plugins/Spark/config.yml

# 命令权限
command-permissions:
  # 是否限制命令使用
  requires-permission: true

# 性能分析器设置
profiler:
  # 采样间隔(毫秒)
  interval: 50
  # 忽略特定线程
  ignore-sleeping: true
  # 合并相似栈帧
  merge-java-stdlib: true

# 内存分析设置
heap-analysis:
  # 是否启用
  enabled: true
  # 分析间隔
  interval: 600

# TPS 监控设置
tps:
  # 精度
  precision: 2
  # 保留时间(分钟)
  retention-minutes: 10

13.3 Timings 分析(旧版 Paper)

Paper 已移除内置 Timings,但了解它有助于分析旧服务器。

# 启动 Timings 记录
# (仅在旧版 Paper 或 Spigot 上可用)
/timings on

# 等待一段时间后
/timings paste

# 获取分析链接
# 输出: https://timings.aikar.co/?id=xxxxx

# 停止记录
/timings off

注意:新版 Paper 已完全使用 Spark 替代 Timings。如果仍在使用旧版 Timings,建议升级到 Spark。


13.4 JVM 监控

13.4.1 GC 日志

# 添加 JVM 参数启用 GC 日志
java \
  -Xlog:gc*:file=logs/gc.log:time,uptime,level,tags:filecount=5,filesize=10M \
  -jar paper.jar --nogui

# 分析 GC 日志
# 使用 GCViewer 工具
# https://github.com/chewiebug/GCViewer
java -jar gcviewer.jar logs/gc.log

13.4.2 VisualVM 远程监控

# 添加 JMX 远程监控参数
java \
  -Dcom.sun.management.jmxremote \
  -Dcom.sun.management.jmxremote.port=9010 \
  -Dcom.sun.management.jmxremote.authenticate=false \
  -Dcom.sun.management.jmxremote.ssl=false \
  -Dcom.sun.management.jmxremote.local.only=false \
  -Djava.rmi.server.hostname=你的服务器IP \
  -jar paper.jar --nogui
# 在本地电脑打开 VisualVM
# 1. 下载 VisualVM: https://visualvm.github.io/
# 2. 添加远程连接: 服务器IP:9010
# 3. 查看 CPU、内存、线程实时图表

13.4.3 JMX Prometheus 导出

# 下载 JMX Prometheus Java Agent
wget https://github.com/prometheus/jmx_exporter/releases/download/0.20.0/jmx_prometheus_javaagent-0.20.0.jar

# 创建 Prometheus 配置
cat > jmx-exporter.yml << 'EOF'
rules:
  - pattern: "java.lang<type=Memory><HeapMemoryUsage>(\\w+)"
    name: jvm_memory_heap_$1
    type: GAUGE
  - pattern: "java.lang<type=Memory><NonHeapMemoryUsage>(\\w+)"
    name: jvm_memory_nonheap_$1
    type: GAUGE
  - pattern: "java.lang<type=GarbageCollector, name=(.+)><>(\\w+)"
    name: jvm_gc_$1_$2
    type: COUNTER
EOF

# 启动参数
java \
  -javaagent:jmx_prometheus_javaagent-0.20.0.jar=7070:jmx-exporter.yml \
  -jar paper.jar --nogui

13.5 系统监控

13.5.1 系统资源监控

# CPU、内存、进程监控
htop

# 详细系统信息
glances

# 磁盘 IO 监控
iotop

# 网络流量监控
iftop

# 系统负载
uptime
# 输出: 14:30:00 up 10 days, load average: 2.15, 1.87, 1.92

13.5.2 Prometheus + Grafana 监控

# docker-compose-monitoring.yml

services:
  node-exporter:
    image: prom/node-exporter
    container_name: node-exporter
    ports:
      - "9100:9100"
    volumes:
      - /proc:/host/proc:ro
      - /sys:/host/sys:ro
      - /:/rootfs:ro
    command:
      - '--path.procfs=/host/proc'
      - '--path.sysfs=/host/sys'

  prometheus:
    image: prom/prometheus
    container_name: prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus-data:/prometheus

  grafana:
    image: grafana/grafana
    container_name: grafana
    ports:
      - "3000:3000"
    environment:
      GF_SECURITY_ADMIN_PASSWORD: admin123
    volumes:
      - grafana-data:/var/lib/grafana

volumes:
  prometheus-data:
  grafana-data:
# prometheus.yml
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'node'
    static_configs:
      - targets: ['node-exporter:9100']

  - job_name: 'minecraft'
    static_configs:
      - targets: ['host.docker.internal:7070']

13.5.3 Grafana Dashboard

推荐 Dashboard:

ID名称说明
1860Node Exporter Full系统监控
10000Minecraft ServerMC 专用监控
763Redis DashboardRedis 监控

13.6 自动告警

13.6.1 TPS 告警脚本

#!/bin/bash
# mc-alert.sh - TPS 自动告警脚本

ALERT_THRESHOLD=18.0
WEBHOOK_URL="https://your-webhook-url"
SERVER="localhost:25565"

# 使用 mcstatus 获取状态
TPS=$(docker exec mc-paper rcon-cli "spark tps" 2>/dev/null | grep -oP '20\.\d+|1\d\.\d+' | head -1)

if [ -z "$TPS" ]; then
    echo "无法获取 TPS"
    exit 1
fi

# 比较阈值
if (( $(echo "$TPS < $ALERT_THRESHOLD" | bc -l) )); then
    echo "警告: TPS 过低 (${TPS})"

    # 发送 Webhook 通知
    curl -s -X POST "$WEBHOOK_URL" \
      -H "Content-Type: application/json" \
      -d "{
        \"content\": \"⚠️ 服务器 TPS 过低: ${TPS} (阈值: ${ALERT_THRESHOLD})\",
        \"embeds\": [{
          \"title\": \"性能告警\",
          \"description\": \"TPS: ${TPS}\",
          \"color\": 16711680
        }]
      }"
fi
# 每 5 分钟检查一次
crontab -e
*/5 * * * * /opt/minecraft/scripts/mc-alert.sh >> /var/log/mc-alert.log 2>&1

13.6.2 内存告警

#!/bin/bash
# memory-alert.sh

MEMORY_USAGE=$(docker stats --no-stream --format "{{.MemPerc}}" mc-paper | tr -d '%')

if (( $(echo "$MEMORY_USAGE > 85" | bc -l) )); then
    echo "警告: 内存使用率过高 (${MEMORY_USAGE}%)"
    # 发送通知...
fi

13.7 性能监控仪表板

13.7.1 监控指标清单

指标采集方式告警阈值说明
TPSSpark/RCON< 18.0核心指标
MSPTSpark/RCON> 45ms每 tick 耗时
内存使用率JMX/Stats> 85%堆内存
CPU 使用率Node Exporter> 80%系统 CPU
磁盘使用率Node Exporter> 90%存储空间
在线玩家数Query/RCON-监控人数波动
实体数量Spark> 5000可能影响性能
网络带宽Node Exporter> 80%入出站带宽

13.7.2 日志分析

# 分析 Paper 日志中的性能警告
grep -i "warn\|error\|tick\|lag\|overloaded" /opt/minecraft/paper/logs/latest.log

# 统计每分钟的连接/断开
grep "joined\|left" /opt/minecraft/paper/logs/latest.log | \
  awk '{print $1, $2}' | cut -d: -f1,2 | sort | uniq -c

# 查看最频繁的插件错误
grep -i "exception\|error" /opt/minecraft/paper/logs/latest.log | \
  grep "plugins" | awk -F'(' '{print $2}' | sort | uniq -c | sort -rn

13.8 性能基准测试

13.8.1 使用 Spark 进行基准测试

# 1. 启动分析器
/spark profiler --timeout 600

# 2. 模拟玩家活动(使用 bot 插件或手动操作)

# 3. 查看结果
/spark profiler --timeout 600 --order total

# 4. 保存报告
/spark profiler --timeout 600 --output-file benchmark.txt

13.8.2 记录性能基线

## 性能基线记录

| 日期 | 版本 | TPS | MSPT | 内存 | 实体 | 玩家 |
|------|------|-----|------|------|------|------|
| 2026-05-01 | 1.21.4 | 20.0 | 12ms | 3.2G | 1200 | 20 |
| 2026-05-10 | 1.21.4 | 19.5 | 18ms | 3.8G | 2500 | 35 |
| ... | ... | ... | ... | ... | ... | ... |

13.9 常见问题

Q1:Spark 显示 TPS 正常但玩家感觉卡?

# 可能是网络延迟而非服务器卡顿
# 使用 Spark 检查网络延迟
/spark healthping

# 检查是否有特定 chunk 导致问题
/spark healthchunks

Q2:如何找到最消耗性能的插件?

# 使用 Spark 的插件性能分析
/spark healthplugins

# 或通过 Profiler 分析
/spark profiler --timeout 120
# 查看输出中的插件相关栈帧

Q3:GC 日志如何分析?

# 简单查看 GC 频率
grep "gc" logs/gc.log | wc -l

# 查看 Full GC 次数
grep "Full GC" logs/gc.log | wc -l

# 如果 Full GC 频繁,说明内存不足或泄漏

13.10 本章小结

要点说明
Spark 是首选分析工具免费、功能全面
Profiler 定位 CPU 瓶颈采样分析找出热点代码
内存分析防止 OOM定期检查堆使用
Prometheus + Grafana 是生产监控方案可视化仪表板
自动告警及时发现问题TPS/内存/磁盘告警
记录性能基线跟踪长期性能变化

扩展阅读