Files
iotlcm/docs/06-故障排查.md
T
MiFaZhan 503fe59fe7 docs: 部署文档
- README:项目概览、快速开始、目录结构、重要提示
- 01 环境准备:硬件/系统/Docker 版本、镜像仓库、端口、防火墙、可选外部服务
- 02 配置说明:.env 必填与可选项、10 份应用配置逐项说明、启动前自检
- 03 启动与验证:首次初始化流程、状态检查、6 步验证清单、首次登录必做项
- 04 可选服务:挡板 onelink-mock、飞书 bot、自带 nginx(含 HTTPS)、组合启动
- 05 升级与备份:版本固定、升级回滚、备份脚本与恢复、日志清理、监控指标
- 06 故障排查:启动/功能/性能/网络四类共 20 个问题
2026-10-28 13:54:39 +08:00

7.5 KiB
Raw Blame History

故障排查

通用排查步骤

# 1. 看容器状态
docker compose ps

# 2. 看某个服务的日志
docker compose logs --tail=100 <服务名>

# 3. 跟随日志
docker compose logs -f <服务名>

# 4. 进容器排查
docker compose exec <服务名> sh

启动类

MySQL 一直不 healthy

现象:iotlcm-mysql 显示 Up (healthrestarting) 或一直 starting,其余服务不启动。

排查:

docker compose logs mysql | tail -50
日志关键词 原因 处理
Access denied root 口令与旧数据卷中的不一致 改 .env 的 MYSQL_ROOT_PASSWORD 与卷内一致,或清空 data/mysql 重建
Can't create/write to file 目录权限问题 sudo chown -R 999:999 data/mysql
No space left on device 磁盘满 清理磁盘
mysqld: Can't open shared library 架构不匹配 确认镜像与宿主机架构一致

schema 初始化失败

现象:MySQL 起来了,但表数量不对,或日志中有 SQL 报错。

排查:

docker compose logs mysql | grep -iE 'error|ERROR' | head -30

常见原因:

原因 处理
MYSQL_APP_PASSWORD 未设置,04-users.sh 退出 在 .env 补上后清空 data/mysql 重建
MYSQL_ADMIN_PASSWORD 未设置,05-reset-passwords.sh 退出 同上
SQL 脚本本身语法问题 单独执行该脚本定位,见 schema/README

::: warning 改脚本后必须清空数据卷 MySQL 只在 data/mysql 为空时执行 schema/。文件改了不会自动重跑:

docker compose down && sudo rm -rf ./data/mysql && docker compose up -d

:::

业务服务反复重启

排查:

docker compose logs --tail=80 admin-svr
报错 原因 处理
possible config files "config" not found config/ 目录不存在或挂载失败 cp -r config.example config 并确认 config/admin-svr/config.yaml 存在
dial tcp mysql:3306: connect: connection refused MySQL 未就绪 等 MySQL healthy,或检查 depends_on 是否生效
Access denied for user 'u_iotlcm' 应用账号密码与数据库内不一致 确认 .env 的 MYSQL_APP_PASSWORD 与初始化时一致;改过则需重建库
panic: unsupported provider xxx 数据库通道模板与镜像版本不匹配 确认镜像版本与 schema 版本配套

功能类

登录后提示未授权 / 接口 401

原因:JWT_SIGNING_KEY 在服务间不一致。

处理:确认 admin-svr、openapi、app-server 三份配置里的 jwt.signingKey 都引用 ${JWT_SIGNING_KEY},且 .env 里有值。改完重启三个服务:

docker compose restart admin-svr openapi app-server

登录成功但页面空白 / 菜单不显示

排查:

  1. 浏览器 F12 看 Network 有无 4xx/5xx
  2. 检查菜单数据:
docker compose exec mysql sh -c \
  'mysql -uroot -p"$MYSQL_ROOT_PASSWORD" db_iotlcm -e "SELECT COUNT(*) FROM sys_menu WHERE status=0;"'

菜单为 0 说明种子数据未导入,需重建库。

  1. 检查角色菜单关联:
docker compose exec mysql sh -c \
  'mysql -uroot -p"$MYSQL_ROOT_PASSWORD" db_iotlcm -e "SELECT COUNT(*) FROM sys_role_menu;"'

卡信息页通道列空白 / 筛选无选项

原因:Mock 通道未插入,或通道数据缺失。

处理:

docker compose exec mysql sh -c \
  'mysql -uroot -p"$MYSQL_ROOT_PASSWORD" db_iotlcm -e "SELECT channel_id, channel_name FROM t_sim_channels;"'

为空则手工执行种子脚本:

docker compose exec -T mysql sh -c \
  'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD" db_iotlcm' < schema/08-seed-mock-channel.sql

批次执行一直失败

排查顺序:

  1. 挡板是否启动(无真实运营商时)
docker compose ps | grep onelink-mock
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8080/api.json

未启动则:docker compose --profile with-mock up -d

  1. worker-svr 是否连上 RabbitMQ
docker compose logs worker-svr | grep -i 'rabbit\|amqp' | tail -20
  1. upstream-chan 是否能连到上游
docker compose logs upstream-chan --tail=50
  1. 运营商是否限流

看 worker-svr 日志中是否有 rate limit、429、12021 等错误。检查 batch.inbound.upstreamRateLimit 配置的 QPS 是否超过上游配额。

历史流量查询无数据

原因:TDengine 未配置或未连接。

处理:

docker compose logs worker-svr | grep -i 'tdengine\|taos' | tail -20

确认 .env 中 TDENGINE_HOST 等变量已填,且 TDengine 的 WebSocket 端口(默认 6041)可达:

docker compose exec worker-svr sh -c 'nc -zv $TDENGINE_HOST $TDENGINE_PORT'

不用该功能时留空即可,不影响主流程。

短信发不出去

排查:

# 1. 短信服务健康
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:11190/healthz

# 2. 服务日志
docker compose logs sms --tail=50
报错 原因
InvalidAccessKeyId .env 里 AK 未填或错误
isv.SMS_SIGNATURE_ILLEGAL signName 与服务商审核的签名不一致
isv.SMS_TEMPLATE_ILLEGAL 模板 ID 未在服务商侧审核通过
缺少 config.templateId 场景模板库未配置,调用方需自带 templateId

图片上传失败 / 图片不显示

原因:data/upload 目录权限或挂载问题。

处理:

ls -la data/upload/
sudo chown -R 1000:1000 data/upload
docker compose restart admin-svr admin-ui

性能类

CPU 被 worker-svr 打满

原因:定时任务开启了全量同步,大量卡片并发查询上游。

处理:

  1. 降低并发:
batch:
  inbound:
    upstreamConcurrency: 50     # 从 300 降低
    upstreamBatchSize: 1
  1. 降低限流 QPS,与上游配额匹配

  2. 演示/试用环境建议直接停用定时任务:

docker compose exec mysql sh -c \
  'mysql -uroot -p"$MYSQL_ROOT_PASSWORD" db_iotlcm -e "UPDATE sys_job SET status=1;"'

种子数据中定时任务默认已全部停用(status=1)。

磁盘持续增长

按占用从大到小排查:

du -sh data/* | sort -rh
目录 处理
data/logs 清理旧日志,见 升级与备份 的日志清理
data/upload 检查是否有异常大的上传文件
data/mysql 数据库增长正常,关注 binlog:docker compose exec mysql du -sh /var/lib/mysql
data/redis AOF 文件,正常

网络类

容器间无法互访

# 查看网络
docker network inspect iotlcm-network

# 从容器内测试
docker compose exec admin-svr sh -c 'nc -zv mysql 3306'

服务名即主机名,配置里应使用 mysql:3306、redis:6379 这样的形式,不要写 127.0.0.1。

宿主机访问不了 127.0.0.1 绑定的服务

admin-svr、admin-ui、openapi、app-server、app-web、docs 默认只绑定 127.0.0.1,仅本机可访问。对外访问需:

  1. 用 --profile with-nginx 启动反向代理,或
  2. 在宿主机配置 nginx 转发到 127.0.0.1:<端口>

不建议直接把端口改成 0.0.0.0 暴露到公网。

获取帮助信息

排查时附上这些信息便于定位:

# 版本信息
docker compose version
docker version --format '{{.Server.Version}}'

# 服务状态
docker compose ps

# 相关服务日志
docker compose logs --tail=200 <服务名>

# 磁盘与内存
df -h
free -h