家庭用电量监控系统 - FAQ 常见问题与解决方案¶
本文档汇总项目开发与运维过程中遇到的所有问题、根因分析及解决方案,供后续排查参考。
目录¶
一、OCR识别相关¶
Q1: 火山方舟SDK调用失败,提示模块不存在¶
现象:使用 volcengine Python SDK调用视觉OCR时报 ModuleNotFoundError 或版本不兼容。
根因:volcengine SDK的 visual_ark 模块存在版本兼容性问题,不同版本API接口不一致。
解决方案:
- 放弃SDK,改用 REST API直接调用(requests库)
- 配置 ARK_API_KEY 和 ARK_BASE_URL,通过HTTP POST请求调用
- 兼容OpenAI SDK格式的接口(/api/v3/chat/completions)
参考配置:
ARK_API_KEY=ark-xxx
ARK_BASE_URL=https://ark.cn-beijing.volces.com/api/v3
ARK_MODEL=doubao-seed-2-0-mini-260428
Q2: OCR识别模型不存在或无访问权限(Error 404)¶
现象:调用API返回 404 InvalidEndpointOrModel.NotFound。
根因: - 模型名称配置错误 - 未在火山方舟控制台开通对应模型的接入点
解决方案:
1. 登录火山方舟控制台 → 模型广场
2. 开通可用模型(推荐:doubao-seed-2-0-mini-260428)
3. 创建接入点(Endpoint),获取Endpoint ID
4. 更新 .env 中的 ARK_MODEL 配置
Q3: 图片扫描重复调用API,浪费配额¶
现象:Pics目录下图片越来越多,每次都全部识别一遍。
根因:未记录已处理文件,也没有只处理最新图片的逻辑。
解决方案:
- 使用 .processed_img.txt 文件记录已处理的图片文件名
- 按文件 ctime 降序排序,只取最新的N张未处理图片
- 通过 MAX_SCAN_COUNT 环境变量控制每次扫描数量(默认1张)
关键代码(file_scan_module.py):
# 按ctime降序排序,只取最新N张未处理图片
unprocessed = [f for f in all_files if f.name not in processed_set]
unprocessed.sort(key=lambda x: x.stat().st_ctime, reverse=True)
to_process = unprocessed[:max_count]
二、数据库相关¶
Q4: MySQL连接失败(Can't connect to MySQL server)¶
现象:Python脚本连接MySQL时报 Can't connect to MySQL server on 'localhost'。
根因:.env 中 DB_HOST 配置为 localhost,但MySQL运行在远程服务器或K8s集群中。
解决方案:
- 更新 DB_HOST 为正确的MySQL服务器IP或域名
- K8s跨命名空间访问使用格式:mysql-svc.server.svc.cluster.local
Q5: 跨年时阶梯电费没有重置¶
现象:2027年1月1日的数据,年累计用电量继续累加,没有从0开始。
根因:阶梯电价计算逻辑只按当前年份简单累加,未处理跨年重置。
解决方案:
- 修改 db_electric_module.py 中的阶梯计算逻辑
- 当检测到记录日期的年份与上一条记录不同时,年累计重置为0
- 年初累计基线(YEAR_CUMULATIVE_BASE)只在数据库最早记录的年份生效
关键逻辑:
if last_record and last_year != current_year:
# 跨年,年累计重置
year_cumulative_kwh = daily_kwh
year_cumulative_cost = daily_cost
Q6: 数据重复入库怎么办¶
现象:同一张图片被多次识别,导致同一天的数据重复插入。
根因:没有去重机制,直接INSERT会导致主键冲突或重复数据。
解决方案:
- 使用 INSERT ... ON DUPLICATE KEY UPDATE 语法
- record_date 设为主键,同一天的数据更新而非插入
- 配合 .processed_img.txt 防止同一图片重复处理
三、Prometheus采集相关¶
Q7: PushGateway不支持自定义时间戳¶
现象:向PushGateway推送带时间戳的指标时报错:
pushed metrics must not have timestamps
根因:PushGateway设计上不支持推送带时间戳的指标,时间戳由PushGateway接收时自动添加。
解决方案:
- 放弃PushGateway方案,改用 自定义Electric Exporter
- Exporter从MySQL查询数据,通过 /metrics 端点暴露指标
- Prometheus通过ServiceMonitor定期抓取,抓取时间即为时间戳
架构调整:
之前:Python脚本 → PushGateway → Prometheus
现在:MySQL → Electric Exporter → Prometheus(主动抓取)
Q8: Prometheus拒绝历史数据(out of bounds)¶
现象:导入历史数据块时报错:
Error on ingesting samples that are too old or are too far into the future
根因:Prometheus TSDB有时间窗口限制,默认只接受近期数据。
尝试过的方案(均未完全成功):
1. 添加 --storage.tsdb.min-time 启动参数 → Prometheus Operator会覆盖
2. 使用promtool导入TSDB块 → 块被标记为obsolete并自动删除
3. 修改块 meta.json 的maxTime → 临时生效但不稳定
最终方案: - Grafana改用 MySQL直查 方案,不依赖Prometheus存储历史数据 - Prometheus只保留实时指标,用于告警和实时监控
Q9: Prometheus抓取不到Electric Exporter指标¶
现象:Electric Exporter部署后,Prometheus的Targets列表中找不到。
根因排查步骤:
1. 检查ServiceMonitor是否与Prometheus在同一命名空间
- ServiceMonitor需要和Prometheus CRD在同一namespace才能被发现
- 解决:将Electric Exporter从 server 命名空间移到 monitoring 命名空间
- 检查DNS解析
- K8s跨命名空间访问需使用完整域名:
service-name.namespace.svc.cluster.local -
解决:ConfigMap中
DB_HOST改为mysql-svc.server.svc.cluster.local -
检查Service端口和标签
- ServiceMonitor通过selector匹配Service的labels
- 确保Service的port名称与ServiceMonitor一致
Q10: Prometheus TSDB数据损坏,所有scrape报错¶
现象:Prometheus所有targets都报 out of bounds 错误,无法入库任何新数据。
根因:之前导入历史数据块的操作导致TSDB元数据损坏,时间边界异常。
解决方案:
1. 缩容Prometheus StatefulSet到0:
bash
kubectl scale sts prometheus-kube-prometheus-prometheus -n monitoring --replicas=0
2. 创建临时Pod挂载PVC,清空所有数据:
bash
kubectl apply -f debug-pod.yaml
kubectl exec -it debug-pod -- rm -rf /data/*
3. 恢复Prometheus副本数:
bash
kubectl scale sts prometheus-kube-prometheus-prometheus -n monitoring --replicas=1
4. 等待Prometheus重新初始化TSDB
四、Grafana展示相关¶
Q11: Grafana面板显示 "No data"¶
现象:所有面板都显示"No data",但数据库中有数据。
根因排查: 1. Prometheus数据源无历史数据 → 改用MySQL数据源直查 2. Grafana重启后配置丢失 → 配置Grafana持久化存储 3. 数据源未正确配置 → 检查MySQL数据源连接
解决方案:
- Grafana使用 MySQL数据源 直接查询数据库
- SQL查询使用 $__timeFilter(record_date) 宏处理时间范围
- 配置Grafana NFS持久化,确保配置不丢失
Q12: 单位显示不符合中文习惯(currencyCNY、kWh)¶
现象:
- 电费显示 currencyCNY 而不是 ¥ 或 "元"
- 大数字自动显示为K/M缩写(如 2.3K 而不是 2347)
- 长辈看不懂英文字符
根因:Grafana的单位系统是国际化的,中文单位支持有限。
解决方案:
1. 单位改为 none:不显示任何单位后缀,避免K缩写和英文单位
2. 通过标题显示中文单位:如 "当月累计电费(元)"
3. SQL字段别名添加单位:如 AS "日用电量(度)"
4. 小数点保留1位:ROUND(字段, 1) 四舍五入
注意:直接将unit设为自定义字符串会导致数据不显示(Grafana无法识别的unit会破坏渲染)。
Q13: 柱状图上方不显示数值标签¶
现象:barchart类型面板,设置了showValue但柱子顶部没有数字。
根因:Grafana的 barchart 类型和 timeseries 类型的数据标签配置方式不同。
解决方案:
- 使用 timeseries 类型 + drawStyle: bars 实现柱状图
- 在fieldConfig.overrides中启用showValue:
json
"overrides": [
{
"matcher": {"id": "byName", "options": "*"},
"properties": [
{"id": "custom.showValue", "value": true},
{"id": "custom.valueMode", "value": "color"}
]
}
]
Q14: Grafana重启后配置丢失(No data)¶
现象:Grafana Pod重启后,数据源和Dashboard都没了,面板全显示No data。
根因:Grafana使用 emptyDir 作为存储,Pod重启后数据全部丢失。
解决方案: 1. 创建NFS PV和PVC用于Grafana数据持久化 2. 修改Grafana Deployment,将storage从emptyDir改为persistentVolumeClaim 3. 重新配置数据源和Dashboard(持久化后只需配置一次)
五、Kubernetes部署相关¶
Q15: Prometheus Operator不支持additionalArgs字段¶
现象:在Prometheus CRD中添加 additionalArgs 想修改启动参数,但Operator报错。
根因:旧版本的Prometheus Operator(如kube-prometheus-stack 35.x)不支持 additionalArgs 字段。
解决方案: - 升级 kube-prometheus-stack 到较新版本(如45.x) - 或者直接修改StatefulSet(不推荐,Operator reconcile会覆盖)
升级命令:
helm upgrade prometheus kube-prometheus-stack/kube-prometheus-stack \
--version 45.16.0 \
-f values.yaml \
-n monitoring
Q16: Alertmanager镜像拉取失败(ImagePullBackOff)¶
现象:升级后Alertmanager Pod状态为ImagePullBackOff。
根因:values文件中镜像配置错误,重复添加了 quay.io/ 前缀。
解决方案: - 移除自定义的镜像配置,使用Chart默认镜像 - 或修正镜像路径,确保正确
Q17: PVC卡在Terminating状态无法删除¶
现象:kubectl delete pvc 后PVC一直处于Terminating状态。
根因:PVC仍被Pod挂载,或finalizer未正确清理。
解决方案:
1. 先删除使用该PVC的Pod/StatefulSet
2. 如果还是卡住,强制移除finalizer:
bash
kubectl patch pvc pvc-name -n namespace -p '{"metadata":{"finalizers":null}}'
Q18: Prometheus Operator被暂停后忘记恢复¶
现象:修改StatefulSet后,过一会儿又被还原了。
根因:Prometheus Operator会持续reconcile,确保实际状态与CRD一致。
规避方法: - 临时修改:缩容Operator Deployment到0 - 永久修改:通过Prometheus CRD配置,不要直接改StatefulSet - 修改完成后记得恢复Operator副本数
六、NFS持久化相关¶
Q19: NFS挂载后权限不足(Permission denied)¶
现象:Pod启动失败,日志显示无法写入NFS目录。
根因:NFS目录的用户ID/组ID与容器内运行用户不匹配。
解决方案:
1. 在NFS服务器上修改目录权限:
bash
chmod 777 /data/softdata/prometheus
chown 1000:2000 /data/softdata/prometheus
2. 或创建临时Pod挂载PVC后修改权限:
bash
kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
name: fix-perms
namespace: monitoring
spec:
volumes:
- name: data
persistentVolumeClaim:
claimName: prometheus-data-nfs-pvc
containers:
- name: fix
image: busybox
command: ["sh", "-c", "chmod 777 /data && chown 1000:2000 /data && sleep 3600"]
volumeMounts:
- name: data
mountPath: /data
EOF
Q20: NFS stale file handle错误¶
现象:Pod日志报 Stale file handle 错误,无法访问NFS数据。
根因:NFS服务器端文件句柄失效(如NFS服务重启、目录重建等)。
解决方案:
- 重启Pod,重新挂载NFS卷:
bash
kubectl delete pod -l app=prometheus -n monitoring
- 如果频繁出现,检查NFS服务器稳定性
Q21: PVC一直Pending,无法绑定PV¶
现象:PVC状态一直是Pending,不绑定PV。
排查步骤:
1. 检查PV和PVC的 accessModes 是否匹配(如都是 ReadWriteMany)
2. 检查 storageClassName 是否一致(或都是空字符串)
3. 检查PV的 volumeName 是否正确配置
4. 检查NFS服务器IP和路径是否正确
常见原因:
- PV和PVC不在同一命名空间(但PV是集群级资源,所以不是这个问题)
- persistentVolumeReclaimPolicy 设置问题
- StorageClass的provisioner有问题
七、代码开发相关¶
Q22: f-string语法错误(SyntaxError)¶
现象:Python运行时报 SyntaxError: f-string: expecting '}'。
根因:f-string中嵌套了引号或大括号,导致解析错误。
解决方案:
- 字符串拼接使用 .format() 方法代替复杂f-string
- 或使用单双引号交替避免冲突
- 或将复杂逻辑提取为变量
Q23: 所有异常都要捕获吗?怎么记录日志?¶
规范要求:
- 所有异常必须使用 try-except 捕获
- 禁止裸 except:,必须指定异常类型
- 使用项目的 logger_module 记录日志
- 关键操作必须记录开始和完成日志
示例:
try:
logger.info("开始执行XX操作")
result = do_something()
logger.info(f"XX操作完成,结果: {result}")
except Exception as e:
logger.error(f"XX操作失败: {str(e)}")
logger.error(traceback.format_exc())
raise
Q24: 环境变量怎么管理?有硬编码限制吗?¶
规范要求:
- 所有敏感信息(密码、API密钥)必须通过环境变量管理
- 使用 .env 文件存储配置,不提交到版本控制
- 使用 python-dotenv 库加载环境变量
- 禁止在代码中硬编码密码、密钥等敏感信息
示例:
from dotenv import load_dotenv
import os
load_dotenv()
DB_HOST = os.getenv("DB_HOST", "localhost")
DB_PASSWORD = os.getenv("DB_PASSWORD", "")
附录:问题排查速查表¶
| 症状 | 优先排查 | 常见原因 |
|---|---|---|
| OCR识别失败 | API密钥、模型名称 | 密钥错误/模型未开通 |
| 数据库连不上 | DB_HOST、网络 | IP错误/防火墙 |
| Prometheus无数据 | Targets状态、Exporter日志 | ServiceMonitor未发现 |
| Grafana No data | 数据源配置、SQL语法 | 数据源错/查询错 |
| Pod启动失败 | describe pod、events | 镜像拉取/权限/配置错 |
| NFS挂载失败 | PV/PVC描述、目录权限 | 路径错/权限不足 |
| 定时任务不执行 | crontab -l、日志文件 | 路径错/环境变量 |
文档版本:v1.0 最后更新:2026年7月
来源:
/home/rain/Documents/electricity_monitoring/docs/FAQ.md| 最后更新:2026-07-24 21:57(由build/sync.py同步,请勿在站点侧修改)