基于Blackbox Exporter的网络服务黑盒监控体系实践

文章目录

  • 前言
  • 一、Blackbox_exporter介绍
    • [1.1 Blackbox_exporter介绍](#1.1 Blackbox_exporter介绍)
    • [1.2 整体构建思路](#1.2 整体构建思路)
  • 二、项目搭建过程
    • [2.1 搭建Prometheus](#2.1 搭建Prometheus)
    • [2.2 搭建Blackbox_exporter](#2.2 搭建Blackbox_exporter)
    • [2.3 Prometheus完成数据存储](#2.3 Prometheus完成数据存储)
    • [2.4 对接夜莺监控系统](#2.4 对接夜莺监控系统)
  • 三、核心监控数据
    • [3.1 核心监控指标](#3.1 核心监控指标)
    • [3.2 网络时延与性能指标](#3.2 网络时延与性能指标)
    • [3.3 补充指标](#3.3 补充指标)

前言

我们公司的服务器都部署在同一个IDC机房。由于物联网设备在绑定时只认单一IP地址,因此我们通过"内网IP+端口"映射到同一公网IP端口的方式,实现服务的对外访问。然而有一天,公司网络突然出现异常,导致物联网设备无法将数据上报至服务,造成服务整体中断。故障持续约半小时,期间出现了两次。我作为运维人员,在接到通知后第一时间进行排查,却发现所有服务器都已无法连接,这基本坐实了是网络层出了问题。

尽管问题的根源不在运维层面,而在于网络线路不稳定,但我并非在故障发生瞬间就察觉到的。为了在未来类似情况中能第一时间定位问题、并准确通知相关团队处理,我决定引入黑盒监控的思路。采用了 Blackbox Exporter 作为探测工具,并结合一台位于云端的高稳定性服务器,对关键服务进行持续性探测(之前大学期间写过一个类似的探测工具,但实现下来发现成熟稳定的 Blackbox Exporter哈哈哈哈有点冒昧了)。

一、Blackbox_exporter介绍

1.1 Blackbox_exporter介绍

Blackbox-exporter是Prometheus官方提供的一个黑盒监控解决方案,可以通过HTTP、HTTPS、DNS、ICMP、TCP和gRPC方式对目标实例进行检测。可用于以下使用场景:

  • HTTP/HTTPS:URL/API可用性检测

  • ICMP:主机存活检测

  • TCP:端口存活检测

  • DNS:域名解析

黑盒监控与白盒监控:

黑盒监控是业务可用性的守门员,我们无需关心服务内部如何实现,只需像真实用户一样验证其关键功能是否正常。这通常体现为使用自动化工具定期探测核心服务的端口状态、HTTP接口的返回状态码、响应时间以及SSL证书有效性等。

它的核心价值在于快速回答服务"通不通"和"快不快"的问题,能够在用户受到影响前发现网络中断、服务宕机或性能劣化等宏观故障,是一种面向现象的监控方式。

白盒监控则要求我们打开"盒子",基于系统内部暴露的指标、日志和链路追踪数据进行深度检查。当黑盒监控告警或指标数据提示系统存在潜在问题时,白盒监控能引导您定位根因。

1.2 整体构建思路

计划采用:Prometheus+Blackbox_exporter+夜莺告警系统+云服务器。

Prometheus:专职数据采集与存储

职责 :作为监控体系的核心底座,主动通过Pull模式 从部署在各个目标机器上的Exporter拉取(Scrape)监控指标数据,并存储在其内置的高效时序数据库中。
关键点在于它负责的是数据的"收"和"存",保证监控数据的完整性和可查询性。

Blackbox Exporter外部探测执行器的角色。

它专精于黑盒监控 ,即从外部用户视角,模拟真实请求来探测目标服务(如HTTP/HTTPS页面、TCP端口、ICMP等)的可用性与性能,但并不关心目标服务内部的运行状态(如CPU使用率等,那属于白盒监控范畴)。其核心价值在于,当您的服务器因网络问题全部失联时,部署在稳定的云服务器上的Blackbox Exporter依然能从外部网络探测您的服务公网入口,从而快速定位故障域是否为机房外部网络。

夜莺:专注数据应用与告警管理
职责 :作为监控系统的"大脑",它不直接接收采集器的数据 ,而是将已有的Prometheus实例配置为一个数据源 。它通过Prometheus的API查询数据,进而实现统一可视化 提供强大的监控大盘和数据分析界面。 强大的告警管理,这是相比直接使用Prometheus的Alertmanager的一大优势。夜莺提供了基于Web UI的、功能丰富的告警规则管理、告警收敛、屏蔽、订阅、自愈等一系列企业级告警功能。

二、项目搭建过程

2.1 搭建Prometheus

bash 复制代码
mv prometheus-3.5.0.linux-amd64/ prometheus
cd prometheus/

htpasswd -nBC 12 'password' | tr -d ':\n'
# 根据密码生成字符串
vim web-config.yml 
basic_auth_users:
  admin: # 根据密码生成字符串

编写启动脚本,并启动Prometheus:

bash 复制代码
vim /etc/systemd/system/prometheus.service

[Unit]
Description=Prometheus Monitoring
Wants=network-online.target
After=network-online.target

[Service]
Type=simple
User=root
Group=root
# 工作目录
WorkingDirectory=/data/prometheus
# 启动命令
ExecStart=/data/prometheus/prometheus \
  --config.file=/data/prometheus/prometheus.yml \
  --storage.tsdb.path=/data/prometheus/data \
  --web.config.file=/data/prometheus/web-config.yml \
  --web.console.templates=/data/prometheus/consoles \
  --web.console.libraries=/data/prometheus/console_libraries \
  --web.enable-lifecycle #开启热加载

Restart=on-failure
RestartSec=5s
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target


systemctl daemon-reload 
systemctl start prometheus 

为了可以动态加载配置,所以开启了web.enable-lifecycle参数,这样就可以用下面的命令进行动态加载了,无需重启Prometheus:

bash 复制代码
# 热加载命令
curl -u "admin:password" -X POST http://192.168.16.2:9090/-/reload

在web访问http://127.0.0.1:9090/即可查看Prometheus前端。

2.2 搭建Blackbox_exporter

bash 复制代码
# 解压并进入服务目录
root@instance-wc5p3ngj:/data/prometheus/blackbox_exporter# ls 
LICENSE  NOTICE  blackbox.yml  blackbox_exporter

# 使用默认配置文件进行启动

vim /etc/systemd/system/blackbox_exporter.service 
[Unit]
Description=Blackbox Exporter
Documentation=https://github.com/prometheus/blackbox_exporter
Wants=network-online.target
After=network-online.target

[Service]
Type=simple
User=root
Group=root
ExecStart=/data/prometheus/blackbox_exporter/blackbox_exporter \
    --config.file=/data/prometheus/blackbox_exporter/blackbox.yml
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target

systemctl daemon-reload
systemctl start blackbox_exporter.service
netstat -lnpt | grep 9115

2.3 Prometheus完成数据存储

编写Prometheus配置文件:

bash 复制代码
vim /data/prometheus/prometheus.yml
global:
  scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
  evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.

alerting:
  alertmanagers:
    - static_configs:
        - targets:

rule_files:
scrape_configs:
	# 对接Prometheus
  - job_name: "prometheus"
    basic_auth:
      username: 'admin'
      password: 'password'
    static_configs:
      - targets: ["192.168.16.2:9090"]
        labels:
          app: "prometheus"
	
  - job_name: "blackbox_net_check"
    metrics_path: /probe
    params:
      module: [http_2xx]
    scrape_interval: 30s
    scrape_timeout: 25s
    static_configs:
      - targets:
          - https://www.baidu.com
        labels:
          env: "prod"
          service: "web-test"
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - source_labels: [__param_target]
        target_label: target
      - target_label: __address__
        replacement: 192.168.16.2:9115

配置文件解读:

字段 含义 你的配置说明
job_name 采集任务标识 标识为 "blackbox_net_check",查询时job="blackbox_net_check"筛选黑盒探测指标
metrics_path 要拉取指标的路径(默认是/metrics,黑盒需改为/probe 访问 Blackbox_exporter 的/probe接口触发探测,而非默认的/metrics
params 访问metrics_path时携带的 URL 参数 module=http_2xx,指定使用 Blackbox 的http_2xx模块(检测 HTTP 2xx 响应)
scrape_interval: 30s 覆盖全局的采集间隔,该任务每 30 秒探测一次 比全局 15 秒慢,适合网络探测
scrape_timeout: 25s 采集超时时间(必须小于scrape_interval 探测超过 25 秒则判定为超时失败,避免卡住采集任务
static_configs 定义 1 组探测目标,每组带自定义标签 第一组:探测https://www.baidu.com,标签env=prod(生产环境)、service=Web-NetTest(网站网络测试)
relabel_configs 重标签规则(采集前修改标签 / 参数),核心是 "把探测目标传给 Blackbox,把采集地址指向 Blackbox" 逐个拆解: 1. source_labels: [__address__] → target_label: __param_target:把targets里的地址(如https://www.baidu.com)作为/probe?target=xxx的参数; 2. source_labels: [__param_target] → target_label: instance:把探测目标赋值给instance标签(查询时instance显示目标地址); 3. source_labels: [__param_target] → target_label: target:新增target标签,和instance互补,更清晰识别探测对象; 4. target_label: __address__ → replacement: 192.168.16.2:9115:把采集地址改为 Blackbox_exporter 的地址。

使用热加载命令重新加载Prometheus完成监控对接。

2.4 对接夜莺监控系统

这里引入了一个夜莺官方给出的架构图,我们引入夜莺的作用也如上图所示。

Prometheus:专职数据采集与存储 职责 :作为监控体系的核心底座,主动通过Pull模式 从部署在各个目标机器上的Exporter拉取(Scrape)监控指标数据,并存储在其内置的高效时序数据库中。
关键点在于它负责的是数据的"收"和"存",保证监控数据的完整性和可查询性。

夜莺:专注数据应用与告警管理 职责 :作为监控系统的"大脑",它不直接接收采集器的数据 ,而是将已有的Prometheus实例配置为一个数据源 。它通过Prometheus的API查询数据,进而实现:
统一可视化 :提供强大的监控大盘和数据分析界面。
强大的告警管理:这是相比直接使用Prometheus的Alertmanager的一大优势。夜莺提供了基于Web UI的、功能丰富的告警规则管理、告警收敛、屏蔽、订阅、自愈等一系列企业级告警功能。

搭建流程如下:

bash 复制代码
# 搭建n9e所需数据库并导入数据
sudo docker run -d \
  --name mysql-n9e \
  -p 3306:3306 \
  -v /data/n9e/mysql:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=password \
  mysql:8.0
  
# 导入数据库
cp n9e.sql mysql/
sudo docker exec -it mysql-n9e mysql -u root -p

# 导入数据库
source /var/lib/mysql/n9e.sql

# 启动redis
sudo docker run -d \
  --name redis-n9e \
  -p 6379:6379 \
  -v /data/n9e/redis:/data \
  redis:6.2.6  \
  redis-server --appendonly yes --requirepass "password"

编写n9e配置文件:

bash 复制代码
mkdir /data/n9e/ && cd /data/n9e
tar -zxvf  n9e-v8.4.1-linux-amd64.tar.gz  -C /data/n9e

vim /data/n9e/etc/config.toml 
[DB]
# mysql postgres sqlite
DBType = "mysql"
# postgres: host=%s port=%s user=%s dbname=%s password=%s sslmode=%s
# postgres: DSN="host=127.0.0.1 port=5432 user=root dbname=n9e_v6 password=1234 sslmode=disable"
# mysql: DSN="root:1234@tcp(localhost:3306)/n9e_v6?charset=utf8mb4&parseTime=True&loc=Local"
#DSN = "n9e.db"
DSN = "root:password@tcp(127.0.0.1:3306)/n9e_v6?charset=utf8mb4&parseTime=True&loc=Local&allowNativePasswords=true"
# enable debug mode or not
Debug = false
# unit: s
MaxLifetime = 7200
# max open connections
MaxOpenConns = 150
# max idle connections
MaxIdleConns = 50

[Redis]
# address, ip:port or ip1:port,ip2:port for cluster and sentinel(SentinelAddrs)
Address = "127.0.0.1:6379"
# Username = ""
Password = "password"
# DB = 0
# UseTLS = false
# TLSMinVersion = "1.2"
# standalone cluster sentinel miniredis
RedisType = "miniredis"
# Mastername for sentinel type
# MasterName = "mymaster"
# SentinelUsername = ""
# SentinelPassword = ""

[[Pushgw.Writers]] 
# Url = "http://127.0.0.1:8480/insert/0/prometheus/api/v1/write"
Url = "http://127.0.0.1:9090/api/v1/write"
# Basic auth username
BasicAuthUser = "admin"
# Basic auth password
BasicAuthPass = "password"
# timeout settings, unit: ms
Headers = ["X-From", "n9e"]
Timeout = 10000
DialTimeout = 3000
TLSHandshakeTimeout = 30000
ExpectContinueTimeout = 1000
IdleConnTimeout = 90000

启动夜莺:

bash 复制代码
vim /etc/systemd/system/n9e.service 
[Unit]
Description=Nightingale Monitoring Service
After=network.target
[Service]
Type=simple
ExecStart=/data/n9e/n9e
WorkingDirectory=/data/n9e
Restart=always
RestartSec=5
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=n9e
[Install]
WantedBy=multi-user.target

systemctl daemon-reload 
systemctl start n9e.service

打开浏览器访问 http://localhost:17000。默认用户名是 root,默认密码是 root.2020

至此,整个搭建工作基本完成了,接下来就是细化工作内容的部分了。

三、核心监控数据

3.1 核心监控指标

判断 "网络是否通、服务是否可用" 的核心,告警优先级最高:

指标 含义 告警建议
probe_success 探测是否成功(1 = 成功,0 = 失败) 告警:当值 = 0 且持续 2 次(60 秒),触发 "网络 / 服务不可达" 告警
probe_http_status_code HTTP 响应状态码 告警:值≠200 时触发 "服务响应异常" 告警

3.2 网络时延与性能指标

用于定位 "网络慢" 的具体环节(是 DNS、TCP 连接还是传输问题),区分 "网络故障" 和 "服务端故障":

指标 含义 告警建议
probe_duration_seconds 探测总耗时(秒) 告警:阈值建议(如 > 1 秒),触发 "访问总时延过高" 告警
probe_http_duration_seconds{phase="resolve"}(或probe_dns_lookup_time_seconds DNS 解析耗时 告警:阈值建议(如 > 0.1 秒),触发 "DNS 解析超时 / 过慢" 告警(网关是 IP 直连,该值接近 0,属正常)
probe_http_duration_seconds{phase="connect"} TCP 连接耗时 告警:阈值建议(如 > 0.2 秒),触发 "TCP 连接过慢(网络链路 / 端口问题)" 告警
probe_http_duration_seconds{phase="tls"} TLS 握手耗时(仅 HTTPS 目标有效) 告警:阈值建议(如 > 0.1 秒),触发 "TLS 握手过慢(证书 / SSL 配置问题)" 告警(网关是 HTTP,该值 = 0,无需监控)
probe_http_duration_seconds{phase="processing"} 服务端处理耗时 告警:若该值占总耗时 80% 以上,触发 "服务端处理慢(非网络问题)" 告警
probe_http_duration_seconds{phase="transfer"} 响应数据传输耗时 告警:阈值建议(如 > 0.1 秒),触发 "数据传输过慢(带宽 / 数据包过大)" 告警

如果使用Prometheus的监控告警的话,这里给出Prometheus+Alertmanager+PrometheusAlert方案的实现地址方式:

https://blog.csdn.net/2401_83649605/article/details/152605133?spm=1001.2014.3001.5501

参考告警规则:(github大佬的)

https://github.com/samber/awesome-prometheus-alerts/blob/master/dist/rules/blackbox/blackbox-exporter.yml

我的:(可以将文件直接导入夜莺,并使用夜莺的告警)

bash 复制代码
groups:
- name: BlackboxExporter
  rules:
    # 1. 探测失败告警(减少误报,for=2m)
    - alert: BlackboxProbeFailed
      expr: probe_success == 0
      for: 2m
      labels:
        severity: critical
      annotations:
        summary: "【{{ $labels.target }}】网络/服务不可达"
        description: "探测目标 {{ $labels.target }} 连续失败,当前状态:probe_success={{ $value }}\n所属服务:{{ $labels.service }}"

    # 2. HTTP状态码异常(仅监控200以外的状态码)
    - alert: BlackboxProbeHttpFailure
      expr: probe_http_status_code <= 199 OR probe_http_status_code >= 400
      for: 1m
      labels:
        severity: critical
      annotations:
        summary: "【{{ $labels.target }}】HTTP状态码异常"
        description: "目标 {{ $labels.target }} 返回状态码 {{ $value }},非预期200\n所属服务:{{ $labels.service }}"

    # 3. 总探测耗时过高(全局慢)
    - alert: BlackboxSlowProbe
      expr: avg_over_time(probe_duration_seconds[1m]) > 1
      for: 1m
      labels:
        severity: warning
      annotations:
        summary: "【{{ $labels.target }}】探测总耗时过高"
        description: "目标 {{ $labels.target }} 平均探测耗时 {{ $value | humanizeDuration }},超过阈值1秒\n所属服务:{{ $labels.service }}"

    # 4. 分阶段时延告警:DNS解析慢(仅非IP直连目标有效)
    - alert: BlackboxDnsResolveSlow
      expr: avg_over_time(probe_http_duration_seconds{phase="resolve"}[1m]) > 0.1
      for: 1m
      labels:
        severity: warning
      annotations:
        summary: "【{{ $labels.target }}】DNS解析过慢"
        description: "目标 {{ $labels.target }} DNS解析平均耗时 {{ $value | humanizeDuration }},超过阈值0.1秒\n所属服务:{{ $labels.service }}"

    # 5. 分阶段时延告警:TCP连接慢
    - alert: BlackboxTcpConnectSlow
      expr: avg_over_time(probe_http_duration_seconds{phase="connect"}[1m]) > 0.2
      for: 1m
      labels:
        severity: warning
      annotations:
        summary: "【{{ $labels.target }}】TCP连接过慢"
        description: "目标 {{ $labels.target }} TCP连接平均耗时 {{ $value | humanizeDuration }},超过阈值0.2秒(网络链路/端口问题)\n所属服务:{{ $labels.service }}"

    # 6. 分阶段时延告警:TLS握手慢(仅HTTPS目标,过滤HTTP目标)
    - alert: BlackboxTlsHandshakeSlow
      expr: avg_over_time(probe_http_duration_seconds{phase="tls", probe_http_ssl="1"}[1m]) > 0.1
      for: 1m
      labels:
        severity: warning
      annotations:
        summary: "【{{ $labels.target }}】TLS握手过慢"
        description: "目标 {{ $labels.target }} TLS握手平均耗时 {{ $value | humanizeDuration }},超过阈值0.1秒\n所属服务:{{ $labels.service }}"

3.3 补充指标

用于验证网络 / 协议配置是否符合预期,兜底异常场景,可以根据自身去定义是否使用。

指标 含义 告警建议
probe_http_ssl 是否使用 SSL(1=HTTPS,0=HTTP) 告警:若 HTTPS 目标值 = 0/HTTP 目标值 = 1,触发 "协议类型异常" 告警
probe_tls_version_info{version="TLS 1.3"} TLS 版本(仅 HTTPS 目标) 告警:若版本≠TLS1.2/1.3,触发 "TLS 版本过低(安全风险)" 告警
probe_ssl_last_chain_expiry_timestamp_seconds SSL 证书过期时间(时间戳) 告警:剩余有效期 <7 天,触发 "SSL 证书即将过期" 告警
probe_http_redirects 重定向次数 告警:值 > 1 时触发 "重定向次数过多(网络 / 配置异常)" 告警
probe_ip_protocol IP 协议版本(4=IPv4,6=IPv6) 告警:若值≠预期(如预期 IPv4 但 = 6),触发 "IP 协议版本异常" 告警
相关推荐
青w韵6 小时前
Claude 高级工具使用解析:从上下文优化到程序化调用的工程实践
数据库·windows
Haooog6 小时前
微服务篇面试题(不定时更新)
微服务·面试·架构
Da Da 泓6 小时前
多线程(四)【线程安全问题】
java·开发语言·jvm·学习·安全·多线程·线程安全问题
福尔摩斯张6 小时前
TCP协议深度解析:从报文格式到连接管理(超详细)
linux·c语言·网络·c++·笔记·网络协议·tcp/ip
那我掉的头发算什么6 小时前
【javaEE】保姆级 HTTP 全解析:请求响应 + 状态码 + Fiddler 实操
网络·http·java-ee·fiddler
2501_924064116 小时前
2025年微服务全链路性能瓶颈分析平台对比与最佳实践
微服务·云原生·性能优化·架构
Hello.Reader6 小时前
Flink SQL DROP 语句安全删除 Catalog / Table / DB / View / Function / Model
数据库·sql·flink
luluoluoa6 小时前
科研业绩SCI、EI、会议、CSCD、CSSCI、中文核心、普刊介绍
数据库
liuzhilongDBA6 小时前
论文精读|DBAIOps
数据库·postgresql·dbaiops