跳转至

家庭用电量监控系统 - 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 命名空间

  1. 检查DNS解析
  2. K8s跨命名空间访问需使用完整域名:service-name.namespace.svc.cluster.local
  3. 解决:ConfigMap中 DB_HOST 改为 mysql-svc.server.svc.cluster.local

  4. 检查Service端口和标签

  5. ServiceMonitor通过selector匹配Service的labels
  6. 确保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 同步,请勿在站点侧修改)