Lychee-Rerank-MM部署教程:Prometheus+Grafana监控GPU利用率与QPS指标
Lychee-Rerank-MM部署教程:Prometheus+Grafana监控GPU利用率与QPS指标
1. 引言
当你成功部署了Lychee多模态重排序模型,看着它在服务器上稳定运行,处理着图文检索任务时,一个现实的问题可能会浮现在脑海:它到底运行得怎么样?
GPU的显存用了多少?模型推理的速度快不快?每秒能处理多少个请求?这些指标就像汽车的仪表盘,没有它们,你就是在“盲开”。你不知道系统是否在高效运转,也不知道何时会遇到性能瓶颈。
这就是为什么我们需要监控。今天,我要带你做的,就是为你的Lychee-Rerank-MM模型装上一个专业的“仪表盘”。我们将使用Prometheus来收集GPU利用率和QPS(每秒查询数)指标,然后用Grafana把这些数据变成直观的图表。这样,你就能一眼看清模型的运行状态,及时发现并解决问题。
2. 监控方案整体设计
在开始动手之前,我们先花几分钟了解一下整个监控系统是怎么工作的。这能帮你更好地理解每个步骤的意义。
我们的监控架构很简单,但很实用,主要包含三个核心组件:
-
数据采集器(Prometheus Node Exporter + 自定义Exporter):这是系统的“眼睛”。Node Exporter负责收集服务器的基础指标,比如CPU、内存、磁盘使用率。我们还需要一个自定义的Exporter来专门收集GPU的显存使用、GPU利用率,以及Lychee模型服务的QPS指标。
-
时序数据库与抓取器(Prometheus Server):这是系统的“大脑”和“仓库”。Prometheus Server会按照你设定的时间间隔(比如每15秒),主动去各个Exporter“抓取”指标数据,然后把这些时间序列数据存储在自己的数据库中。
-
数据可视化平台(Grafana):这是系统的“仪表盘”。Grafana从Prometheus里读取数据,然后让你通过拖拽的方式,创建出各种漂亮的图表和监控面板,比如GPU利用率曲线图、QPS实时统计表。
它们之间的关系,你可以参考下面的流程图:
graph TD
A[Lychee-Rerank-MM 服务] -->|暴露/metrics端点| B[自定义Python Exporter]
C[服务器硬件] -->|系统指标| D[Prometheus Node Exporter]
B --> E[Prometheus Server<br/>抓取并存储指标]
D --> E
E -->|作为数据源| F[Grafana]
F -->|查询与展示| G[可视化监控面板]
整个部署过程,我们会按照“先搭建基础设施,再完善监控指标”的思路进行。准备好了吗?我们开始吧。
3. 基础监控环境搭建
我们先来部署Prometheus和Grafana这两个核心服务。为了保持环境干净和便于管理,我强烈建议使用Docker来运行它们。
3.1 创建监控配置文件目录
首先,我们在服务器上创建一个目录,用来存放所有的配置文件。
mkdir -p /opt/monitoring/lychee
cd /opt/monitoring/lychee
3.2 部署Prometheus
Prometheus需要一个配置文件来告诉它去哪里抓取数据。我们来创建这个文件。
- 创建Prometheus配置文件
prometheus.yml:
# /opt/monitoring/lychee/prometheus.yml
global:
scrape_interval: 15s # 每15秒抓取一次数据
evaluation_interval: 15s # 每15秒评估一次规则
scrape_configs:
# 监控Prometheus自身
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
# 监控服务器节点(通过Node Exporter)
- job_name: 'node'
static_configs:
- targets: ['node-exporter:9100'] # 注意这里用了服务名
# 监控Lychee自定义指标(这是我们后面要创建的)
- job_name: 'lychee-exporter'
static_configs:
- targets: ['lychee-exporter:8000'] # 注意这里用了服务名
- 使用Docker Compose一键启动:
为了简化管理,我们创建一个 docker-compose.yml 文件,把Prometheus、Grafana和Node Exporter的服务定义都放在里面。
# /opt/monitoring/lychee/docker-compose.yml
version: '3.8'
services:
prometheus:
image: prom/prometheus:latest
container_name: prometheus
restart: unless-stopped
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/etc/prometheus/console_libraries'
- '--web.console.templates=/etc/prometheus/consoles'
- '--storage.tsdb.retention.time=30d' # 数据保留30天
networks:
- monitoring
grafana:
image: grafana/grafana:latest
container_name: grafana
restart: unless-stopped
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin123 # 首次登录密码,请务必修改!
volumes:
- grafana_data:/var/lib/grafana
networks:
- monitoring
node-exporter:
image: prom/node-exporter:latest
container_name: node-exporter
restart: unless-stopped
ports:
- "9100:9100"
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.rootfs=/rootfs'
- '--path.sysfs=/host/sys'
- '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
networks:
- monitoring
networks:
monitoring:
driver: bridge
volumes:
prometheus_data:
grafana_data:
- 启动服务:
在存放 docker-compose.yml 文件的目录下,运行以下命令:
docker-compose up -d
这个命令会在后台启动所有服务。你可以用 docker-compose ps 查看服务状态,应该能看到三个容器都在运行。
- 验证Prometheus:
打开浏览器,访问 http://你的服务器IP:9090。如果能看到Prometheus的Web界面,并且点击上方菜单栏的 Status -> Targets,能看到 prometheus 和 node 两个job的状态都是 UP,那就说明基础监控服务已经跑起来了。(lychee-exporter 的状态目前会是 DOWN,因为我们还没部署它,这是正常的)。
3.3 初步配置Grafana
-
登录Grafana: 访问
http://你的服务器IP:3000,使用用户名admin和密码admin123登录。登录后第一件事,就是在提示中修改这个默认密码! -
添加Prometheus数据源:
- 点击左侧导航栏的齿轮图标(Configuration),选择 Data Sources。
- 点击 Add data source,选择 Prometheus。
- 在URL一栏填写
http://prometheus:9090(注意,这里用的是Docker Compose网络内的服务名,不是localhost)。 - 点击 Save & Test,如果显示“Data source is working”,就说明连接成功了。
好了,监控平台的基础架子已经搭好了。接下来,我们要解决最关键的问题:如何让Prometheus获取到Lychee模型的GPU和QPS数据。
4. 自定义指标采集器开发
Prometheus的Node Exporter能提供通用的系统指标,但对于我们特定的AI模型服务,比如GPU显存使用详情、模型推理的QPS,就需要我们自己来暴露这些指标。我们将编写一个Python程序来充当这个“桥梁”。
4.1 创建自定义Exporter项目
回到我们的监控目录,创建一个子目录来存放这个采集器。
mkdir -p /opt/monitoring/lychee/lychee_exporter
cd /opt/monitoring/lychee/lychee_exporter
4.2 编写指标采集脚本
创建一个名为 exporter.py 的文件,内容如下。这个脚本会做三件事:1. 启动一个Web服务提供/metrics端点;2. 定期收集GPU指标;3. 统计Lychee服务的QPS。
#!/usr/bin/env python3
# /opt/monitoring/lychee/lychee_exporter/exporter.py
import time
import psutil
import subprocess
from datetime import datetime
from prometheus_client import start_http_server, Gauge, Counter, Histogram
import threading
import re
import logging
# 设置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
# 定义Prometheus指标
# GPU指标
GPU_MEMORY_USED = Gauge('lychee_gpu_memory_used_bytes', 'GPU memory used by Lychee process (bytes)')
GPU_MEMORY_TOTAL = Gauge('lychee_gpu_memory_total_bytes', 'Total GPU memory (bytes)')
GPU_UTILIZATION = Gauge('lychee_gpu_utilization_percent', 'GPU utilization percentage')
GPU_POWER_USAGE = Gauge('lychee_gpu_power_usage_watts', 'GPU power usage in watts')
GPU_TEMPERATURE = Gauge('lychee_gpu_temperature_celsius', 'GPU temperature in Celsius')
# QPS指标
LYCHEE_QPS = Gauge('lychee_queries_per_second', 'Current queries per second')
LYCHEE_TOTAL_QUERIES = Counter('lychee_total_queries', 'Total number of queries processed')
LYCHEE_REQUEST_DURATION = Histogram('lychee_request_duration_seconds', 'Duration of Lychee inference requests')
# 系统指标(补充Node Exporter)
PROCESS_CPU_PERCENT = Gauge('lychee_process_cpu_percent', 'CPU percentage used by Lychee process')
PROCESS_MEMORY_MB = Gauge('lychee_process_memory_mb', 'Memory used by Lychee process (MB)')
class LycheeMonitor:
def __init__(self):
self.last_query_count = 0
self.last_update_time = time.time()
self.qps_window = [] # 用于计算滑动窗口QPS
self.lychee_pid = self._find_lychee_pid()
def _find_lychee_pid(self):
"""查找Lychee服务的进程ID"""
try:
# 根据你的启动方式调整进程名
for proc in psutil.process_iter(['pid', 'name', 'cmdline']):
try:
cmdline = ' '.join(proc.info['cmdline'] or [])
if 'app.py' in cmdline and 'lychee' in cmdline.lower():
logger.info(f"Found Lychee process: PID {proc.info['pid']}")
return proc.info['pid']
except (psutil.NoSuchProcess, psutil.AccessDenied):
continue
except Exception as e:
logger.error(f"Error finding Lychee PID: {e}")
return None
def get_gpu_metrics(self):
"""使用nvidia-smi获取GPU指标"""
try:
result = subprocess.run(
['nvidia-smi', '--query-gpu=memory.used,memory.total,utilization.gpu,power.draw,temperature.gpu',
'--format=csv,noheader,nounits'],
capture_output=True,
text=True,
timeout=5
)
if result.returncode == 0:
# 解析输出,假设只有一块GPU,多GPU需要调整
values = result.stdout.strip().split(', ')
if len(values) >= 5:
# 内存单位转换:MB -> Bytes
memory_used_mb = float(values[0])
memory_total_mb = float(values[1])
GPU_MEMORY_USED.set(memory_used_mb * 1024 * 1024) # MB to Bytes
GPU_MEMORY_TOTAL.set(memory_total_mb * 1024 * 1024) # MB to Bytes
GPU_UTILIZATION.set(float(values[2]))
GPU_POWER_USAGE.set(float(values[3]))
GPU_TEMPERATURE.set(float(values[4]))
logger.debug(f"GPU Metrics updated: {memory_used_mb}/{memory_total_mb} MB, {values[2]}% util")
except Exception as e:
logger.error(f"Error getting GPU metrics: {e}")
# 设置指标为-1表示获取失败
GPU_MEMORY_USED.set(-1)
GPU_UTILIZATION.set(-1)
def get_process_metrics(self):
"""获取Lychee进程的CPU和内存使用情况"""
if self.lychee_pid:
try:
process = psutil.Process(self.lychee_pid)
PROCESS_CPU_PERCENT.set(process.cpu_percent(interval=0.1))
PROCESS_MEMORY_MB.set(process.memory_info().rss / 1024 / 1024) # Bytes to MB
except (psutil.NoSuchProcess, psutil.AccessDenied) as e:
logger.warning(f"Could not get process metrics: {e}")
self.lychee_pid = self._find_lychee_pid() # 尝试重新查找PID
def update_qps_metric(self):
"""更新QPS指标(这里需要根据你的实际日志或接口来统计)"""
# 方法1:通过分析日志文件(示例)
current_time = time.time()
try:
# 假设你的Lychee服务日志在/tmp/lychee_server.log
# 这里统计包含特定关键词(如“Query processed”)的行数
log_count = 0
try:
with open('/tmp/lychee_server.log', 'r') as f:
for line in f:
if 'Query processed' in line or 'inference_time' in line: # 根据你的日志调整
log_count += 1
except FileNotFoundError:
pass
# 计算当前窗口的QPS(简单示例)
self.qps_window.append((current_time, log_count))
# 只保留最近10秒的数据
self.qps_window = [(t, c) for t, c in self.qps_window if current_time - t < 10]
if len(self.qps_window) > 1:
time_span = self.qps_window[-1][0] - self.qps_window[0][0]
query_span = self.qps_window[-1][1] - self.qps_window[0][1]
if time_span > 0:
current_qps = query_span / time_span
LYCHEE_QPS.set(current_qps)
logger.debug(f"Current QPS: {current_qps:.2f}")
# 更新总查询数(这是一个Counter,只增不减)
if log_count > self.last_query_count:
LYCHEE_TOTAL_QUERIES.inc(log_count - self.last_query_count)
self.last_query_count = log_count
except Exception as e:
logger.error(f"Error updating QPS: {e}")
def collect_all_metrics(self):
"""收集所有指标"""
logger.info("Collecting metrics...")
self.get_gpu_metrics()
self.get_process_metrics()
self.update_qps_metric()
logger.info("Metrics collection completed")
def main():
# 启动Prometheus指标的HTTP服务器,端口8000
start_http_server(8000)
logger.info("Lychee Exporter started on port 8000")
monitor = LycheeMonitor()
# 每5秒收集一次指标
while True:
try:
monitor.collect_all_metrics()
except Exception as e:
logger.error(f"Error in main collection loop: {e}")
time.sleep(5)
if __name__ == '__main__':
main()
4.3 创建依赖文件与启动脚本
- 创建
requirements.txt:
# /opt/monitoring/lychee/lychee_exporter/requirements.txt
prometheus-client>=0.20.0
psutil>=5.9.0
- 创建
Dockerfile(用于容器化部署):
# /opt/monitoring/lychee/lychee_exporter/Dockerfile
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 安装nvidia-smi命令(如果需要从容器内调用宿主机的nvidia-smi,通常不需要,采用主机挂载方式)
# RUN apt-get update && apt-get install -y --no-install-recommends nvidia-utils-535 && rm -rf /var/lib/apt/lists/*
COPY exporter.py .
EXPOSE 8000
CMD ["python", "exporter.py"]
- 更新
docker-compose.yml:
我们需要把自定义的Exporter也加入到Docker Compose的管理中。编辑之前的 docker-compose.yml 文件,在 services: 部分添加以下内容:
lychee-exporter:
build: ./lychee_exporter # 指向我们刚创建的目录
container_name: lychee-exporter
restart: unless-stopped
ports:
- "8000:8000"
# 关键:将宿主机的GPU工具和日志挂载到容器内
volumes:
- /usr/bin/nvidia-smi:/usr/bin/nvidia-smi:ro
- /tmp/lychee_server.log:/tmp/lychee_server.log:ro
- /proc:/host/proc:ro # 用于psutil读取进程信息
# 让容器可以访问宿主机的GPU设备(如果需要)
# devices:
# - /dev/nvidia0:/dev/nvidia0
# - /dev/nvidiactl:/dev/nvidiactl
# - /dev/nvidia-uvm:/dev/nvidia-uvm
# 或者使用runtime(推荐):
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
networks:
- monitoring
重要说明:上面的 volumes 挂载是将宿主机的 nvidia-smi 命令和Lychee的日志文件映射到容器内,这样容器里的Python脚本才能调用它们。/proc 的挂载是为了让 psutil 能读取到宿主机的进程信息。
4.4 启动自定义Exporter
现在,回到 /opt/monitoring/lychee 目录,重新启动所有服务,这会包含我们新建的Exporter。
docker-compose down # 先停止旧服务
docker-compose up -d --build lychee-exporter # 构建并启动新的exporter容器
docker-compose up -d # 启动所有服务
使用 docker-compose logs -f lychee-exporter 查看Exporter的日志,确认没有报错,并且看到“Lychee Exporter started on port 8000”的信息。
4.5 验证指标暴露
访问 http://你的服务器IP:8000/metrics,你应该能看到Prometheus格式的指标数据,例如:
# HELP lychee_gpu_memory_used_bytes GPU memory used by Lychee process (bytes)
# TYPE lychee_gpu_memory_used_bytes gauge
lychee_gpu_memory_used_bytes 1.23456789e+09
# HELP lychee_gpu_utilization_percent GPU utilization percentage
# TYPE lychee_gpu_utilization_percent gauge
lychee_gpu_utilization_percent 45.0
...
同时,再次访问Prometheus的Targets页面 (http://IP:9090/targets),现在应该能看到 lychee-exporter 的状态也变成了 UP。
至此,数据采集的“桥梁”已经架设完毕,Prometheus正在定期抓取我们模型的专属指标。最后一步,就是在Grafana上打造一个美观实用的仪表盘了。
5. Grafana监控面板配置
现在,所有数据都已流入Prometheus。我们将在Grafana中创建一个专属面板,将这些数据可视化。
5.1 创建新的Dashboard
- 在Grafana左侧导航栏,点击 Dashboards -> New dashboard。
- 点击 Add visualization 来添加第一个图表。
5.2 添加关键监控图表
我们将添加几个核心图表来监控Lychee服务的健康度。
图表1:GPU显存使用率
- 面板类型:选择 Stat 或 Gauge(仪表盘)来显示实时百分比。
- 查询语句:
(lychee_gpu_memory_used_bytes / lychee_gpu_memory_total_bytes) * 100 - 设置:
- Title: GPU显存使用率
- Unit: Percent (0-100)
- Thresholds: 可以设置绿色(<80%),黄色(80-90%),红色(>90%)来预警。
图表2:GPU利用率折线图
- 面板类型:选择 Time series(时间序列图)。
- 查询语句:
lychee_gpu_utilization_percent - 设置:
- Title: GPU利用率 (%)
- Unit: Percent (0-100)
- 可以添加一条
avg_over_time(lychee_gpu_utilization_percent[5m])的查询来显示5分钟平均线,让曲线更平滑。
图表3:QPS(每秒查询数)折线图
- 面板类型:选择 Time series。
- 查询语句:
*如果QPS指标波动较大,可以使用lychee_queries_per_secondrate()函数从Counter计算(如果lychee_total_queries是Counter的话):rate(lychee_total_queries[5m]) - 设置:
- Title: 请求QPS
- Unit: Queries/sec (QPS)
图表4:总处理查询数
- 面板类型:选择 Stat。
- 查询语句:
lychee_total_queries - 设置:
- Title: 总处理查询数
- Unit: 无(或选择
none)
图表5:进程内存使用
- 面板类型:选择 Time series。
- 查询语句:
lychee_process_memory_mb - 设置:
- Title: Lychee进程内存 (MB)
- Unit: megabytes (MB)
5.3 优化面板布局与告警
- 拖拽调整:将上述图表在面板上合理布局,例如将GPU相关指标放在一行,QPS和请求数放在另一行。
- 添加告警(可选但建议):
- 点击图表标题 -> Edit -> Alert -> Create alert。
- 例如,为“GPU显存使用率”创建告警规则:当
(lychee_gpu_memory_used_bytes / lychee_gpu_memory_total_bytes) * 100 > 90持续5分钟时,触发告警。 - 配置告警通知渠道(需要在Grafana中提前配置好Email、Slack、钉钉、企业微信等)。
- 保存Dashboard:点击顶部 Save dashboard,给它起个名字,比如
Lychee-Rerank-MM 服务监控。
现在,你的专属监控仪表盘就创建完成了!它应该类似下图所示,让你对服务的运行状态一目了然。
graph TD
subgraph “Grafana 监控面板”
A[GPU显存使用率<br/>仪表盘] --> B[整体服务健康视图]
C[GPU利用率折线图] --> B
D[请求QPS折线图] --> B
E[总处理查询数<br/>统计值] --> B
F[进程内存使用折线图] --> B
end
B --> G{状态判断}
G -->|指标异常| H[触发告警通知]
G -->|指标正常| I[持续稳定运行]
6. 总结
通过这篇教程,我们完成了一件非常重要的事情:为Lychee-Rerank-MM模型服务装上了“眼睛”和“仪表盘”。
我们来回顾一下关键步骤和收获:
- 搭建了监控基础设施:用Docker Compose快速部署了Prometheus和Grafana,这是所有监控数据的存储和展示中心。
- 开发了自定义指标采集器:这是本次实践的核心。我们写了一个Python程序,它能够读取
nvidia-smi的输出获取GPU指标,并通过分析服务日志(或未来可集成更精确的API)来统计QPS,最后以Prometheus能理解的格式暴露出来。 - 配置了可视化仪表盘:在Grafana中,我们将冰冷的数字变成了直观的图表。GPU利用率曲线、显存使用仪表、QPS波动图,这些都能让你瞬间把握服务的运行脉搏。
这套监控系统能帮你做什么?
- 性能评估:清晰看到模型在不同负载下的GPU利用率和QPS,为资源扩容或优化提供数据支撑。
- 故障预警:设置告警规则后,能在显存即将耗尽或QPS异常下跌时收到通知,避免服务不可用。
- 成本优化:观察资源使用率,判断当前服务器配置是否合理,是否存在资源浪费。
- 瓶颈分析:当QPS上不去时,可以结合GPU利用率和进程CPU使用率,快速判断瓶颈是在计算、内存还是I/O。
下一步可以做什么?
- 更精确的QPS统计:目前我们通过分析日志文件来统计,这可能不够实时和准确。更优的方案是在Lychee服务的代码中直接埋点,在每次处理请求时递增一个计数器,并在一个独立的HTTP端点暴露这个指标。
- 监控推理延迟:在自定义Exporter中增加对请求耗时的统计和分桶(Histogram),监控P50、P90、P99等延迟指标,这对评估用户体验至关重要。
- 业务指标监控:除了系统指标,还可以考虑暴露一些业务指标,比如不同指令(Instruction)下的请求分布、重排序得分的分布等。
- 部署优化:将自定义Exporter、Prometheus、Grafana的配置和部署脚本化、自动化,方便在其他环境快速复制这套监控体系。
监控不是一次性的任务,而是一个持续的过程。希望这套方案能成为你运维Lychee-Rerank-MM乃至其他AI模型服务的得力助手,让技术运维变得更加可观测、可掌控。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。
更多推荐



所有评论(0)