验证码识别成功率跌到六成,你是靠告警第一时间发现,还是等客户投诉了才回头翻日志?很多接入 CaptchaAI 的团队一开始都没接监控,等余额耗尽、类型不支持、网络超时这些故障混在一起,出问题都定位不到根因。Prometheus 采集指标,Grafana 可视化并告警,是目前最主流的开源组合。本文给出可以直接落地的指标定义、导出器代码、Docker Compose 部署清单、PromQL 查询和告警规则。
需要采集哪些指标
| 指标名称 | 类型 | 说明 |
|---|---|---|
captcha_solves_total |
计数器 | 识别请求总次数 |
captcha_solves_success |
计数器 | 识别成功次数 |
captcha_solves_errors |
计数器 | 失败次数(按错误类型细分) |
captcha_solve_duration |
直方图 | 识别耗时分布 |
captcha_balance |
仪表 | 当前账户余额 |
captcha_queue_length |
仪表 | 队列中待处理的任务数 |
用 Python 写一个指标导出器
下面的 metrics.py 用 prometheus_client 给识别逻辑加上计数器、直方图和仪表三类指标:
# metrics.py
import time
import requests
from prometheus_client import (
Counter, Histogram, Gauge, start_http_server,
)
# Define metrics
SOLVES_TOTAL = Counter(
"captcha_solves_total",
"Total CAPTCHA solve attempts",
["method"],
)
SOLVES_SUCCESS = Counter(
"captcha_solves_success",
"Successful CAPTCHA solves",
["method"],
)
SOLVES_ERRORS = Counter(
"captcha_solves_errors",
"Failed CAPTCHA solves",
["method", "error_code"],
)
SOLVE_DURATION = Histogram(
"captcha_solve_duration_seconds",
"CAPTCHA solve duration in seconds",
["method"],
buckets=[5, 10, 15, 20, 30, 45, 60, 90, 120],
)
BALANCE = Gauge(
"captcha_balance_usd",
"Current CaptchaAI account balance in USD",
)
QUEUE_LENGTH = Gauge(
"captcha_queue_length",
"Number of pending CAPTCHA tasks",
)
class InstrumentedSolver:
"""Solver with Prometheus metric instrumentation."""
def __init__(self, api_key):
self.api_key = api_key
self.base = "https://ocr.captchaai.com"
def solve(self, method, **params):
"""Solve CAPTCHA with metric collection."""
SOLVES_TOTAL.labels(method=method).inc()
start = time.time()
try:
token = self._do_solve(method, params)
duration = time.time() - start
SOLVES_SUCCESS.labels(method=method).inc()
SOLVE_DURATION.labels(method=method).observe(duration)
return token
except Exception as e:
error_code = str(e)[:30]
SOLVES_ERRORS.labels(
method=method, error_code=error_code,
).inc()
raise
def update_balance(self):
"""Fetch and update balance metric."""
resp = requests.get(f"{self.base}/res.php", params={
"key": self.api_key,
"action": "getbalance",
"json": 1,
}, timeout=15)
balance = float(resp.json()["request"])
BALANCE.set(balance)
return balance
def _do_solve(self, method, params, timeout=120):
data = {"key": self.api_key, "method": method, "json": 1}
data.update(params)
resp = requests.post(
f"{self.base}/in.php", data=data, timeout=30,
)
result = resp.json()
if result.get("status") != 1:
raise RuntimeError(result.get("request"))
task_id = result["request"]
start = time.time()
while time.time() - start < timeout:
time.sleep(5)
resp = requests.get(f"{self.base}/res.php", params={
"key": self.api_key,
"action": "get",
"id": task_id,
"json": 1,
}, timeout=15)
data = resp.json()
if data["request"] != "CAPCHA_NOT_READY":
if data.get("status") == 1:
return data["request"]
raise RuntimeError(data["request"])
raise TimeoutError("Solve timeout")
# Start metrics server on port 8000
start_http_server(8000)
print("Metrics server running on :8000/metrics")
solve() 会自动记录次数、耗时和错误码;update_balance() 建议丢进定时任务,每隔几分钟同步一次余额。访问 http://localhost:8000/metrics 即可看到原始指标文本。
配置 Prometheus 抓取任务
把导出器地址写进 prometheus.yml,让 Prometheus 每 10 秒抓一次:
# prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: "captcha-solver"
static_configs:
- targets: ["solver-app:8000"]
scrape_interval: 10s
用 Docker Compose 一次性起 Prometheus + Grafana
不想分开装三套服务时,用下面的 docker-compose.yml 一条命令把 solver、Prometheus、Grafana 一起拉起来:
# docker-compose.yml
version: "3.8"
services:
solver:
build: .
environment:
- CAPTCHAAI_KEY=${CAPTCHAAI_KEY}
ports:
- "8000:8000"
prometheus:
image: prom/prometheus:latest
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana-data:/var/lib/grafana
volumes:
grafana-data:
启动后 Prometheus 在 :9090,Grafana 在 :3000(默认密码来自 GF_SECURITY_ADMIN_PASSWORD,上生产前记得改掉)。
Grafana 面板常用 PromQL
刚接入时不用做全部指标,先做四块就够判断"服务是否正常":成功率、平均耗时、错误分布、账户余额。规模上来后再补队列深度和吞吐量。
识别成功率
成功次数除以总次数,乘以 100:
rate(captcha_solves_success[5m])
/ rate(captcha_solves_total[5m]) * 100
平均识别耗时
_sum 除以 _count,得到窗口内平均耗时:
rate(captcha_solve_duration_seconds_sum[5m])
/ rate(captcha_solve_duration_seconds_count[5m])
按错误类型统计
按 error_code 分组,快速看出余额不足、超时还是接口错误占大头:
sum by (error_code) (
rate(captcha_solves_errors[5m])
)
余额趋势
仪表类型的指标可以直接画出余额随时间变化的曲线:
captcha_balance_usd
P95 识别耗时
P95 比平均值更能反映最差情况下的体验:
histogram_quantile(0.95,
rate(captcha_solve_duration_seconds_bucket[5m])
)
设置告警规则
把下面的规则加进 alert_rules.yml:余额过低、错误率过高、P95 耗时过长都能第一时间推到 IM 群或邮箱:
# alert_rules.yml
groups:
- name: captcha-alerts
rules:
- alert: LowBalance
expr: captcha_balance_usd < 5
for: 5m
labels:
severity: warning
annotations:
summary: "CaptchaAI balance below $5"
- alert: HighErrorRate
expr: |
rate(captcha_solves_errors[5m])
/ rate(captcha_solves_total[5m]) > 0.1
for: 10m
labels:
severity: critical
annotations:
summary: "CAPTCHA error rate above 10%"
- alert: SlowSolveTime
expr: |
histogram_quantile(0.95,
rate(captcha_solve_duration_seconds_bucket[5m])
) > 60
for: 15m
labels:
severity: warning
annotations:
summary: "P95 solve time exceeds 60s"
国内团队部署时的几个细节
Prometheus、Grafana、solver 都部署在国内服务器(阿里云、腾讯云或自建机房)时,监控栈本身不涉及跨境访问。但 solver 调用 CaptchaAI 接口走国际链路,captcha_solve_duration 里偶尔出现的长尾耗时,很多时候是跨境网络抖动,未必是识别变慢。建议打上 method 标签,用 sum by (method) 把 reCAPTCHA、Turnstile、GeeTest v3 的耗时和成功率分开看。安装依赖慢时可加国内镜像:pip install -i https://pypi.tuna.tsinghua.edu.cn/simple prometheus_client requests。
常见故障排查
| 现象 | 原因 | 处理方式 |
|---|---|---|
/metrics 没有数据 |
导出器没启动 | 确认已调用 start_http_server(8000) |
| Prometheus target 显示 Down | 抓取地址不对 | 检查 Docker 网络和端口映射 |
| Grafana 面板没有数据 | 没配置 Prometheus 数据源 | 在 Grafana 里添加 Prometheus 数据源 |
| 服务重启后指标归零 | 计数器重置是预期行为 | 查询时用 rate(),不要直接读原始计数器 |
常见问题
Prometheus 监控会拖慢验证码识别本身吗?
不会。prometheus_client 每次操作开销不到 1 毫秒,10-15 秒抓取一次对识别速度没有可感知的影响。
多个 worker 同时跑,Grafana 上的成功率数字还准吗?
准。每个 worker 暴露自己的 /metrics,Prometheus 抓取所有目标,rate()、sum() 默认就是跨实例聚合。
reCAPTCHA、Turnstile、GeeTest v3 混着用,怎么在同一个面板里分开看?
给调用打上 method 标签,查询时用 sum by (method) 筛选,就能把不同类型的成功率、耗时拆开对比。
LowBalance 告警阈值设成 $5,是不是太低了?
$5 只是示例值,按日均消耗调整。日均消耗 $20 左右的账户,建议提到 $30-50,避免半夜余额耗尽却没人处理。
Prometheus 的数据要保留多久,会不会把磁盘写满?
默认保留 15 天,占用通常几百 MB 到几 GB。要留更久,可在启动参数加 --storage.tsdb.retention.time=90d。
相关指南
把这套监控接进你的生产环境——现在试用 CaptchaAI。