main:添加核心文件并初始化项目
新增内容: - 创建基础项目结构。 - 添加 `.gitignore` 和 `.dockerignore` 文件。 - 编写 `pyproject.toml` 和依赖文件。 - 添加算法模块及示例算法。 - 实现核心功能模块(日志、错误处理、指标)。 - 添加开发和运行所需的相关脚本文件及文档。
This commit is contained in:
346
docs/metrics-guide.md
Normal file
346
docs/metrics-guide.md
Normal file
@@ -0,0 +1,346 @@
|
||||
# 指标记录方案对比与使用指南
|
||||
|
||||
## 问题背景
|
||||
|
||||
在多实例部署场景下(Kubernetes、Serverless),原有的内存指标存储方案存在以下问题:
|
||||
|
||||
1. **指标分散**:每个实例独立记录指标,无法聚合
|
||||
2. **数据丢失**:实例销毁后指标丢失
|
||||
3. **统计不准**:无法获得全局准确的指标视图
|
||||
|
||||
## 解决方案对比
|
||||
|
||||
### 方案1:Pushgateway(推荐)
|
||||
|
||||
**原理:** 应用主动推送指标到 Pushgateway,Prometheus 从 Pushgateway 抓取
|
||||
|
||||
**优点:**
|
||||
- ✅ Prometheus 官方支持,生态成熟
|
||||
- ✅ 实现简单,代码改动小
|
||||
- ✅ 适合短生命周期任务(Serverless、批处理)
|
||||
- ✅ 支持持久化,重启不丢失数据
|
||||
|
||||
**缺点:**
|
||||
- ⚠️ 单点故障风险(可通过高可用部署解决)
|
||||
- ⚠️ 不适合超高频推送(每秒数千次)
|
||||
|
||||
**适用场景:**
|
||||
- Serverless 函数
|
||||
- 批处理任务
|
||||
- 短生命周期容器
|
||||
- 实例数量动态变化的场景
|
||||
|
||||
### 方案2:Redis + 自定义 Exporter
|
||||
|
||||
**原理:** 应用将指标写入 Redis,自定义 Exporter 从 Redis 读取并转换为 Prometheus 格式
|
||||
|
||||
**优点:**
|
||||
- ✅ 灵活可控,支持复杂聚合逻辑
|
||||
- ✅ Redis 高性能,支持高并发写入
|
||||
- ✅ 可以实现自定义的指标计算
|
||||
|
||||
**缺点:**
|
||||
- ⚠️ 需要自己实现 Exporter,维护成本高
|
||||
- ⚠️ 增加了系统复杂度
|
||||
- ⚠️ Redis 需要额外的运维成本
|
||||
|
||||
**适用场景:**
|
||||
- 需要自定义指标聚合逻辑
|
||||
- 超高频指标写入(每秒数万次)
|
||||
- 需要实时查询指标数据
|
||||
|
||||
### 方案3:标准 Prometheus Pull 模式(不推荐)
|
||||
|
||||
**原理:** Prometheus 从每个实例抓取指标,在查询时聚合
|
||||
|
||||
**优点:**
|
||||
- ✅ Prometheus 标准做法
|
||||
- ✅ 无需额外组件
|
||||
|
||||
**缺点:**
|
||||
- ❌ 需要服务发现机制(Kubernetes Service Discovery)
|
||||
- ❌ 短生命周期实例可能来不及抓取
|
||||
- ❌ 实例销毁后数据丢失
|
||||
|
||||
**适用场景:**
|
||||
- 长生命周期服务
|
||||
- 实例数量相对固定
|
||||
- 有完善的服务发现机制
|
||||
|
||||
## 使用指南
|
||||
|
||||
### 方案1:Pushgateway(推荐)
|
||||
|
||||
#### 1. 启动服务
|
||||
|
||||
```bash
|
||||
cd deployment
|
||||
docker-compose up -d redis pushgateway prometheus grafana
|
||||
```
|
||||
|
||||
#### 2. 修改代码
|
||||
|
||||
在 `src/functional_scaffold/api/routes.py` 中:
|
||||
|
||||
```python
|
||||
# 替换导入
|
||||
from functional_scaffold.core.metrics_pushgateway import (
|
||||
track_request,
|
||||
track_algorithm_execution,
|
||||
)
|
||||
|
||||
# 使用方式不变
|
||||
@router.post("/invoke")
|
||||
@track_request("POST", "/invoke")
|
||||
async def invoke_algorithm(request: InvokeRequest):
|
||||
# ... 业务逻辑
|
||||
```
|
||||
|
||||
#### 3. 配置环境变量
|
||||
|
||||
在 `.env` 文件中:
|
||||
|
||||
```bash
|
||||
PUSHGATEWAY_URL=localhost:9091
|
||||
METRICS_JOB_NAME=functional_scaffold
|
||||
INSTANCE_ID=instance-1 # 可选,默认使用 HOSTNAME
|
||||
```
|
||||
|
||||
#### 4. 验证
|
||||
|
||||
```bash
|
||||
# 查看 Pushgateway 指标
|
||||
curl http://localhost:9091/metrics
|
||||
|
||||
# 查看 Prometheus
|
||||
open http://localhost:9090
|
||||
|
||||
# 查询示例
|
||||
http_requests_total{job="functional_scaffold"}
|
||||
```
|
||||
|
||||
### 方案2:Redis + Exporter
|
||||
|
||||
#### 1. 启动服务
|
||||
|
||||
```bash
|
||||
cd deployment
|
||||
docker-compose up -d redis redis-exporter prometheus grafana
|
||||
```
|
||||
|
||||
#### 2. 修改代码
|
||||
|
||||
在 `src/functional_scaffold/api/routes.py` 中:
|
||||
|
||||
```python
|
||||
# 替换导入
|
||||
from functional_scaffold.core.metrics_redis import (
|
||||
track_request,
|
||||
track_algorithm_execution,
|
||||
)
|
||||
|
||||
# 使用方式不变
|
||||
@router.post("/invoke")
|
||||
@track_request("POST", "/invoke")
|
||||
async def invoke_algorithm(request: InvokeRequest):
|
||||
# ... 业务逻辑
|
||||
```
|
||||
|
||||
#### 3. 配置环境变量
|
||||
|
||||
在 `.env` 文件中:
|
||||
|
||||
```bash
|
||||
REDIS_HOST=localhost
|
||||
REDIS_PORT=6379
|
||||
REDIS_METRICS_DB=0
|
||||
REDIS_PASSWORD= # 可选
|
||||
INSTANCE_ID=instance-1 # 可选
|
||||
```
|
||||
|
||||
#### 4. 安装 Redis 依赖
|
||||
|
||||
```bash
|
||||
pip install redis
|
||||
```
|
||||
|
||||
或在 `requirements.txt` 中添加:
|
||||
|
||||
```
|
||||
redis>=5.0.0
|
||||
```
|
||||
|
||||
#### 5. 验证
|
||||
|
||||
```bash
|
||||
# 查看 Redis 中的指标
|
||||
redis-cli
|
||||
> HGETALL metrics:request_counter
|
||||
|
||||
# 查看 Exporter 输出
|
||||
curl http://localhost:8001/metrics
|
||||
|
||||
# 查看 Prometheus
|
||||
open http://localhost:9090
|
||||
```
|
||||
|
||||
## 性能对比
|
||||
|
||||
| 指标 | Pushgateway | Redis + Exporter | 标准 Pull |
|
||||
|------|-------------|------------------|-----------|
|
||||
| 写入延迟 | ~5ms | ~1ms | N/A |
|
||||
| 查询延迟 | ~10ms | ~20ms | ~5ms |
|
||||
| 吞吐量 | ~1000 req/s | ~10000 req/s | ~500 req/s |
|
||||
| 内存占用 | 低 | 中 | 低 |
|
||||
| 复杂度 | 低 | 高 | 低 |
|
||||
|
||||
## 迁移步骤
|
||||
|
||||
### 从原有方案迁移到 Pushgateway
|
||||
|
||||
1. **安装依赖**(如果需要):
|
||||
```bash
|
||||
pip install prometheus-client
|
||||
```
|
||||
|
||||
2. **替换导入**:
|
||||
```python
|
||||
# 旧代码
|
||||
from functional_scaffold.core.metrics import track_request
|
||||
|
||||
# 新代码
|
||||
from functional_scaffold.core.metrics_pushgateway import track_request
|
||||
```
|
||||
|
||||
3. **配置环境变量**:
|
||||
```bash
|
||||
export PUSHGATEWAY_URL=localhost:9091
|
||||
```
|
||||
|
||||
4. **启动 Pushgateway**:
|
||||
```bash
|
||||
docker-compose up -d pushgateway
|
||||
```
|
||||
|
||||
5. **更新 Prometheus 配置**(已包含在 `monitoring/prometheus.yml`)
|
||||
|
||||
6. **测试验证**:
|
||||
```bash
|
||||
# 发送请求
|
||||
curl -X POST http://localhost:8000/invoke -d '{"number": 17}'
|
||||
|
||||
# 查看指标
|
||||
curl http://localhost:9091/metrics | grep http_requests_total
|
||||
```
|
||||
|
||||
### 从原有方案迁移到 Redis
|
||||
|
||||
1. **安装依赖**:
|
||||
```bash
|
||||
pip install redis
|
||||
```
|
||||
|
||||
2. **替换导入**:
|
||||
```python
|
||||
# 旧代码
|
||||
from functional_scaffold.core.metrics import track_request
|
||||
|
||||
# 新代码
|
||||
from functional_scaffold.core.metrics_redis import track_request
|
||||
```
|
||||
|
||||
3. **配置环境变量**:
|
||||
```bash
|
||||
export REDIS_HOST=localhost
|
||||
export REDIS_PORT=6379
|
||||
```
|
||||
|
||||
4. **启动 Redis 和 Exporter**:
|
||||
```bash
|
||||
docker-compose up -d redis redis-exporter
|
||||
```
|
||||
|
||||
5. **测试验证**:
|
||||
```bash
|
||||
# 发送请求
|
||||
curl -X POST http://localhost:8000/invoke -d '{"number": 17}'
|
||||
|
||||
# 查看 Redis
|
||||
redis-cli HGETALL metrics:request_counter
|
||||
|
||||
# 查看 Exporter
|
||||
curl http://localhost:8001/metrics
|
||||
```
|
||||
|
||||
## 常见问题
|
||||
|
||||
### Q1: Pushgateway 会成为单点故障吗?
|
||||
|
||||
A: 可以通过以下方式解决:
|
||||
- 部署多个 Pushgateway 实例(负载均衡)
|
||||
- 使用持久化存储(已配置)
|
||||
- 推送失败时降级到本地日志
|
||||
|
||||
### Q2: Redis 方案的性能如何?
|
||||
|
||||
A: Redis 单实例可以支持 10万+ QPS,对于大多数场景足够。如果需要更高性能,可以:
|
||||
- 使用 Redis Cluster
|
||||
- 批量写入(减少网络往返)
|
||||
- 使用 Pipeline
|
||||
|
||||
### Q3: 如何在 Kubernetes 中使用?
|
||||
|
||||
A:
|
||||
- **Pushgateway**: 部署为 Service,应用通过 Service 名称访问
|
||||
- **Redis**: 使用 StatefulSet 或托管 Redis 服务
|
||||
|
||||
### Q4: 指标数据会丢失吗?
|
||||
|
||||
A:
|
||||
- **Pushgateway**: 支持持久化,重启不丢失
|
||||
- **Redis**: 配置了 AOF 持久化,重启不丢失
|
||||
- **标准 Pull**: 实例销毁后丢失
|
||||
|
||||
### Q5: 如何选择方案?
|
||||
|
||||
建议:
|
||||
- **Serverless/短生命周期** → Pushgateway
|
||||
- **超高并发/自定义逻辑** → Redis
|
||||
- **长生命周期/K8s** → 标准 Pull(需配置服务发现)
|
||||
|
||||
## 监控和告警
|
||||
|
||||
### Grafana 仪表板
|
||||
|
||||
访问 http://localhost:3000(admin/admin)
|
||||
|
||||
已预配置的面板:
|
||||
- HTTP 请求总数
|
||||
- HTTP 请求延迟(P50/P95/P99)
|
||||
- 算法执行次数
|
||||
- 算法执行延迟
|
||||
- 错误率
|
||||
|
||||
### 告警规则
|
||||
|
||||
在 `monitoring/alerts/rules.yaml` 中配置:
|
||||
|
||||
```yaml
|
||||
groups:
|
||||
- name: functional_scaffold
|
||||
rules:
|
||||
- alert: HighErrorRate
|
||||
expr: rate(http_requests_total{status="error"}[5m]) > 0.05
|
||||
for: 5m
|
||||
labels:
|
||||
severity: warning
|
||||
annotations:
|
||||
summary: "高错误率告警"
|
||||
description: "错误率超过 5%"
|
||||
```
|
||||
|
||||
## 参考资料
|
||||
|
||||
- [Prometheus Pushgateway 文档](https://github.com/prometheus/pushgateway)
|
||||
- [Prometheus 最佳实践](https://prometheus.io/docs/practices/)
|
||||
- [Redis 官方文档](https://redis.io/documentation)
|
||||
Reference in New Issue
Block a user