docs: add detailed 32960 pipeline comments
This commit is contained in:
@@ -64,6 +64,7 @@ public final class MqttEndpointManager implements AutoCloseable {
|
||||
public void start() {
|
||||
for (MqttInboundProperties.Endpoint ep : props.getEndpoints()) {
|
||||
try {
|
||||
// 多 endpoint 互不影响:单个连接初始化失败会派发 operationalError,但不会阻止其他 endpoint。
|
||||
Mqtt3AsyncClient client = buildClient(ep);
|
||||
clients.add(client);
|
||||
connectAndSubscribe(client, ep);
|
||||
@@ -146,6 +147,7 @@ public final class MqttEndpointManager implements AutoCloseable {
|
||||
String externalDeviceId = firstNonBlank(parsed.deviceId(), parsed.vin());
|
||||
IdentityResolution identity = resolveIdentity(parsed);
|
||||
Map<String, String> meta = new HashMap<>(4);
|
||||
// metadata 同时保留外部设备号和内部 VIN,便于排查绑定表错误导致的车辆归属问题。
|
||||
meta.put("vin", identity.identity().vin());
|
||||
meta.put("externalVin", parsed.externalVin() == null ? "" : parsed.externalVin());
|
||||
meta.put("phone", parsed.phone() == null ? "" : parsed.phone());
|
||||
@@ -173,6 +175,7 @@ public final class MqttEndpointManager implements AutoCloseable {
|
||||
} catch (Exception e) {
|
||||
log.warn("mqtt endpoint [{}] message handling failed topic={} len={}",
|
||||
ep.getName(), topic, payload.length, e);
|
||||
// 单条消息异常也转成 RawFrame 错误事件,避免 MQTT 回调线程吞掉现场。
|
||||
publishMessageError(ep, topic, payload, e.getMessage() == null ? e.getClass().getSimpleName() : e.getMessage());
|
||||
}
|
||||
}
|
||||
@@ -215,6 +218,7 @@ public final class MqttEndpointManager implements AutoCloseable {
|
||||
}
|
||||
|
||||
private void publishOperationalError(MqttInboundProperties.Endpoint ep, String phase, String reason) {
|
||||
// 连接/订阅级别错误也进入 Dispatcher,这样监控和历史查询能看到接入端本身的问题。
|
||||
String endpointName = ep == null ? "" : ep.getName();
|
||||
String profile = ep == null ? "" : ep.getProfile();
|
||||
String topic = ep == null ? "" : ep.getTopic();
|
||||
|
||||
@@ -7,11 +7,16 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* MQTT 接入配置。支持多 endpoint(每个 endpoint 可对应一个车厂 / 一个 broker)。
|
||||
*
|
||||
* <p>这是 JSON/MQTT 厂商入口,不参与 GB32960 TCP 32960 端口接入;如果同一辆车同时存在
|
||||
* MQTT 和 32960 数据,需要在下游按 protocol/source 做归因。
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "lingniu.ingest.mqtt")
|
||||
public class MqttInboundProperties {
|
||||
|
||||
/** 总开关。关闭时不会创建任何 MQTT 客户端连接。 */
|
||||
private boolean enabled = false;
|
||||
/** 多 broker/多 topic 配置;每个 endpoint 独立重连、订阅并转成内部 VehicleEvent。 */
|
||||
private List<Endpoint> endpoints = new ArrayList<>();
|
||||
|
||||
public boolean isEnabled() { return enabled; }
|
||||
@@ -31,6 +36,7 @@ public class MqttInboundProperties {
|
||||
private String clientId;
|
||||
private String username;
|
||||
private String password;
|
||||
/** false 表示保留 broker 会话,重连后可继续接收离线期间的 QoS1/2 消息。 */
|
||||
private boolean cleanSession = false;
|
||||
private int keepAliveSeconds = 20;
|
||||
private int connectionTimeoutSeconds = 10;
|
||||
|
||||
@@ -116,6 +116,7 @@ public class XindaPushClient extends PushClient {
|
||||
String cmd = msg.getCmd();
|
||||
if (cmd == null) return;
|
||||
try {
|
||||
// 信达只把业务消息派发到 Dispatcher;登录/心跳/订阅 ACK 只影响连接状态和日志。
|
||||
switch (cmd) {
|
||||
case "8001" -> handleLoginAck(msg);
|
||||
case "8002" -> log.debug("[xinda-push] heartbeat ack");
|
||||
@@ -128,6 +129,7 @@ public class XindaPushClient extends PushClient {
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("[xinda-push] dispatch failed cmd={} json={}", cmd, msg.getJson(), e);
|
||||
// 推送回调异常也生成错误 RawFrame,保证原始 JSON 不丢。
|
||||
publishMessageError(msg, e.getMessage() == null ? e.getClass().getSimpleName() : e.getMessage());
|
||||
}
|
||||
}
|
||||
@@ -193,6 +195,7 @@ public class XindaPushClient extends PushClient {
|
||||
JSONObject identityFields = parsed.json();
|
||||
IdentityResolution identity = resolveIdentity(identityFields);
|
||||
Map<String, String> meta = new HashMap<>();
|
||||
// 保留外部字段和内部 VIN 的双轨元数据,方便定位绑定错误或第三方字段变更。
|
||||
meta.put("source", "xinda-push");
|
||||
meta.put("cmd", payload.command());
|
||||
meta.put("vin", identity.identity().vin());
|
||||
|
||||
@@ -41,10 +41,12 @@ public final class XindaPushEventMapper implements EventMapper<XindaPushMessage>
|
||||
try {
|
||||
json = parse(message.json());
|
||||
} catch (Exception e) {
|
||||
// JSON 解析失败不丢弃,转 passthrough 保留 rawJson,后续可通过历史库回查。
|
||||
return List.of(passthrough(message, new JSONObject(), true, false,
|
||||
e.getMessage() == null ? e.getClass().getSimpleName() : e.getMessage()));
|
||||
}
|
||||
if (json.getBooleanValue("operationalError")) {
|
||||
// 接入侧运行错误也统一作为 passthrough 事件进入管线,便于监控和审计。
|
||||
return List.of(passthrough(message, json, false, false));
|
||||
}
|
||||
return switch (message.command()) {
|
||||
|
||||
@@ -7,16 +7,21 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* 信达 Push 接入配置。所有敏感字段均可通过环境变量注入,彻底取代旧代码里的硬编码。
|
||||
*
|
||||
* <p>该入口属于第三方推送协议,与 GB32960 TCP 接收链路并列。生产排查 32960 时,
|
||||
* 应先确认本开关是否关闭,避免把信达推送事件误认为 32960 原始包。
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "lingniu.ingest.xinda-push")
|
||||
public class XindaPushProperties {
|
||||
|
||||
/** 总开关。关闭时不会向信达平台建连/订阅。 */
|
||||
private boolean enabled = false;
|
||||
private String host;
|
||||
private int port = 10100;
|
||||
private String username;
|
||||
private String password;
|
||||
private String clientDesc = "lingniu-ingest";
|
||||
/** 默认订阅常见定位/轨迹类消息,新增业务消息需要先在 mapper 中确认字段映射。 */
|
||||
private List<String> subscribeMsgIds = new ArrayList<>(List.of("0200", "0300", "0401"));
|
||||
/** 断线重连间隔(秒)。 */
|
||||
private int reconnectIntervalSec = 5;
|
||||
|
||||
Reference in New Issue
Block a user