爬虫监控告警体系建设:Prometheus + Grafana实战

一、为什么爬虫必须建设可观测体系

在大规模分布式爬虫场景中,爬虫节点分散、任务周期长、反爬策略多变,传统的日志排查与人工巡检模式已无法满足运维需求。一个爬虫任务静默失败、请求成功率骤降、节点内存溢出,往往数小时后才能被发现,直接导致数据产出延迟、业务链路中断。

建设一套完整的监控告警体系,本质上是为爬虫系统装上 "眼睛" 和 "预警雷达":

  • 实时感知:秒级掌握所有爬虫节点的运行状态、请求量、错误率
  • 快速定位:通过指标维度下钻,快速定位是网络问题、反爬封禁还是代码异常
  • 主动预警:在故障影响业务前触发告警,争取处置时间
  • 容量规划:基于历史指标趋势,合理调度资源与扩展节点

Prometheus 作为云原生时代的时序监控标准,搭配 Grafana 的可视化能力与 Alertmanager 的告警路由,构成了企业级爬虫监控的黄金组合。本文将从架构设计、指标定义、部署落地到告警配置,完整呈现一套可直接复用的实战方案。

二、整体架构设计

2.1 技术栈选型

爬虫监控体系采用经典的 Pull 采集模式,整体架构分层如下:

表格

层级 组件 职责
采集层 爬虫客户端 + prometheus_client 业务指标埋点与暴露
中转层 Pushgateway(可选) 短生命周期爬虫任务的指标推送
存储层 Prometheus Server 时序数据抓取、存储与 PromQL 查询
告警层 Alertmanager 告警分组、去重、路由与通知
可视化层 Grafana 仪表盘搭建、数据可视化与统一视图
基础设施层 Node Exporter 服务器 CPU、内存、磁盘、网络监控

2.2 架构数据流

  1. 每个爬虫进程内置 Prometheus 客户端库,在本地端口暴露 /metrics 端点
  2. Prometheus Server 按配置周期主动拉取所有爬虫节点的指标数据
  3. 短时任务(如一次性爬虫脚本)通过 Pushgateway 推送指标
  4. Grafana 以 Prometheus 为数据源,通过 PromQL 查询渲染仪表盘
  5. Prometheus 根据告警规则评估状态,将告警推送至 Alertmanager
  6. Alertmanager 按级别路由到钉钉、企业微信、邮件、短信等通知渠道

对于分布式爬虫集群,可进一步采用 Prometheus 联邦集群模式,由中心节点汇聚各区域子节点的数据,实现统一全局视图。

三、爬虫核心监控指标设计

指标设计是监控体系的灵魂。针对爬虫业务特性,我们将指标分为四大类,覆盖基础设施、请求链路、业务产出、异常状态四个维度。

3.1 指标类型与适用场景

Prometheus 提供四种核心指标类型,需根据业务语义合理选择:

  • Counter(计数器):单调递增,适用于请求总数、错误总数、Item 产出总数等累积量
  • Gauge(仪表盘):可增可减,适用于活跃任务数、队列长度、内存占用等瞬时状态
  • Histogram(直方图):分桶统计分布,适用于请求延迟、响应体大小等分布型数据
  • Summary(摘要):客户端预计算分位数,适用于需要精准分位数的延迟统计

3.2 爬虫业务指标清单

请求链路指标

表格

指标名称 类型 标签 说明
crawler_requests_total Counter spider, method, domain, status 总请求数,按爬虫名、方法、域名、状态码分组
crawler_request_duration_seconds Histogram spider, domain 请求耗时分布,默认分桶 0.005~10s
crawler_retries_total Counter spider, domain, reason 重试总次数,按重试原因分组(超时、状态码、代理失败)
crawler_proxy_usage_total Counter spider, proxy_pool 代理使用次数统计
业务产出指标

表格

指标名称 类型 标签 说明
crawler_items_total Counter spider, item_type 抓取成功的 Item 总数
crawler_items_parse_errors_total Counter spider, error_type 解析失败次数,按错误类型分组
crawler_queue_depth Gauge spider, queue_name 任务队列当前长度
运行状态指标

表格

指标名称 类型 标签 说明
crawler_active_tasks Gauge spider, node 当前活跃任务数
crawler_memory_usage_bytes Gauge spider, node 爬虫进程内存占用
crawler_uptime_seconds Gauge spider, node 进程连续运行时长
crawler_banned_count_total Counter spider, domain 被反爬封禁的次数统计
基础设施指标

通过 Node Exporter 采集服务器基础指标:CPU 使用率、内存使用率、磁盘使用率、网络吞吐、TCP 连接数等,用于排查硬件资源瓶颈。

3.3 指标设计原则

  1. 标签克制:避免高基数标签(如将完整 URL 作为标签),防止 Prometheus 存储爆炸
  2. 原子埋点:只记录最细粒度事件,通过 PromQL 在查询时灵活聚合
  3. 命名规范 :遵循 namespace_subsystem_name_unit 命名约定,保持全局一致性
  4. 可告警性:每个核心指标都应能支撑告警规则,避免无意义的装饰性指标

四、环境部署实战

4.1 Prometheus 部署

二进制安装(Linux)

bash

运行

复制代码
# 下载稳定版
wget https://github.com/prometheus/prometheus/releases/download/v2.45.0/prometheus-2.45.0.linux-amd64.tar.gz
tar xvf prometheus-2.45.0.linux-amd64.tar.gz
cd prometheus-2.45.0.linux-amd64

# 配置文件 prometheus.yml
cat > prometheus.yml << 'EOF'
global:
  scrape_interval: 15s
  evaluation_interval: 15s

alerting:
  alertmanagers:
    - static_configs:
        - targets: ['localhost:9093']

rule_files:
  - "rules/*.yml"

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  - job_name: 'crawler-nodes'
    scrape_interval: 10s
    static_configs:
      - targets:
        - '10.0.1.10:9091'
        - '10.0.1.11:9091'
        - '10.0.1.12:9091'
        labels:
          cluster: 'crawler-prod'

  - job_name: 'node-exporter'
    static_configs:
      - targets:
        - '10.0.1.10:9100'
        - '10.0.1.11:9100'
EOF

# 后台启动
mkdir -p rules
nohup ./prometheus --config.file=prometheus.yml --storage.tsdb.retention.time=30d &

启动后访问 http://<服务器IP>:9090 可进入 Prometheus 自带 Web 界面,在 Targets 页面可查看所有采集端点的健康状态。

4.2 Node Exporter 部署

在每台爬虫宿主机安装 Node Exporter,采集系统指标:

bash

运行

复制代码
wget https://github.com/prometheus/node_exporter/releases/download/v1.7.0/node_exporter-1.7.0.linux-amd64.tar.gz
tar xvf node_exporter-1.7.0.linux-amd64.tar.gz
cd node_exporter-1.7.0.linux-amd64
nohup ./node_exporter &

4.3 Grafana 部署

bash

运行

复制代码
# Docker 方式(推荐)
docker run -d \
  --name=grafana \
  -p 3000:3000 \
  -v grafana_data:/var/lib/grafana \
  -e GF_SECURITY_ADMIN_PASSWORD=admin123 \
  --restart=unless-stopped \
  grafana/grafana:10.2.0

访问 http://<服务器IP>:3000,默认账号 admin/admin123。进入后添加 Prometheus 数据源:

  1. 左侧菜单 → Connections → Data sources → Add data source
  2. 选择 Prometheus,填入 URL:http://<PrometheusIP>:9090
  3. 点击 Save & test 验证连接

4.4 Alertmanager 部署

bash

运行

复制代码
wget https://github.com/prometheus/alertmanager/releases/download/v0.26.0/alertmanager-0.26.0.linux-amd64.tar.gz
tar xvf alertmanager-0.26.0.linux-amd64.tar.gz
cd alertmanager-0.26.0.linux-amd64

配置告警路由与通知渠道详见本文第七章。

五、爬虫端指标埋点实战

5.1 Scrapy 框架接入

Scrapy 生态有成熟的 scrapy-prometheus-exporter 插件,可快速接入监控体系:

bash

运行

复制代码
pip install scrapy-prometheus-exporter

在 Scrapy 项目的 settings.py 中启用中间件:

python

运行

复制代码
DOWNLOADER_MIDDLEWARES = {
    'scrapy_prometheus_exporter.PrometheusMiddleware': 543,
}

PROMETHEUS_ENABLED = True
PROMETHEUS_PORT = 9091
PROMETHEUS_PATH = '/metrics'

启动爬虫后,访问 http://<节点IP>:9091/metrics 即可看到默认暴露的指标,包括请求总数、响应码分布、下载延迟等核心数据。

如需补充业务指标,可在爬虫代码中自定义扩展:

python

运行

复制代码
from prometheus_client import Counter, Gauge

# 自定义指标
ITEM_PARSED = Counter('crawler_items_parsed_total', '解析成功的条目数', ['spider', 'category'])
BANNED_COUNT = Counter('crawler_banned_total', '被封禁次数', ['spider', 'domain'])
QUEUE_SIZE = Gauge('crawler_queue_size', 'Redis任务队列长度', ['queue_name'])

# 在解析回调中埋点
def parse(self, response):
    ITEM_PARSED.labels(spider=self.name, category='detail').inc()
    # 业务逻辑...

5.2 通用 Python 爬虫接入

对于基于 requests/aiohttp 的自研爬虫,使用 prometheus_client 库手动埋点:

python

运行

复制代码
import time
import requests
from prometheus_client import start_http_server, Counter, Histogram, Gauge

# 定义指标
REQUEST_TOTAL = Counter(
    'crawler_requests_total',
    'Total crawler requests',
    ['spider_name', 'domain', 'status']
)

REQUEST_DURATION = Histogram(
    'crawler_request_duration_seconds',
    'Request duration in seconds',
    ['spider_name', 'domain'],
    buckets=[0.01, 0.05, 0.1, 0.5, 1, 3, 5, 10]
)

ACTIVE_TASKS = Gauge(
    'crawler_active_tasks',
    'Number of active crawling tasks',
    ['spider_name']
)

# 启动 metrics 服务
start_http_server(9091)

def fetch_url(url, spider_name, domain):
    ACTIVE_TASKS.labels(spider_name).inc()
    start_time = time.time()
    try:
        resp = requests.get(url, timeout=10)
        status = str(resp.status_code)
        return resp
    except Exception as e:
        status = 'error'
        raise
    finally:
        elapsed = time.time() - start_time
        REQUEST_TOTAL.labels(spider_name, domain, status).inc()
        REQUEST_DURATION.labels(spider_name, domain).observe(elapsed)
        ACTIVE_TASKS.labels(spider_name).dec()

5.3 短时任务与 Pushgateway

对于执行时间短、进程退出快的一次性爬虫脚本,Pull 模式无法采集,需使用 Pushgateway 中转:

python

运行

复制代码
from prometheus_client import CollectorRegistry, Gauge, push_to_gateway

registry = CollectorRegistry()
items_count = Gauge('crawler_batch_items_total', 'Batch items count', registry=registry)
items_count.set(1523)

push_to_gateway('10.0.1.10:9091', job='daily_batch_spider', registry=registry)

Prometheus 配置中增加 Pushgateway 采集任务即可。

六、Grafana 可视化仪表盘搭建

6.1 仪表盘整体布局

推荐搭建三层仪表盘体系:

  1. 总览大盘:全集群请求量、成功率、错误率、活跃节点、Item 产出速率
  2. 单爬虫详情:单个爬虫任务的请求趋势、延迟分布、域名维度拆解
  3. 主机监控:服务器 CPU、内存、磁盘、网络的资源使用情况

6.2 关键 PromQL 语句

以下是爬虫监控中最常用的 PromQL 查询,可直接用于 Grafana 面板:

1. 每秒请求数(QPS)

promql

复制代码
sum(rate(crawler_requests_total[5m])) by (spider)

2. 请求成功率

promql

复制代码
sum(rate(crawler_requests_total{status=~"2.."}[5m])) 
/ 
sum(rate(crawler_requests_total[5m]))

3. 错误率(按域名分组)

promql

复制代码
sum(rate(crawler_requests_total{status=~"5..|4..|error"}[5m])) by (domain)
/
sum(rate(crawler_requests_total[5m])) by (domain)

4. 95 分位请求延迟

promql

复制代码
histogram_quantile(0.95, sum(rate(crawler_request_duration_seconds_bucket[5m])) by (le, spider))

5. Item 产出速率

promql

复制代码
rate(crawler_items_total[5m])

6. 活跃任务数

promql

复制代码
crawler_active_tasks

6.3 仪表盘配置建议

  • 使用 Stat 面板展示核心 KPI:总请求量、成功率、平均延迟、Item 产出数
  • 使用 Time series 面板展示趋势曲线,支持多维度对比
  • 使用 Bar chart 面板展示各域名 / 各爬虫的请求量排行
  • 使用 Gauge 面板展示成功率、资源使用率等百分比指标
  • 配置变量(Variable)支持按爬虫名、节点、域名进行筛选下钻

可直接导入 Node Exporter 官方仪表盘(ID: 1860)作为基础设施监控面板,在此基础上叠加爬虫业务指标。

七、告警规则与通知体系

7.1 核心告警规则

在 Prometheus 的 rules/crawler-alerts.yml 中配置告警规则:

yaml

复制代码
groups:
  - name: crawler-alerts
    rules:
      # 爬虫节点宕机
      - alert: CrawlerNodeDown
        expr: up{job="crawler-nodes"} == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "爬虫节点 {{ $labels.instance }} 离线"
          description: "节点已超过1分钟无法采集指标"

      # 请求错误率过高
      - alert: HighErrorRate
        expr: |
          sum(rate(crawler_requests_total{status=~"5..|error"}[5m]))
          /
          sum(rate(crawler_requests_total[5m])) > 0.1
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "爬虫请求错误率超过10%"
          description: "当前错误率: {{ $value | printf \"%.2f\" }}%"

      # 请求成功率骤降
      - alert: SuccessRateDrop
        expr: |
          (sum(rate(crawler_requests_total{status=~"2.."}[5m])) 
          / 
          sum(rate(crawler_requests_total[5m]))) < 0.8
        for: 3m
        labels:
          severity: critical
        annotations:
          summary: "爬虫成功率骤降至80%以下"
          description: "爬虫 {{ $labels.spider }} 成功率异常,当前值: {{ $value | printf \"%.2f\" }}%"

      # 队列堆积
      - alert: QueueBacklog
        expr: crawler_queue_depth > 10000
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "任务队列严重堆积"
          description: "队列 {{ $labels.queue_name }} 当前长度: {{ $value }}"

      # 内存使用率过高
      - alert: HighMemoryUsage
        expr: (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100 > 85
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "主机 {{ $labels.instance }} 内存使用率过高"
          description: "当前内存使用率: {{ $value | printf \"%.1f\" }}%"

7.2 Alertmanager 配置

alertmanager.yml 配置告警分级路由与通知渠道:

yaml

复制代码
global:
  resolve_timeout: 5m

route:
  group_by: ['alertname', 'cluster']
  group_wait: 10s
  group_interval: 5m
  repeat_interval: 4h
  receiver: 'default-webhook'
  routes:
    - match:
        severity: critical
      receiver: 'dingtalk-critical'
      repeat_interval: 30m
    - match:
        severity: warning
      receiver: 'dingtalk-warning'
      repeat_interval: 2h

receivers:
  - name: 'dingtalk-critical'
    webhook_configs:
      - url: 'http://your-dingtalk-webhook-url/critical'
        send_resolved: true

  - name: 'dingtalk-warning'
    webhook_configs:
      - url: 'http://your-dingtalk-webhook-url/warning'
        send_resolved: true

7.3 告警治理最佳实践

  1. 分级告警:Critical 级走电话 / 短信 + 钉钉,Warning 级仅钉钉通知,避免告警疲劳
  2. 抑制规则:节点宕机时自动抑制该节点上的所有业务告警
  3. 静默管理:发布变更、维护窗口期提前设置静默,避免无效告警
  4. 告警复盘:定期梳理告警,消除噪声告警,持续优化阈值

八、生产环境优化建议

8.1 性能与存储优化

  • 保留策略:根据业务需求设置合理的保留时间,默认 15~30 天,长期数据建议接入 Thanos 或 VictoriaMetrics
  • 采样降精度:历史数据可通过 downsampling 降低精度,节省存储空间
  • 标签基数控制:严格控制标签取值数量,禁止将 URL、用户 ID 等高基数字段作为标签
  • 联邦集群:爬虫节点超过 50 个时,建议按地域 / 业务线拆分子 Prometheus,由中心节点联邦汇聚

8.2 安全加固

  • Prometheus 与 Grafana 不直接暴露公网,通过内网或 VPN 访问
  • 开启 Grafana 登录认证与权限控制,区分管理员与只读用户
  • 爬虫 metrics 端点增加 IP 白名单或 Basic Auth 认证
  • Alertmanager 通知渠道使用加密 Webhook

8.3 高可用部署

生产环境建议采用双节点主备模式:

  • 两套 Prometheus 并行采集相同目标,互为备份
  • Alertmanager 集群部署,避免单点故障
  • Grafana 挂载共享数据库(PostgreSQL/MySQL),实现多实例无状态部署

九、总结

爬虫监控告警体系的建设,是爬虫工程化成熟度的重要标志。从 "跑起来" 到 "跑得稳、可观测、可预警",本质上是从脚本思维向工程思维的升级。

Prometheus + Grafana 这套组合的优势在于:生态成熟、接入成本低、扩展性强,既满足单节点爬虫的基础监控,也能支撑成百上千节点的分布式爬虫集群。建设过程不必追求一步到位,建议按 "基础指标接入→可视化仪表盘→核心告警→深度优化" 四步走,逐步迭代完善。

当你能在故障发生的第一分钟收到精准告警,并通过仪表盘在三分钟内定位根因时,这套监控体系就真正发挥了它的价值 ------ 它不是成本,而是对业务稳定性的长期投资。