Files
iotlcm/docs/deploy/troubleshooting.md
T
MiFaZhan 6d3b8dab43 docs: 部署手册补充时序库已内置
部署编排已加入 TDengine(tdengine 3.3.6.13)与 tdengine-init 建库建表服务,
文档同步:
- prerequisites:外部依赖章节把 TDengine 从「可选/需自行部署」改为「已内置」,
  列出两个库的分片/保留/超级表,并说明与生产的版本差异
- troubleshooting:历史流量无数据一节改为常见原因表(init 未成功、库表缺失、地址错误),
  给出对应的排查命令与处理方式
2026-10-30 10:03:12 +08:00

254 lines
7.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: 故障排查
description: 部署与运行中的常见问题及处理
outline: deep
---
# 故障排查
## 通用排查
```bash
docker compose ps # 容器状态
docker compose logs --tail=100 <服务> # 最近日志
docker compose logs -f <服务> # 跟随日志
docker compose exec <服务> sh # 进容器
```
## 启动类
### MySQL 一直不 healthy
**现象**:`iotlcm-mysql` 反复重启或一直 `starting`,其余服务不启动。
```bash
docker compose logs mysql | tail -50
```
| 日志关键词 | 原因 | 处理 |
| --- | --- | --- |
| `Access denied` | root 口令与旧数据卷不一致 | 改 `docker-compose.yml` 与卷内一致,或清空 `data/mysql` 重建 |
| `Can't create/write to file` | 目录权限 | `sudo chown -R 999:999 data/mysql` |
| `No space left on device` | 磁盘满 | 清理磁盘 |
| `Can't open shared library` | 架构不匹配 | 确认镜像与宿主机架构一致 |
### schema 初始化失败
```bash
docker compose logs mysql | grep -iE 'error' | head -30
```
| 原因 | 处理 |
| --- | --- |
| `MYSQL_APP_PASSWORD` 未设置,`04-users.sh` 退出 | 补上后清空 `data/mysql` 重建 |
| `MYSQL_ADMIN_PASSWORD` 未设置,`05-reset-passwords.sh` 退出 | 同上 |
| SQL 脚本语法问题 | 单独执行该脚本定位 |
::: warning 改脚本后必须清空数据卷
MySQL 只在 `data/mysql` 为空时执行 `schema/`,文件改了不会自动重跑:
```bash
docker compose down && sudo rm -rf ./data/mysql && docker compose up -d
```
:::
### 业务服务反复重启
```bash
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: connection refused` | MySQL 未就绪 | 等 MySQL healthy |
| `Access denied for user 'u_iotlcm'` | 应用账号口令与库内不一致 | 确认 `docker-compose.yml` 的 `MYSQL_APP_PASSWORD` 与初始化时一致 |
| `panic: unsupported provider xxx` | 通道模板与镜像版本不匹配 | 确认镜像版本与 schema 版本配套 |
## 功能类
### 登录后提示未授权 / 接口 401
**原因**:`JWT_SIGNING_KEY` 在服务间不一致。
确认 `admin-svr`、`openapi`、`app-server` 三份配置的 `jwt.signingKey` 都引用 `${JWT_SIGNING_KEY}` 且 `docker-compose.yml` 有值,然后重启:
```bash
docker compose restart admin-svr openapi app-server
```
### 登录成功但页面空白 / 菜单不显示
1. 浏览器 F12 看 Network 有无 4xx/5xx
2. 检查菜单数据:
```bash
docker compose exec mysql sh -c \
'mysql -uroot -p"$MYSQL_ROOT_PASSWORD" db_iotlcm -e "SELECT COUNT(*) FROM sys_menu WHERE status=0;"'
```
菜单为 0 说明种子数据未导入,需重建库。
3. 检查角色菜单关联:
```bash
docker compose exec mysql sh -c \
'mysql -uroot -p"$MYSQL_ROOT_PASSWORD" db_iotlcm -e "SELECT COUNT(*) FROM sys_role_menu;"'
```
### 卡信息页通道列空白 / 筛选无选项
**原因**:Mock 通道未插入。
```bash
docker compose exec mysql sh -c \
'mysql -uroot -p"$MYSQL_ROOT_PASSWORD" db_iotlcm -e "SELECT channel_id, channel_name FROM t_sim_channels;"'
```
为空则手工执行种子脚本:
```bash
docker compose exec -T mysql sh -c \
'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD" db_iotlcm' < schema/08-seed-mock-channel.sql
```
### 批次执行一直失败
按顺序排查:
1. **挡板是否启动**(无真实运营商时)
```bash
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`。
2. **worker-svr 是否连上 RabbitMQ**
```bash
docker compose logs worker-svr | grep -i 'rabbit\|amqp' | tail -20
```
3. **upstream-chan 是否能连到上游**
```bash
docker compose logs upstream-chan --tail=50
```
4. **是否被运营商限流**
检查 worker-svr 日志中的 `rate limit`、`429`、`12021`。核对 `batch.inbound.upstreamRateLimit` 的 QPS 是否超过上游配额。
### 历史流量查询无数据
**原因**:TDengine 未启动、未完成建表,或配置里的地址不对。
```bash
docker compose logs worker-svr | grep -i 'tdengine\|taos' | tail -20
docker compose logs tdengine-init | tail -20 # 建库建表是否成功
docker compose exec tdengine taos -s "show databases;"
```
常见原因与处理:
| 现象 | 原因 | 处理 |
| --- | --- | --- |
| `tdengine-init` 报 MISS | 建表失败 | 看该容器日志里的 `DB error`;改 `tdengine-init/init.sql` 后重跑 `docker compose up -d tdengine-init` |
| worker 日志报库表不存在 | 未执行建表 | 同上,确保 init 容器退出码为 0 |
| 连接超时 | 地址/端口不对 | 配置里应为 `ws(tdengine:6041)`,容器内用服务名而非 IP |
建表脚本全部带 `IF NOT EXISTS`,可重复执行。
### 短信发不出去
```bash
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:11190/healthz
docker compose logs sms --tail=50
```
| 报错 | 原因 |
| --- | --- |
| `InvalidAccessKeyId` | `docker-compose.yml` 中 AK 未填或错误 |
| `isv.SMS_SIGNATURE_ILLEGAL` | `signName` 与服务商审核签名不一致 |
| `isv.SMS_TEMPLATE_ILLEGAL` | 模板 ID 未审核通过 |
| `缺少 config.templateId` | 场景模板库未配置,调用方需自带 templateId |
### 图片上传失败 / 不显示
```bash
ls -la data/upload/
sudo chown -R 1000:1000 data/upload
docker compose restart admin-svr admin-ui
```
## 性能类
### CPU 被 worker-svr 打满
**原因**:定时任务开启全量同步,大量卡片并发查询上游。
1. 降低并发与限流:
```yaml
batch:
inbound:
upstreamConcurrency: 50 # 从 300 降低
upstreamBatchSize: 1
```
2. 演示 / 试用环境直接停用定时任务:
```bash
docker compose exec mysql sh -c \
'mysql -uroot -p"$MYSQL_ROOT_PASSWORD" db_iotlcm -e "UPDATE sys_job SET status=1;"'
```
种子数据中定时任务默认已全部停用(`status=1`)。
### 磁盘持续增长
```bash
du -sh data/* | sort -rh
```
| 目录 | 处理 |
| --- | --- |
| `data/logs` | 清理旧日志,见[升级与备份](operations) |
| `data/upload` | 检查异常大的上传文件 |
| `data/mysql` | 数据库增长正常,关注 binlog |
| `data/redis` | AOF 文件,正常 |
## 网络类
### 容器间无法互访
```bash
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:<端口>`
::: danger 不要直接把端口改成 0.0.0.0
这会把管理端、数据库等内部服务暴露到公网。
:::
## 求助时提供的信息
```bash
docker compose version
docker version --format '{{.Server.Version}}'
docker compose ps
docker compose logs --tail=200 <服务名>
df -h && free -h
```