跳到主要内容

技术问题排查

常见症状 / 错误及其解决方案。快速分类 → 详细解决流程。

容器模式(2026.05+)诊断资源
  • status.sh — 容器 + 端口 + API + app.properties 核心键的一行摘要
  • health.sh — 基于退出码的综合健康检查(适合 cron)
  • doctor.sh — 诊断打包 tarball(api / docker / systemd / 7 个组件日志 / 脱敏配置 / 主机指标) → 支持升级
  • /api/v1/system/health — 8 个组件的状态映射 + 503 分支(立即识别哪个组件处于 DOWN 状态)
  • 容器模式运维 — 故障应对 + 命令速查表

按症状索引​

症状可能原因
应用启动时卡住Cassandra 连接失败,DDL 应用失败
/api/v1/edge 响应为 started=falseCollector 初始化失败(驱动 / 缓存问题)
特定 OPC 出现 connection_status=DISCONNECTEDPLC 网络 / 认证 / 地址格式
所有 OPC 偶尔同时断开因 OPC 添加/修改导致 OPCUAServerManager 整体重启
MQTT 无法发布mqtt.enable=false 或 broker 认证失败
Sparkplug 主题未发布sparkplug.enable=false 或缺少 jar
画面加载缓慢opcList() N+1 查询 + sleep 累积
OPC 启动每次耗时 5 秒Thread.sleep 影响(Phase A1 目标)

启动 / 初始化​

Cassandra 连接失败​

Caused by: com.datastax.oss.driver.core.exceptions.NoHostAvailableException
检查项确认
Cassandra 运行中nodetool status
端口可达telnet <app.db.host> 9042
keyspace 存在cqlsh -u cassandra -p cassandra 后 DESCRIBE KEYSPACE pe;
app.db.* 与 oltp.cassandra.* 一致检查 app.properties 两侧条目

app.sql.path 的 resouces 拼写错误​

app.properties 的 app.sql.path = classpath:resouces/sql 的 resouces 虽然拼写有误,但由于目录也保持了相同的名称,因此可以正常工作。如果出现找不到 SQL 资源的错误,请确认 WEB-INF/resouces/sql/ 路径实际是否存在。


OPC / 驱动​

特定 OPC 无法连接​

协议初步检查
OPCUAopc_agent_port 可达,尝试 discovery=true,用户名/密码
Modbus TCP502 端口可达,holding-register:... 格式
MELSECMC 协议已启用,controller-type=Q_L 一致
S7rack/slot 一致,"PUT/GET" 已启用
LS若 NetUtils.isReachable 失败,怀疑 ICMP 被阻断,端口 2004
EIPrack/slot,端口 44818

优先参考各驱动页面中的"常见错误 + 解决方案"表。

LS-PLC Ping failed​

LS 驱动在连接前通过 ICMP ping 来检查可达性。如果公司网络阻断了 ICMP,即使 PLC 正常也会显示为失败。

解决方案:

  • 在防火墙中允许 ICMP
  • 或后续更改 LSDriver.connect() 中的 ping 检查为可选项(当前需要代码变更)

32位 / 64位值不一致​

大部分原因是 format 未指定。

协议错误模式 → 正确模式
LSD00600 + Integer(按 16 位读取) → D00600 + Integer + format=DW
Modbusholding-register:1(16 位) → holding-register:1:DINT
S7%DB1.DBW0 + Float → %DB1.DBD0 + format=REAL

32 位浮点值为 NaN / 异常大数​

字节序(endianness)问题。检查从站 / 主站的字节/字交换策略:

  • Modbus → 使用 :UDINT_LSWORD_FIRST 等 PLC4j 选项
  • 其他协议 → 使用计算公式进行后处理

传输(MQTT / Sparkplug)​

MQTT 无法发布​

# broker 도달 확인
MQTT_USER="${MQTT_USER:-edge}"
MQTT_PASSWORD="$(tr -d '\r\n' < /run/secrets/mqtt-password)"
mosquitto_pub -h <mqtt.server.host> -p 1883 -u "$MQTT_USER" -P "$MQTT_PASSWORD" -t /edge/point -m '{"test":1}'

检查清单:

  • mqtt.enable=true
  • mqtt.server.host/port/user/password 正确
  • broker 是否允许客户端发布的 ACL
  • catalina.out 中是否出现 MQTT connected 或重连日志

Sparkplug 主题不可见​

检查项方法
是否为 sparkplug.enable=true检查 properties + 需要重启
jar 是否在 lib 中ls WebContent/WEB-INF/lib/tahu-core*.jar
是否为同一 brokermqtt.server.* 与 SPB 是否相同
broker 的 SPB 主题 ACLspBv1.0/# 发布权限

NDEATH 被发布两次​

这是正常行为。正常终止时显式发布 +(由于也注册了 will)如果 broker 无法识别连接终止为 will-bypass,则 will 也可能被额外发布。在这种情况下,主机侧应实现为对相同 bdSeq 的 NDEATH 只处理一次。


性能 / 响应性​

OPC 启动/停止响应耗时 5 秒​

这是由于 ConnectService 的有意 Thread.sleep(保证 collector 预热)。

  • 临时规避:通过刷新页面确认轮询响应
  • 永久解决:应用 REFACTORING_PLAN.md Phase A1(去除 Thread.sleep / CountDownLatch)后的后续 PR

页面首次加载缓慢​

opcList() N+1 查询 + LastValueMap 查找分散可能导致额外 1~2 秒延迟。

  • 应用 Phase B1(IN 批量 select)和 B2(单一 facade)后预计改善

修改一个 OPC 时其他 OPC 也暂时中断​

这是因为 OPCUAServerManager.restart() 是整体重启(Phase A2 — 部分重载目标)。

紧急规避:在非运维时间进行 OPC 变更。


数据 / Cassandra​

tombstone 累积警告​

运维中批量删除 OPC 时,nodetool cfstats pe.app_tag 的 tombstone 指标可能暂时飙升。

  • 由于本网关的 OPC/标签数量通常 ≤ 1000,情况并不严重
  • 时序数据(TM_TAG_POINT)不属于本网关,而是 plantpulse-timeseries-engine 的职责

tag not found: <id>​

在 PUT /api/v1/tag/{tagId} 或读取时频繁发生。

原因:

  • tag_id 拼写错误
  • APP_TAG.xml 的 R03 属于 ALLOW FILTERING 查询,未指定 partition key。tag_id 必须准确。

确认:

cqlsh -u cassandra -p cassandra -k pe -e "SELECT tag_id FROM app_tag;"

写入值时出现 tag write not supported for opc_type=...​

除 HTTP 外的协议目前不支持写入。

  • 仅实现 HTTPDriver.bind()
  • 其他协议的写入需要 Sparkplug Phase 3(NCMD/DCMD)以及 SPI 扩展

安全 / 运维​

/api/* 未认证即可访问​

设计上以公司网络为前提(SecurityFilter 的 check-pattern 中不包含 /api/*)。外部暴露时,请在反向代理前端配置 mTLS / API Key / Basic 认证。

CSRF​

仅对 *_.do 模式应用 CSRF。v1 变更端点不在应用范围内。外部暴露时请一并考虑。


日志收集指南​

报告问题时,附带以下内容可以加快分析。

# 환경
curl -s http://localhost:8080/api/v1/edge

# OPC 상태
curl -s http://localhost:8080/api/v1/opc

# 시스템 메트릭
curl -s http://localhost:8080/api/v1/monitoring

# 최근 로그
tail -n 500 $CATALINA_HOME/logs/catalina.out

请对 app.properties 的密码进行脱敏后再附上。